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