xref: /llvm-project/llvm/test/Transforms/SCCP/range-and.ll (revision 0f4d9f9b71be8a95cd24534bf914fc9a6fb0ff30)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --verbose
2; RUN: opt -S -passes=sccp %s | FileCheck %s
3
4declare void @use(i1)
5
6define void @and_range_limit(i64 %a) {
7; CHECK-LABEL: @and_range_limit(
8; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
9; CHECK-NEXT:    [[C_0:%.*]] = icmp slt i64 [[R]], 15
10; CHECK-NEXT:    call void @use(i1 [[C_0]])
11; CHECK-NEXT:    call void @use(i1 true)
12; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i64 [[R]], 100
13; CHECK-NEXT:    call void @use(i1 [[C_2]])
14; CHECK-NEXT:    call void @use(i1 false)
15; CHECK-NEXT:    [[C_4:%.*]] = icmp ne i64 [[R]], 100
16; CHECK-NEXT:    call void @use(i1 [[C_4]])
17; CHECK-NEXT:    call void @use(i1 true)
18; CHECK-NEXT:    ret void
19;
20  %r = and i64 %a, 255
21  %c.0 = icmp slt i64 %r, 15
22  call void @use(i1 %c.0)
23  %c.1 = icmp slt i64 %r, 256
24  call void @use(i1 %c.1)
25  %c.2 = icmp eq i64 %r, 100
26  call void @use(i1 %c.2)
27  %c.3 = icmp eq i64 %r, 300
28  call void @use(i1 %c.3)
29  %c.4 = icmp ne i64 %r, 100
30  call void @use(i1 %c.4)
31  %c.5 = icmp ne i64 %r, 300
32  call void @use(i1 %c.5)
33  ret void
34}
35
36; Below are test cases for PR44949.
37
38; We can remove `%res = and i64 %p, 255`, because %r = 0 and we can eliminate
39; %p as well.
40define i64 @constant_and_undef(i1 %c1, i64 %a) {
41; CHECK-LABEL: @constant_and_undef(
42; CHECK-NEXT:  entry:
43; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
44; CHECK:       bb1:
45; CHECK-NEXT:    br label [[BB3:%.*]]
46; CHECK:       bb2:
47; CHECK-NEXT:    br label [[BB3]]
48; CHECK:       bb3:
49; CHECK-NEXT:    ret i64 0
50;
51entry:
52  br i1 %c1, label %bb1, label %bb2
53
54bb1:
55  br label %bb3
56
57bb2:
58  %r = and i64 %a, 0
59  br label %bb3
60
61bb3:
62  %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ]
63  %res = and i64 %p, 255
64  ret i64 %res
65}
66
67; Check that we go to overdefined when merging a constant range with undef. We
68; cannot remove '%res = and i64 %p, 255'.
69define i64 @constant_range_and_undef(i1 %cond, i64 %a) {
70; CHECK-LABEL: @constant_range_and_undef(
71; CHECK-NEXT:  entry:
72; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
73; CHECK:       bb1:
74; CHECK-NEXT:    br label [[BB3:%.*]]
75; CHECK:       bb2:
76; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
77; CHECK-NEXT:    br label [[BB3]]
78; CHECK:       bb3:
79; CHECK-NEXT:    [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ [[R]], [[BB2]] ]
80; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
81; CHECK-NEXT:    ret i64 [[RES]]
82;
83entry:
84  br i1 %cond, label %bb1, label %bb2
85
86bb1:
87  br label %bb3
88
89bb2:
90  %r = and i64 %a, 255
91  br label %bb3
92
93bb3:
94  %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ]
95  %res = and i64 %p, 255
96  ret i64 %res
97}
98
99; Same as @constant_range_and_undef, with the undef coming from the other
100; block.
101define i64 @constant_range_and_undef_switched_incoming(i1 %cond, i64 %a) {
102; CHECK-LABEL: @constant_range_and_undef_switched_incoming(
103; CHECK-NEXT:  entry:
104; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
105; CHECK:       bb1:
106; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
107; CHECK-NEXT:    br label [[BB3:%.*]]
108; CHECK:       bb2:
109; CHECK-NEXT:    br label [[BB3]]
110; CHECK:       bb3:
111; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ undef, [[BB2]] ]
112; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
113; CHECK-NEXT:    ret i64 [[RES]]
114;
115entry:
116  br i1 %cond, label %bb1, label %bb2
117
118bb1:
119  %r = and i64 %a, 255
120  br label %bb3
121
122bb2:
123  br label %bb3
124
125bb3:
126  %p = phi i64 [ %r, %bb1 ], [ undef, %bb2 ]
127  %res = and i64 %p, 255
128  ret i64 %res
129}
130
131define i64 @constant_range_and_255_100(i1 %cond, i64 %a) {
132; CHECK-LABEL: @constant_range_and_255_100(
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
135; CHECK:       bb1:
136; CHECK-NEXT:    [[R_1:%.*]] = and i64 [[A:%.*]], 100
137; CHECK-NEXT:    br label [[BB3:%.*]]
138; CHECK:       bb2:
139; CHECK-NEXT:    [[R_2:%.*]] = and i64 [[A]], 255
140; CHECK-NEXT:    br label [[BB3]]
141; CHECK:       bb3:
142; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R_1]], [[BB1]] ], [ [[R_2]], [[BB2]] ]
143; CHECK-NEXT:    [[P_AND:%.*]] = and i64 [[P]], 255
144; CHECK-NEXT:    call void @use(i1 true)
145; CHECK-NEXT:    ret i64 [[P_AND]]
146;
147entry:
148  br i1 %cond, label %bb1, label %bb2
149
150bb1:
151  %r.1 = and i64 %a, 100
152  br label %bb3
153
154bb2:
155  %r.2 = and i64 %a, 255
156  br label %bb3
157
158bb3:
159  %p = phi i64 [ %r.1, %bb1 ], [ %r.2, %bb2 ]
160  %p.and = and i64 %p, 255
161  %c = icmp ult i64 %p.and, 256
162  call void @use(i1 %c)
163  ret i64 %p.and
164}
165
166
167define i64 @constant_range_and_undef2(i1 %c1, i1 %c2, i64 %a) {
168; CHECK-LABEL: @constant_range_and_undef2(
169; CHECK-NEXT:  entry:
170; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
171; CHECK:       bb1:
172; CHECK-NEXT:    [[V1:%.*]] = add i64 undef, undef
173; CHECK-NEXT:    br label [[BB3:%.*]]
174; CHECK:       bb2:
175; CHECK-NEXT:    [[V2:%.*]] = and i64 [[A:%.*]], 255
176; CHECK-NEXT:    br label [[BB3]]
177; CHECK:       bb3:
178; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[V1]], [[BB1]] ], [ [[V2]], [[BB2]] ]
179; CHECK-NEXT:    br i1 [[C2:%.*]], label [[BB4:%.*]], label [[BB5:%.*]]
180; CHECK:       bb4:
181; CHECK-NEXT:    br label [[BB6:%.*]]
182; CHECK:       bb5:
183; CHECK-NEXT:    [[V3:%.*]] = and i64 [[A]], 255
184; CHECK-NEXT:    br label [[BB6]]
185; CHECK:       bb6:
186; CHECK-NEXT:    [[P2:%.*]] = phi i64 [ [[P]], [[BB4]] ], [ [[V3]], [[BB5]] ]
187; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P2]], 255
188; CHECK-NEXT:    ret i64 [[RES]]
189;
190entry:
191  br i1 %c1, label %bb1, label %bb2
192
193bb1:
194  %v1 = add i64 undef, undef
195  br label %bb3
196
197bb2:
198  %v2 = and i64 %a, 255
199  br label %bb3
200
201bb3:
202  %p = phi i64 [ %v1, %bb1 ], [ %v2, %bb2 ]
203  br i1 %c2, label %bb4, label %bb5
204
205bb4:
206  br label %bb6
207
208bb5:
209  %v3 = and i64 %a, 255
210  br label %bb6
211
212bb6:
213  %p2 = phi i64 [ %p, %bb4 ], [ %v3, %bb5 ]
214  %res = and i64 %p2, 255
215  ret i64 %res
216}
217
218define i1 @constant_range_and_undef_3(i1 %cond, i64 %a) {
219; CHECK-LABEL: @constant_range_and_undef_3(
220; CHECK-NEXT:  entry:
221; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
222; CHECK:       bb1:
223; CHECK-NEXT:    br label [[BB3:%.*]]
224; CHECK:       bb2:
225; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
226; CHECK-NEXT:    br label [[BB3]]
227; CHECK:       bb3:
228; CHECK-NEXT:    [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ [[R]], [[BB2]] ]
229; CHECK-NEXT:    ret i1 true
230;
231entry:
232  br i1 %cond, label %bb1, label %bb2
233
234bb1:
235  br label %bb3
236
237bb2:
238  %r = and i64 %a, 255
239  br label %bb3
240
241bb3:
242  %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ]
243  %c = icmp ult i64 %p, 256
244  ret i1 %c
245}
246
247define i1 @constant_range_and_undef_3_switched_incoming(i1 %cond, i64 %a) {
248; CHECK-LABEL: @constant_range_and_undef_3_switched_incoming(
249; CHECK-NEXT:  entry:
250; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
251; CHECK:       bb1:
252; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
253; CHECK-NEXT:    br label [[BB3:%.*]]
254; CHECK:       bb2:
255; CHECK-NEXT:    br label [[BB3]]
256; CHECK:       bb3:
257; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ undef, [[BB2]] ]
258; CHECK-NEXT:    ret i1 true
259;
260entry:
261  br i1 %cond, label %bb1, label %bb2
262
263bb1:
264  %r = and i64 %a, 255
265  br label %bb3
266
267bb2:
268  br label %bb3
269
270bb3:
271  %p = phi i64 [ %r, %bb1 ], [ undef, %bb2 ]
272  %c = icmp ult i64 %p, 256
273  ret i1 %c
274}
275
276; Same as @constant_range_and_undef, but with 3 incoming
277; values: undef, a constant and a constant range.
278define i64 @constant_range_and_undef_3_incoming_v1(i1 %c1, i1 %c2, i64 %a) {
279; CHECK-LABEL: @constant_range_and_undef_3_incoming_v1(
280; CHECK-NEXT:  entry:
281; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
282; CHECK:       bb1:
283; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
284; CHECK-NEXT:    br label [[BB4:%.*]]
285; CHECK:       bb2:
286; CHECK-NEXT:    br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]]
287; CHECK:       bb3:
288; CHECK-NEXT:    br label [[BB4]]
289; CHECK:       bb4:
290; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ 10, [[BB2]] ], [ undef, [[BB3]] ]
291; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
292; CHECK-NEXT:    ret i64 [[RES]]
293;
294entry:
295  br i1 %c1, label %bb1, label %bb2
296
297bb1:
298  %r = and i64 %a, 255
299  br label %bb4
300
301bb2:
302  br i1 %c2, label %bb3, label %bb4
303
304bb3:
305  br label %bb4
306
307bb4:
308  %p = phi i64 [ %r, %bb1 ], [ 10, %bb2], [ undef, %bb3 ]
309  %res = and i64 %p, 255
310  ret i64 %res
311}
312
313; Same as @constant_range_and_undef_3_incoming_v1, but with different order of
314; incoming values.
315define i64 @constant_range_and_undef_3_incoming_v2(i1 %c1, i1 %c2, i64 %a) {
316; CHECK-LABEL: @constant_range_and_undef_3_incoming_v2(
317; CHECK-NEXT:  entry:
318; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
319; CHECK:       bb1:
320; CHECK-NEXT:    br label [[BB4:%.*]]
321; CHECK:       bb2:
322; CHECK-NEXT:    br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]]
323; CHECK:       bb3:
324; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
325; CHECK-NEXT:    br label [[BB4]]
326; CHECK:       bb4:
327; CHECK-NEXT:    [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ 10, [[BB2]] ], [ [[R]], [[BB3]] ]
328; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
329; CHECK-NEXT:    ret i64 [[RES]]
330;
331entry:
332  br i1 %c1, label %bb1, label %bb2
333
334bb1:
335  br label %bb4
336
337bb2:
338  br i1 %c2, label %bb3, label %bb4
339
340bb3:
341  %r = and i64 %a, 255
342  br label %bb4
343
344bb4:
345  %p = phi i64 [ undef, %bb1 ], [ 10, %bb2], [ %r, %bb3 ]
346  %res = and i64 %p, 255
347  ret i64 %res
348}
349
350; Same as @constant_range_and_undef_3_incoming_v1, but with different order of
351; incoming values.
352define i64 @constant_range_and_undef_3_incoming_v3(i1 %c1, i1 %c2, i64 %a) {
353; CHECK-LABEL: @constant_range_and_undef_3_incoming_v3(
354; CHECK-NEXT:  entry:
355; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
356; CHECK:       bb1:
357; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
358; CHECK-NEXT:    br label [[BB4:%.*]]
359; CHECK:       bb2:
360; CHECK-NEXT:    br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4]]
361; CHECK:       bb3:
362; CHECK-NEXT:    br label [[BB4]]
363; CHECK:       bb4:
364; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ undef, [[BB2]] ], [ 10, [[BB3]] ]
365; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
366; CHECK-NEXT:    ret i64 [[RES]]
367;
368entry:
369  br i1 %c1, label %bb1, label %bb2
370
371bb1:
372  %r = and i64 %a, 255
373  br label %bb4
374
375bb2:
376  br i1 %c2, label %bb3, label %bb4
377
378bb3:
379  br label %bb4
380
381bb4:
382  %p = phi i64 [ %r, %bb1 ], [ undef, %bb2], [ 10, %bb3 ]
383  %res = and i64 %p, 255
384  ret i64 %res
385}
386
387
388define i64 @constant_range_and_phi_constant_undef(i1 %c1, i1 %c2, i64 %a) {
389; CHECK-LABEL: @constant_range_and_phi_constant_undef(
390; CHECK-NEXT:  entry:
391; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
392; CHECK:       bb1:
393; CHECK-NEXT:    [[R:%.*]] = and i64 [[A:%.*]], 255
394; CHECK-NEXT:    br label [[BB5:%.*]]
395; CHECK:       bb2:
396; CHECK-NEXT:    br i1 [[C2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
397; CHECK:       bb3:
398; CHECK-NEXT:    br label [[BB4]]
399; CHECK:       bb4:
400; CHECK-NEXT:    br label [[BB5]]
401; CHECK:       bb5:
402; CHECK-NEXT:    [[P:%.*]] = phi i64 [ [[R]], [[BB1]] ], [ 10, [[BB4]] ]
403; CHECK-NEXT:    [[RES:%.*]] = and i64 [[P]], 255
404; CHECK-NEXT:    ret i64 [[RES]]
405;
406entry:
407  br i1 %c1, label %bb1, label %bb2
408
409bb1:
410  %r = and i64 %a, 255
411  br label %bb5
412
413bb2:
414  br i1 %c2, label %bb3, label %bb4
415
416bb3:
417  br label %bb4
418
419bb4:
420  %p.1 = phi i64 [ 10, %bb2 ], [ undef, %bb3]
421  br label %bb5
422
423bb5:
424  %p = phi i64 [ %r, %bb1 ], [ %p.1, %bb4]
425  %res = and i64 %p, 255
426  ret i64 %res
427}
428