[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / merge-range-and-undef.ll
blob1d70932ee857b71d00f31f88fe64f463733b0031
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=correlated-propagation %s | FileCheck %s
4 ; Test case for PR44949.
6 declare void @use(i1)
8 ; We can remove `%res = and i64 %p, 255`, because %r = 0 and we can eliminate
9 ; %p as well.
10 define 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
24 entry:
25   br i1 %c1, label %bb1, label %bb2
27 bb1:
28   br label %bb3
30 bb2:
31   %r = and i64 %a, 0
32   br label %bb3
34 bb3:
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
44 ; Check that we go to overdefined when merging a constant range with undef. We
45 ; cannot remove '%res = and i64 %p, 255'.
46 define 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]]
64 entry:
65   br i1 %cond, label %bb1, label %bb2
67 bb1:
68   br label %bb3
70 bb2:
71   %r = and i64 %a, 255
72   br label %bb3
74 bb3:
75   %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ]
76   %res = and i64 %p, 255
77   br label %exit
79 exit: ; 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
87 define 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]]
116 entry:
117   br i1 %c1, label %bb1, label %bb2
119 bb1:
120   %v1 = add i64 undef, undef
121   br label %bb3
123 bb2:
124   %v2 = and i64 %a, 255
125   br label %bb3
127 bb3:
128   %p = phi i64 [ %v1, %bb1 ], [ %v2, %bb2 ]
129   br i1 %c2, label %bb4, label %bb5
131 bb4:
132   br label %bb6
134 bb5:
135   %v3 = and i64 %a, 255
136   br label %bb6
138 bb6:
139   %p2 = phi i64 [ %p, %bb4 ], [ %v3, %bb5 ]
140   %res = and i64 %p2, 255
141   br label %exit
143 exit: ; 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
151 define 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
168 entry:
169   br i1 %cond, label %bb1, label %bb2
171 bb1:
172   br label %bb3
174 bb2:
175   %r = and i64 %a, 255
176   br label %bb3
178 bb3:
179   %p = phi i64 [ undef, %bb1 ], [ %r, %bb2 ]
180   br label %exit
182 exit: ; 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
191 ; Same as @constant_range_and_undef, but with 3 incoming
192 ; values: undef, a constant and a constant range.
193 define 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]]
213 entry:
214   br i1 %c1, label %bb1, label %bb2
216 bb1:
217   %r = and i64 %a, 255
218   br label %bb4
220 bb2:
221   br i1 %c2, label %bb3, label %bb4
223 bb3:
224   br label %bb4
226 bb4:
227   %p = phi i64 [ %r, %bb1 ], [ 10, %bb2], [ undef, %bb3 ]
228   %res = and i64 %p, 255
229   br label %exit
231 exit: ; 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
239 ; Same as @constant_range_and_undef_3_incoming_v1, but with different order of
240 ; incoming values.
241 define 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]]
261 entry:
262   br i1 %c1, label %bb1, label %bb2
264 bb1:
265   br label %bb4
267 bb2:
268   br i1 %c2, label %bb3, label %bb4
270 bb3:
271   %r = and i64 %a, 255
272   br label %bb4
274 bb4:
275   %p = phi i64 [ undef, %bb1 ], [ 10, %bb2], [ %r, %bb3 ]
276   %res = and i64 %p, 255
277   br label %exit
279 exit: ; 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
287 ; Same as @constant_range_and_undef_3_incoming_v1, but with different order of
288 ; incoming values.
289 define 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]]
309 entry:
310   br i1 %c1, label %bb1, label %bb2
312 bb1:
313   %r = and i64 %a, 255
314   br label %bb4
316 bb2:
317   br i1 %c2, label %bb3, label %bb4
319 bb3:
320   br label %bb4
322 bb4:
323   %p = phi i64 [ %r, %bb1 ], [ undef, %bb2], [ 10, %bb3 ]
324   %res = and i64 %p, 255
325   br label %exit
327 exit: ; 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
335 define 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]]
356 entry:
357   br i1 %c1, label %bb1, label %bb2
359 bb1:
360   %r = and i64 %a, 255
361   br label %bb5
363 bb2:
364   br i1 %c2, label %bb3, label %bb4
366 bb3:
367   br label %bb4
369 bb4:
370   %p.1 = phi i64 [ 10, %bb2 ], [ undef, %bb3]
371   br label %bb5
373 bb5:
374   %p = phi i64 [ %r, %bb1 ], [ %p.1, %bb4]
375   %res = and i64 %p, 255
376   br label %exit
378 exit: ; 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
386 ; Test case for PR68381.
387 ; Because of `undef`, we can only delete the second `and` instruction.
388 define i32 @constant_range_and_undef_and(i1 %c0, i1 %c1, i8 %v1, i8 %v2) {
389 ; CHECK-LABEL: @constant_range_and_undef_and(
390 ; CHECK-NEXT:  start:
391 ; CHECK-NEXT:    br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
392 ; CHECK:       bb0:
393 ; CHECK-NEXT:    [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32
394 ; CHECK-NEXT:    br label [[BB1]]
395 ; CHECK:       bb1:
396 ; CHECK-NEXT:    [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]
397 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]
398 ; CHECK:       bb2:
399 ; CHECK-NEXT:    [[V2_I32:%.*]] = zext i8 [[V2:%.*]] to i32
400 ; CHECK-NEXT:    [[Y:%.*]] = or i32 [[X]], [[V2_I32]]
401 ; CHECK-NEXT:    [[Z:%.*]] = and i32 [[Y]], 255
402 ; CHECK-NEXT:    ret i32 [[Z]]
404 start:
405   br i1 %c0, label %bb0, label %bb1
407 bb0:
408   %v1_i32 = zext i8 %v1 to i32
409   br label %bb1
411 bb1:
412   %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]
413   br i1 %c1, label %bb0, label %bb2
415 bb2:
416   %v2_i32 = zext i8 %v2 to i32
417   %y = or i32 %x, %v2_i32
418   %z = and i32 %y, 255
419   %z1 = and i32 %z, 255
420   ret i32 %z1