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