Teach InstCombine about address spaces
[oota-llvm.git] / test / Transforms / InstCombine / load-cmp.ll
1 ; RUN: opt -instcombine -S < %s | FileCheck -check-prefix=NODL %s
2 ; RUN: opt -instcombine -S -default-data-layout="p:32:32:32-n8:16:32:64" < %s | FileCheck -check-prefix=P32 %s
3
4 @G16 = internal constant [10 x i16] [i16 35, i16 82, i16 69, i16 81, i16 85,
5                                      i16 73, i16 82, i16 69, i16 68, i16 0]
6 @GD = internal constant [6 x double]
7    [double -10.0, double 1.0, double 4.0, double 2.0, double -20.0, double -40.0]
8
9 %Foo = type { i32, i32, i32, i32 }
10
11 @GS = internal constant %Foo { i32 1, i32 4, i32 9, i32 14 }
12
13 @GStructArr = internal constant [4 x %Foo] [ %Foo { i32 1, i32 4, i32 9, i32 14 },
14                                              %Foo { i32 5, i32 4, i32 6, i32 11 },
15                                              %Foo { i32 6, i32 5, i32 9, i32 20 },
16                                              %Foo { i32 12, i32 3, i32 9, i32 8 } ]
17
18
19 define i1 @test1(i32 %X) {
20   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
21   %Q = load i16* %P
22   %R = icmp eq i16 %Q, 0
23   ret i1 %R
24 ; NODL-LABEL: @test1(
25 ; NODL-NEXT: %R = icmp eq i32 %X, 9
26 ; NODL-NEXT: ret i1 %R
27
28 ; P32-LABEL: @test1(
29 ; P32-NEXT: %R = icmp eq i32 %X, 9
30 ; P32-NEXT: ret i1 %R
31 }
32
33 define i1 @test1_noinbounds(i32 %X) {
34   %P = getelementptr [10 x i16]* @G16, i32 0, i32 %X
35   %Q = load i16* %P
36   %R = icmp eq i16 %Q, 0
37   ret i1 %R
38 ; NODL-LABEL: @test1_noinbounds(
39 ; NODL-NEXT: %P = getelementptr [10 x i16]* @G16, i32 0, i32 %X
40
41 ; P32-LABEL: @test1_noinbounds(
42 ; P32-NEXT: %R = icmp eq i32 %X, 9
43 ; P32-NEXT: ret i1 %R
44 }
45
46 define i1 @test1_noinbounds_i64(i64 %X) {
47   %P = getelementptr [10 x i16]* @G16, i64 0, i64 %X
48   %Q = load i16* %P
49   %R = icmp eq i16 %Q, 0
50   ret i1 %R
51 ; NODL-LABEL: @test1_noinbounds_i64(
52 ; NODL-NEXT: %P = getelementptr [10 x i16]* @G16, i64 0, i64 %X
53
54 ; P32-LABEL: @test1_noinbounds_i64(
55 ; P32: %R = icmp eq i32 %1, 9
56 ; P32-NEXT: ret i1 %R
57 }
58
59 define i1 @test2(i32 %X) {
60   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
61   %Q = load i16* %P
62   %R = icmp slt i16 %Q, 85
63   ret i1 %R
64 ; NODL-LABEL: @test2(
65 ; NODL-NEXT: %R = icmp ne i32 %X, 4
66 ; NODL-NEXT: ret i1 %R
67 }
68
69 define i1 @test3(i32 %X) {
70   %P = getelementptr inbounds [6 x double]* @GD, i32 0, i32 %X
71   %Q = load double* %P
72   %R = fcmp oeq double %Q, 1.0
73   ret i1 %R
74 ; NODL-LABEL: @test3(
75 ; NODL-NEXT: %R = icmp eq i32 %X, 1
76 ; NODL-NEXT: ret i1 %R
77
78 ; P32-LABEL: @test3(
79 ; P32-NEXT: %R = icmp eq i32 %X, 1
80 ; P32-NEXT: ret i1 %R
81
82 }
83
84 define i1 @test4(i32 %X) {
85   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
86   %Q = load i16* %P
87   %R = icmp sle i16 %Q, 73
88   ret i1 %R
89 ; NODL-LABEL: @test4(
90 ; NODL-NEXT: lshr i32 933, %X
91 ; NODL-NEXT: and i32 {{.*}}, 1
92 ; NODL-NEXT: %R = icmp ne i32 {{.*}}, 0
93 ; NODL-NEXT: ret i1 %R
94
95 ; P32-LABEL: @test4(
96 ; P32-NEXT: lshr i32 933, %X
97 ; P32-NEXT: and i32 {{.*}}, 1
98 ; P32-NEXT: %R = icmp ne i32 {{.*}}, 0
99 ; P32-NEXT: ret i1 %R
100 }
101
102 define i1 @test4_i16(i16 %X) {
103   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i16 %X
104   %Q = load i16* %P
105   %R = icmp sle i16 %Q, 73
106   ret i1 %R
107
108 ; NODL-LABEL: @test4_i16(
109 ; NODL-NEXT: lshr i16 933, %X
110 ; NODL-NEXT: and i16 {{.*}}, 1
111 ; NODL-NEXT: %R = icmp ne i16 {{.*}}, 0
112 ; NODL-NEXT: ret i1 %R
113
114 ; P32-LABEL: @test4_i16(
115 ; P32-NEXT: sext i16 %X to i32
116 ; P32-NEXT: lshr i32 933, %1
117 ; P32-NEXT: and i32 {{.*}}, 1
118 ; P32-NEXT: %R = icmp ne i32 {{.*}}, 0
119 ; P32-NEXT: ret i1 %R
120 }
121
122 define i1 @test5(i32 %X) {
123   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
124   %Q = load i16* %P
125   %R = icmp eq i16 %Q, 69
126   ret i1 %R
127 ; NODL-LABEL: @test5(
128 ; NODL-NEXT: icmp eq i32 %X, 2
129 ; NODL-NEXT: icmp eq i32 %X, 7
130 ; NODL-NEXT: %R = or i1
131 ; NODL-NEXT: ret i1 %R
132
133 ; P32-LABEL: @test5(
134 ; P32-NEXT: icmp eq i32 %X, 2
135 ; P32-NEXT: icmp eq i32 %X, 7
136 ; P32-NEXT: %R = or i1
137 ; P32-NEXT: ret i1 %R
138 }
139
140 define i1 @test6(i32 %X) {
141   %P = getelementptr inbounds [6 x double]* @GD, i32 0, i32 %X
142   %Q = load double* %P
143   %R = fcmp ogt double %Q, 0.0
144   ret i1 %R
145 ; NODL-LABEL: @test6(
146 ; NODL-NEXT: add i32 %X, -1
147 ; NODL-NEXT: %R = icmp ult i32 {{.*}}, 3
148 ; NODL-NEXT: ret i1 %R
149
150 ; P32-LABEL: @test6(
151 ; P32-NEXT: add i32 %X, -1
152 ; P32-NEXT: %R = icmp ult i32 {{.*}}, 3
153 ; P32-NEXT: ret i1 %R
154 }
155
156 define i1 @test7(i32 %X) {
157   %P = getelementptr inbounds [6 x double]* @GD, i32 0, i32 %X
158   %Q = load double* %P
159   %R = fcmp olt double %Q, 0.0
160   ret i1 %R
161 ; NODL-LABEL: @test7(
162 ; NODL-NEXT: add i32 %X, -1
163 ; NODL-NEXT: %R = icmp ugt i32 {{.*}}, 2
164 ; NODL-NEXT: ret i1 %R
165
166 ; P32-LABEL: @test7(
167 ; P32-NEXT: add i32 %X, -1
168 ; P32-NEXT: %R = icmp ugt i32 {{.*}}, 2
169 ; P32-NEXT: ret i1 %R
170 }
171
172 define i1 @test8(i32 %X) {
173   %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
174   %Q = load i16* %P
175   %R = and i16 %Q, 3
176   %S = icmp eq i16 %R, 0
177   ret i1 %S
178 ; NODL-LABEL: @test8(
179 ; NODL-NEXT: and i32 %X, -2
180 ; NODL-NEXT: icmp eq i32 {{.*}}, 8
181 ; NODL-NEXT: ret i1
182
183 ; P32-LABEL: @test8(
184 ; P32-NEXT: and i32 %X, -2
185 ; P32-NEXT: icmp eq i32 {{.*}}, 8
186 ; P32-NEXT: ret i1
187 }
188
189 @GA = internal constant [4 x { i32, i32 } ] [
190   { i32, i32 } { i32 1, i32 0 },
191   { i32, i32 } { i32 2, i32 1 },
192   { i32, i32 } { i32 3, i32 1 },
193   { i32, i32 } { i32 4, i32 0 }
194 ]
195
196 define i1 @test9(i32 %X) {
197   %P = getelementptr inbounds [4 x { i32, i32 } ]* @GA, i32 0, i32 %X, i32 1
198   %Q = load i32* %P
199   %R = icmp eq i32 %Q, 1
200   ret i1 %R
201 ; NODL-LABEL: @test9(
202 ; NODL-NEXT: add i32 %X, -1
203 ; NODL-NEXT: icmp ult i32 {{.*}}, 2
204 ; NODL-NEXT: ret i1
205
206 ; P32-LABEL: @test9(
207 ; P32-NEXT: add i32 %X, -1
208 ; P32-NEXT: icmp ult i32 {{.*}}, 2
209 ; P32-NEXT: ret i1
210 }
211
212 define i1 @test10_struct(i32 %x) {
213 ; NODL-LABEL: @test10_struct(
214 ; NODL: getelementptr inbounds %Foo* @GS, i32 %x, i32 0
215
216 ; P32-LABEL: @test10_struct(
217 ; P32: getelementptr inbounds %Foo* @GS, i32 %x, i32 0
218   %p = getelementptr inbounds %Foo* @GS, i32 %x, i32 0
219   %q = load i32* %p
220   %r = icmp eq i32 %q, 9
221   ret i1 %r
222 }
223
224 define i1 @test10_struct_noinbounds(i32 %x) {
225 ; NODL-LABEL: @test10_struct_noinbounds(
226 ; NODL: getelementptr %Foo* @GS, i32 %x, i32 0
227
228 ; P32-LABEL: @test10_struct_noinbounds(
229 ; P32: getelementptr %Foo* @GS, i32 %x, i32 0
230   %p = getelementptr %Foo* @GS, i32 %x, i32 0
231   %q = load i32* %p
232   %r = icmp eq i32 %q, 9
233   ret i1 %r
234 }
235
236 ; Test that the GEP indices are converted before we ever get here
237 ; Index < ptr size
238 define i1 @test10_struct_i16(i16 %x){
239 ; NODL-LABEL: @test10_struct_i16(
240 ; NODL: getelementptr inbounds %Foo* @GS, i16 %x, i32 0
241
242 ; P32-LABEL: @test10_struct_i16(
243 ; P32: %1 = sext i16 %x to i32
244 ; P32: getelementptr inbounds %Foo* @GS, i32 %1, i32 0
245   %p = getelementptr inbounds %Foo* @GS, i16 %x, i32 0
246   %q = load i32* %p
247   %r = icmp eq i32 %q, 0
248   ret i1 %r
249 }
250
251 ; Test that the GEP indices are converted before we ever get here
252 ; Index > ptr size
253 define i1 @test10_struct_i64(i64 %x){
254 ; NODL-LABEL: @test10_struct_i64(
255 ; NODL: getelementptr inbounds %Foo* @GS, i64 %x, i32 0
256
257 ; P32-LABEL: @test10_struct_i64(
258 ; P32: %1 = trunc i64 %x to i32
259 ; P32: getelementptr inbounds %Foo* @GS, i32 %1, i32 0
260   %p = getelementptr inbounds %Foo* @GS, i64 %x, i32 0
261   %q = load i32* %p
262   %r = icmp eq i32 %q, 0
263   ret i1 %r
264 }
265
266 define i1 @test10_struct_noinbounds_i16(i16 %x) {
267 ; NODL-LABEL: @test10_struct_noinbounds_i16(
268 ; NODL: getelementptr %Foo* @GS, i16 %x, i32 0
269
270 ; P32-LABEL: @test10_struct_noinbounds_i16(
271 ; P32: %1 = sext i16 %x to i32
272 ; P32: getelementptr %Foo* @GS, i32 %1, i32 0
273   %p = getelementptr %Foo* @GS, i16 %x, i32 0
274   %q = load i32* %p
275   %r = icmp eq i32 %q, 0
276   ret i1 %r
277 }
278
279 define i1 @test10_struct_arr(i32 %x) {
280 ; NODL-LABEL: @test10_struct_arr(
281 ; NODL-NEXT: %r = icmp ne i32 %x, 1
282 ; NODL-NEXT: ret i1 %r
283
284 ; P32-LABEL: @test10_struct_arr(
285 ; P32-NEXT: %r = icmp ne i32 %x, 1
286 ; P32-NEXT: ret i1 %r
287   %p = getelementptr inbounds [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2
288   %q = load i32* %p
289   %r = icmp eq i32 %q, 9
290   ret i1 %r
291 }
292
293 define i1 @test10_struct_arr_noinbounds(i32 %x) {
294 ; NODL-LABEL: @test10_struct_arr_noinbounds(
295 ; NODL-NEXT  %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2
296
297 ; P32-LABEL: @test10_struct_arr_noinbounds(
298 ; P32-NEXT  %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2
299   %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2
300   %q = load i32* %p
301   %r = icmp eq i32 %q, 9
302   ret i1 %r
303 }
304
305 define i1 @test10_struct_arr_i16(i16 %x) {
306 ; NODL-LABEL: @test10_struct_arr_i16(
307 ; NODL-NEXT: %r = icmp ne i16 %x, 1
308 ; NODL-NEXT: ret i1 %r
309
310 ; P32-LABEL: @test10_struct_arr_i16(
311 ; P32-NEXT: %r = icmp ne i16 %x, 1
312 ; P32-NEXT: ret i1 %r
313   %p = getelementptr inbounds [4 x %Foo]* @GStructArr, i16 0, i16 %x, i32 2
314   %q = load i32* %p
315   %r = icmp eq i32 %q, 9
316   ret i1 %r
317 }
318
319 define i1 @test10_struct_arr_i64(i64 %x) {
320 ; NODL-LABEL: @test10_struct_arr_i64(
321 ; NODL-NEXT: %r = icmp ne i64 %x, 1
322 ; NODL-NEXT: ret i1 %r
323
324 ; P32-LABEL: @test10_struct_arr_i64(
325 ; P32-NEXT: trunc i64 %x to i32
326 ; P32-NEXT: %r = icmp ne i32 %1, 1
327 ; P32-NEXT: ret i1 %r
328   %p = getelementptr inbounds [4 x %Foo]* @GStructArr, i64 0, i64 %x, i32 2
329   %q = load i32* %p
330   %r = icmp eq i32 %q, 9
331   ret i1 %r
332 }
333
334 define i1 @test10_struct_arr_noinbounds_i16(i16 %x) {
335 ; NODL-LABEL: @test10_struct_arr_noinbounds_i16(
336 ; NODL-NEXT:  %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i16 %x, i32 2
337
338 ; P32-LABEL: @test10_struct_arr_noinbounds_i16(
339 ; P32-NEXT: %r = icmp ne i16 %x, 1
340   %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i16 %x, i32 2
341   %q = load i32* %p
342   %r = icmp eq i32 %q, 9
343   ret i1 %r
344 }
345
346 define i1 @test10_struct_arr_noinbounds_i64(i64 %x) {
347 ; FIXME: Should be no trunc?
348 ; NODL-LABEL: @test10_struct_arr_noinbounds_i64(
349 ; NODL-NEXT:  %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i64 %x, i32 2
350
351 ; P32-LABEL: @test10_struct_arr_noinbounds_i64(
352 ; P32: %r = icmp ne i32 %1, 1
353 ; P32-NEXT: ret i1 %r
354   %p = getelementptr [4 x %Foo]* @GStructArr, i32 0, i64 %x, i32 2
355   %q = load i32* %p
356   %r = icmp eq i32 %q, 9
357   ret i1 %r
358 }