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