1; RUN: opt < %s -bounds-checking -S | FileCheck %s
2target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
3
4@.str = private constant [8 x i8] c"abcdefg\00"   ; <[8 x i8]*>
5
6@.str_as1 = private addrspace(1) constant [8 x i8] c"abcdefg\00"   ; <[8 x i8] addrspace(1)*>
7
8
9declare noalias i8* @malloc(i64) nounwind
10declare noalias i8* @calloc(i64, i64) nounwind
11declare noalias i8* @realloc(i8* nocapture, i64) nounwind
12
13; CHECK: @f1
14define void @f1() nounwind {
15  %1 = tail call i8* @malloc(i64 32)
16  %2 = bitcast i8* %1 to i32*
17  %idx = getelementptr inbounds i32* %2, i64 2
18; CHECK-NOT: trap
19  store i32 3, i32* %idx, align 4
20  ret void
21}
22
23; CHECK: @f2
24define void @f2() nounwind {
25  %1 = tail call i8* @malloc(i64 32)
26  %2 = bitcast i8* %1 to i32*
27  %idx = getelementptr inbounds i32* %2, i64 8
28; CHECK: trap
29  store i32 3, i32* %idx, align 4
30  ret void
31}
32
33; CHECK: @f3
34define void @f3(i64 %x) nounwind {
35  %1 = tail call i8* @calloc(i64 4, i64 %x)
36  %2 = bitcast i8* %1 to i32*
37  %idx = getelementptr inbounds i32* %2, i64 8
38; CHECK: mul i64 4, %
39; CHECK: sub i64 {{.*}}, 32
40; CHECK-NEXT: icmp ult i64 {{.*}}, 32
41; CHECK-NEXT: icmp ult i64 {{.*}}, 4
42; CHECK-NEXT: or i1
43; CHECK: trap
44  store i32 3, i32* %idx, align 4
45  ret void
46}
47
48; CHECK: @f4
49define void @f4(i64 %x) nounwind {
50  %1 = tail call i8* @realloc(i8* null, i64 %x) nounwind
51  %2 = bitcast i8* %1 to i32*
52  %idx = getelementptr inbounds i32* %2, i64 8
53; CHECK: trap
54  %3 = load i32* %idx, align 4
55  ret void
56}
57
58; CHECK: @f5
59define void @f5(i64 %x) nounwind {
60  %idx = getelementptr inbounds [8 x i8]* @.str, i64 0, i64 %x
61; CHECK: trap
62  %1 = load i8* %idx, align 4
63  ret void
64}
65
66define void @f5_as1(i64 %x) nounwind {
67; CHECK: @f5_as1
68  %idx = getelementptr inbounds [8 x i8] addrspace(1)* @.str_as1, i64 0, i64 %x
69  ; CHECK: sub i16
70  ; CHECK icmp ult i16
71; CHECK: trap
72  %1 = load i8 addrspace(1)* %idx, align 4
73  ret void
74}
75
76; CHECK: @f6
77define void @f6(i64 %x) nounwind {
78  %1 = alloca i128
79; CHECK-NOT: trap
80  %2 = load i128* %1, align 4
81  ret void
82}
83
84; CHECK: @f7
85define void @f7(i64 %x) nounwind {
86  %1 = alloca i128, i64 %x
87; CHECK: mul i64 16,
88; CHECK: trap
89  %2 = load i128* %1, align 4
90  ret void
91}
92
93; CHECK: @f8
94define void @f8() nounwind {
95  %1 = alloca i128
96  %2 = alloca i128
97  %3 = select i1 undef, i128* %1, i128* %2
98; CHECK-NOT: trap
99  %4 = load i128* %3, align 4
100  ret void
101}
102
103; CHECK: @f9
104define void @f9(i128* %arg) nounwind {
105  %1 = alloca i128
106  %2 = select i1 undef, i128* %arg, i128* %1
107; CHECK-NOT: trap
108  %3 = load i128* %2, align 4
109  ret void
110}
111
112; CHECK: @f10
113define void @f10(i64 %x, i64 %y) nounwind {
114  %1 = alloca i128, i64 %x
115  %2 = alloca i128, i64 %y
116  %3 = select i1 undef, i128* %1, i128* %2
117; CHECK: select
118; CHECK: select
119; CHECK: trap
120  %4 = load i128* %3, align 4
121  ret void
122}
123
124; CHECK: @f11
125define void @f11(i128* byval %x) nounwind {
126  %1 = bitcast i128* %x to i8*
127  %2 = getelementptr inbounds i8* %1, i64 16
128; CHECK: br label
129  %3 = load i8* %2, align 4
130  ret void
131}
132
133; CHECK: @f11_as1
134define void @f11_as1(i128 addrspace(1)* byval %x) nounwind {
135  %1 = bitcast i128 addrspace(1)* %x to i8 addrspace(1)*
136  %2 = getelementptr inbounds i8 addrspace(1)* %1, i16 16
137; CHECK: br label
138  %3 = load i8 addrspace(1)* %2, align 4
139  ret void
140}
141
142; CHECK: @f12
143define i64 @f12(i64 %x, i64 %y) nounwind {
144  %1 = tail call i8* @calloc(i64 1, i64 %x)
145; CHECK: mul i64 %y, 8
146  %2 = bitcast i8* %1 to i64*
147  %3 = getelementptr inbounds i64* %2, i64 %y
148  %4 = load i64* %3, align 8
149  ret i64 %4
150}
151
152; PR17402
153; CHECK-LABEL: @f13
154define void @f13() nounwind {
155entry:
156  br label %alive
157
158dead:
159  ; Self-refential GEPs can occur in dead code.
160  %incdec.ptr = getelementptr inbounds i32* %incdec.ptr, i64 1
161  ; CHECK: %incdec.ptr = getelementptr inbounds i32* %incdec.ptr
162  %l = load i32* %incdec.ptr
163  br label %alive
164
165alive:
166  ret void
167}
168