[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / Transforms / Attributor / potential.ll
blob11652f0f7b71ac3cee0caefab4b922c72d22db9e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
5 ; Test for multiple potential values
7 ; potential-test 1
8 ; bool iszero(int c) { return c == 0; }
9 ; bool potential_test1(bool c) { return iszero(c ? 1 : -1); }
11 define internal i1 @iszero1(i32 %c) {
12 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
13 ; CGSCC-LABEL: define {{[^@]+}}@iszero1
14 ; CGSCC-SAME: () #[[ATTR0:[0-9]+]] {
15 ; CGSCC-NEXT:    ret i1 false
17   %cmp = icmp eq i32 %c, 0
18   ret i1 %cmp
21 define i1 @potential_test1(i1 %c) {
22 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
23 ; TUNIT-LABEL: define {{[^@]+}}@potential_test1
24 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
25 ; TUNIT-NEXT:    ret i1 false
27 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
28 ; CGSCC-LABEL: define {{[^@]+}}@potential_test1
29 ; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
30 ; CGSCC-NEXT:    [[RET:%.*]] = call noundef i1 @iszero1() #[[ATTR2:[0-9]+]]
31 ; CGSCC-NEXT:    ret i1 [[RET]]
33   %arg = select i1 %c, i32 -1, i32 1
34   %ret = call i1 @iszero1(i32 %arg)
35   ret i1 %ret
39 ; potential-test 2
41 ; potential values of argument of iszero are {1,-1}
42 ; potential value of returned value of iszero is 0
44 ; int call_with_two_values(int x) { return iszero(x) + iszero(-x); }
45 ; int potential_test2(int x) { return call_with_two_values(1) + call_with_two_values(-1); }
47 define internal i32 @iszero2(i32 %c) {
48 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
49 ; CGSCC-LABEL: define {{[^@]+}}@iszero2
50 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
51 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
52 ; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
53 ; CGSCC-NEXT:    ret i32 [[RET]]
55   %cmp = icmp eq i32 %c, 0
56   %ret = zext i1 %cmp to i32
57   ret i32 %ret
60 define internal i32 @call_with_two_values(i32 %c) {
61 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
62 ; CGSCC-LABEL: define {{[^@]+}}@call_with_two_values
63 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
64 ; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR2]]
65 ; CGSCC-NEXT:    [[MINUSC:%.*]] = sub i32 0, [[C]]
66 ; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @iszero2(i32 noundef [[MINUSC]]) #[[ATTR2]]
67 ; CGSCC-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
68 ; CGSCC-NEXT:    ret i32 [[RET]]
70   %csret1 = call i32 @iszero2(i32 %c)
71   %minusc = sub i32 0, %c
72   %csret2 = call i32 @iszero2(i32 %minusc)
73   %ret = add i32 %csret1, %csret2
74   ret i32 %ret
77 define i32 @potential_test2(i1 %c) {
78 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
79 ; TUNIT-LABEL: define {{[^@]+}}@potential_test2
80 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
81 ; TUNIT-NEXT:    ret i32 0
83 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
84 ; CGSCC-LABEL: define {{[^@]+}}@potential_test2
85 ; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
86 ; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR2]]
87 ; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR2]]
88 ; CGSCC-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
89 ; CGSCC-NEXT:    ret i32 [[RET]]
91   %csret1 = call i32 @call_with_two_values(i32 1)
92   %csret2 = call i32 @call_with_two_values(i32 -1)
93   %ret = add i32 %csret1, %csret2
94   ret i32 %ret
98 ; potential-test 3
100 ; potential values of returned value of f are {0,1}
101 ; potential values of argument of g are {0,1}
102 ; potential value of returned value of g is 1
103 ; then returned value of g can be simplified
105 ; int zero_or_one(int c) { return c < 2; }
106 ; int potential_test3() { return zero_or_one(iszero(0))+zero_or_one(iszero(1)); }
108 define internal i32 @iszero3(i32 %c) {
109 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
110 ; CGSCC-LABEL: define {{[^@]+}}@iszero3
111 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
112 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
113 ; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
114 ; CGSCC-NEXT:    ret i32 [[RET]]
116   %cmp = icmp eq i32 %c, 0
117   %ret = zext i1 %cmp to i32
118   ret i32 %ret
121 define internal i32 @less_than_two(i32 %c) {
122 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
123 ; CGSCC-LABEL: define {{[^@]+}}@less_than_two
124 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
125 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 2
126 ; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
127 ; CGSCC-NEXT:    ret i32 [[RET]]
129   %cmp = icmp slt i32 %c, 2
130   %ret = zext i1 %cmp to i32
131   ret i32 %ret
134 define i32 @potential_test3() {
135 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
136 ; TUNIT-LABEL: define {{[^@]+}}@potential_test3
137 ; TUNIT-SAME: () #[[ATTR0]] {
138 ; TUNIT-NEXT:    ret i32 2
140 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
141 ; CGSCC-LABEL: define {{[^@]+}}@potential_test3
142 ; CGSCC-SAME: () #[[ATTR1]] {
143 ; CGSCC-NEXT:    [[CMP1:%.*]] = call i32 @iszero3(i32 noundef 0) #[[ATTR2]]
144 ; CGSCC-NEXT:    [[TRUE1:%.*]] = call i32 @less_than_two(i32 noundef [[CMP1]]) #[[ATTR2]]
145 ; CGSCC-NEXT:    [[CMP2:%.*]] = call i32 @iszero3(i32 noundef 1) #[[ATTR2]]
146 ; CGSCC-NEXT:    [[TRUE2:%.*]] = call i32 @less_than_two(i32 noundef [[CMP2]]) #[[ATTR2]]
147 ; CGSCC-NEXT:    [[RET:%.*]] = add i32 [[TRUE1]], [[TRUE2]]
148 ; CGSCC-NEXT:    ret i32 [[RET]]
150   %cmp1 = call i32 @iszero3(i32 0)
151   %true1 = call i32 @less_than_two(i32 %cmp1)
152   %cmp2 = call i32 @iszero3(i32 1)
153   %true2 = call i32 @less_than_two(i32 %cmp2)
154   %ret = add i32 %true1, %true2
155   ret i32 %ret
159 ; potential-test 4,5
161 ; simplified
162 ; int potential_test4(int c) { return return1or3(c) == 2; }
163 ; int potential_test5(int c) { return return1or3(c) == return2or4(c); }
165 ; not simplified
166 ; int potential_test6(int c) { return return1or3(c) == 3; }
167 ; int potential_test7(int c) { return return1or3(c) == return3or4(c); }
169 define i32 @potential_test4(i32 %c) {
170 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
171 ; TUNIT-LABEL: define {{[^@]+}}@potential_test4
172 ; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
173 ; TUNIT-NEXT:    ret i32 0
175 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
176 ; CGSCC-LABEL: define {{[^@]+}}@potential_test4
177 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
178 ; CGSCC-NEXT:    [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
179 ; CGSCC-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2
180 ; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
181 ; CGSCC-NEXT:    ret i32 [[RET]]
183   %csret = call i32 @return1or3(i32 %c)
184   %false = icmp eq i32 %csret, 2
185   %ret = zext i1 %false to i32
186   ret i32 %ret
189 define i32 @potential_test5(i32 %c) {
190 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
191 ; TUNIT-LABEL: define {{[^@]+}}@potential_test5
192 ; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
193 ; TUNIT-NEXT:    ret i32 0
195 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
196 ; CGSCC-LABEL: define {{[^@]+}}@potential_test5
197 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
198 ; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
199 ; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR2]]
200 ; CGSCC-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
201 ; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
202 ; CGSCC-NEXT:    ret i32 [[RET]]
204   %csret1 = call i32 @return1or3(i32 %c)
205   %csret2 = call i32 @return2or4(i32 %c)
206   %false = icmp eq i32 %csret1, %csret2
207   %ret = zext i1 %false to i32
208   ret i32 %ret
211 define i1 @potential_test6(i32 %c) {
212 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
213 ; TUNIT-LABEL: define {{[^@]+}}@potential_test6
214 ; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
215 ; TUNIT-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1:[0-9]+]]
216 ; TUNIT-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
217 ; TUNIT-NEXT:    ret i1 [[RET]]
219 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
220 ; CGSCC-LABEL: define {{[^@]+}}@potential_test6
221 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
222 ; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
223 ; CGSCC-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
224 ; CGSCC-NEXT:    ret i1 [[RET]]
226   %csret1 = call i32 @return1or3(i32 %c)
227   %ret = icmp eq i32 %csret1, 3
228   ret i1 %ret
231 define i1 @potential_test7(i32 %c) {
232 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
233 ; TUNIT-LABEL: define {{[^@]+}}@potential_test7
234 ; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
235 ; TUNIT-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]]
236 ; TUNIT-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]]
237 ; TUNIT-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
238 ; TUNIT-NEXT:    ret i1 [[RET]]
240 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
241 ; CGSCC-LABEL: define {{[^@]+}}@potential_test7
242 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
243 ; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
244 ; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]]
245 ; CGSCC-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
246 ; CGSCC-NEXT:    ret i1 [[RET]]
248   %csret1 = call i32 @return1or3(i32 %c)
249   %csret2 = call i32 @return3or4(i32 %c)
250   %ret = icmp eq i32 %csret1, %csret2
251   ret i1 %ret
254 define internal i32 @return1or3(i32 %c) {
255 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
256 ; CHECK-LABEL: define {{[^@]+}}@return1or3
257 ; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
258 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
259 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 1, i32 3
260 ; CHECK-NEXT:    ret i32 [[RET]]
262   %cmp = icmp eq i32 %c, 0
263   %ret = select i1 %cmp, i32 1, i32 3
264   ret i32 %ret
267 define internal i32 @return2or4(i32 %c) {
268 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
269 ; CGSCC-LABEL: define {{[^@]+}}@return2or4
270 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
271 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
272 ; CGSCC-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 2, i32 4
273 ; CGSCC-NEXT:    ret i32 [[RET]]
275   %cmp = icmp eq i32 %c, 0
276   %ret = select i1 %cmp, i32 2, i32 4
277   ret i32 %ret
280 define internal i32 @return3or4(i32 %c) {
281 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
282 ; CHECK-LABEL: define {{[^@]+}}@return3or4
283 ; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
284 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
285 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 3, i32 4
286 ; CHECK-NEXT:    ret i32 [[RET]]
288   %cmp = icmp eq i32 %c, 0
289   %ret = select i1 %cmp, i32 3, i32 4
290   ret i32 %ret
293 ; potential-test 8
295 ; propagate argument to callsite argument
297 define internal i1 @cmp_with_four(i32 %c) {
298 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
299 ; CGSCC-LABEL: define {{[^@]+}}@cmp_with_four
300 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
301 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 4
302 ; CGSCC-NEXT:    ret i1 [[CMP]]
304   %cmp = icmp eq i32 %c, 4
305   ret i1 %cmp
308 define internal i1 @wrapper(i32 %c) {
309 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
310 ; CGSCC-LABEL: define {{[^@]+}}@wrapper
311 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
312 ; CGSCC-NEXT:    [[RET:%.*]] = call i1 @cmp_with_four(i32 noundef [[C]]) #[[ATTR2]]
313 ; CGSCC-NEXT:    ret i1 [[RET]]
315   %ret = call i1 @cmp_with_four(i32 %c)
316   ret i1 %ret
319 define i1 @potential_test8() {
320 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
321 ; TUNIT-LABEL: define {{[^@]+}}@potential_test8
322 ; TUNIT-SAME: () #[[ATTR0]] {
323 ; TUNIT-NEXT:    ret i1 false
325 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
326 ; CGSCC-LABEL: define {{[^@]+}}@potential_test8
327 ; CGSCC-SAME: () #[[ATTR1]] {
328 ; CGSCC-NEXT:    [[RES1:%.*]] = call i1 @wrapper(i32 noundef 1) #[[ATTR2]]
329 ; CGSCC-NEXT:    [[RES3:%.*]] = call i1 @wrapper(i32 noundef 3) #[[ATTR2]]
330 ; CGSCC-NEXT:    [[RES5:%.*]] = call i1 @wrapper(i32 noundef 5) #[[ATTR2]]
331 ; CGSCC-NEXT:    [[RES13:%.*]] = or i1 [[RES1]], [[RES3]]
332 ; CGSCC-NEXT:    [[RES135:%.*]] = or i1 [[RES13]], [[RES5]]
333 ; CGSCC-NEXT:    ret i1 [[RES135]]
335   %res1 = call i1 @wrapper(i32 1)
336   %res3 = call i1 @wrapper(i32 3)
337   %res5 = call i1 @wrapper(i32 5)
338   %res13 = or i1 %res1, %res3
339   %res135 =  or i1 %res13, %res5
340   ret i1 %res135
343 define i1 @potential_test9() {
344 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
345 ; CHECK-LABEL: define {{[^@]+}}@potential_test9
346 ; CHECK-SAME: () #[[ATTR0]] {
347 ; CHECK-NEXT:  entry:
348 ; CHECK-NEXT:    br label [[COND:%.*]]
349 ; CHECK:       cond:
350 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
351 ; CHECK-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
352 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
353 ; CHECK-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
354 ; CHECK:       body:
355 ; CHECK-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
356 ; CHECK-NEXT:    br label [[INC]]
357 ; CHECK:       inc:
358 ; CHECK-NEXT:    [[I_1]] = add i32 [[I_0]], 1
359 ; CHECK-NEXT:    br label [[COND]]
360 ; CHECK:       end:
361 ; CHECK-NEXT:    ret i1 false
363 entry:
364   br label %cond
365 cond:
366   %i.0 = phi i32 [0, %entry], [%i.1, %inc]
367   %c.0 = phi i32 [1, %entry], [%c.1, %inc]
368   %cmp = icmp slt i32 %i.0, 10
369   br i1 %cmp, label %body, label %end
370 body:
371   %c.1 = mul i32 %c.0, -1
372   br label %inc
373 inc:
374   %i.1 = add i32 %i.0, 1
375   br label %cond
376 end:
377   %ret = icmp eq i32 %c.0, 0
378   ret i1 %ret
381 ; Test 10
382 ; potential returned values of @may_return_undef is {1, -1}
383 ; and returned value of @potential_test10 can be simplified to 0(false)
385 define internal i32 @may_return_undef(i32 %c) {
386 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
387 ; CGSCC-LABEL: define {{[^@]+}}@may_return_undef
388 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
389 ; CGSCC-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
390 ; CGSCC-NEXT:      i32 1, label [[A:%.*]]
391 ; CGSCC-NEXT:      i32 -1, label [[B:%.*]]
392 ; CGSCC-NEXT:    ]
393 ; CGSCC:       a:
394 ; CGSCC-NEXT:    ret i32 1
395 ; CGSCC:       b:
396 ; CGSCC-NEXT:    ret i32 -1
397 ; CGSCC:       otherwise:
398 ; CGSCC-NEXT:    ret i32 undef
400   switch i32 %c, label %otherwise [i32 1, label %a
401   i32 -1, label %b]
403   ret i32 1
405   ret i32 -1
406 otherwise:
407   ret i32 undef
410 define i1 @potential_test10(i32 %c) {
411 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
412 ; TUNIT-LABEL: define {{[^@]+}}@potential_test10
413 ; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
414 ; TUNIT-NEXT:    ret i1 false
416 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
417 ; CGSCC-LABEL: define {{[^@]+}}@potential_test10
418 ; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
419 ; CGSCC-NEXT:    [[RET:%.*]] = call i32 @may_return_undef(i32 noundef [[C]]) #[[ATTR2]]
420 ; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RET]], 0
421 ; CGSCC-NEXT:    ret i1 [[CMP]]
423   %ret = call i32 @may_return_undef(i32 %c)
424   %cmp = icmp eq i32 %ret, 0
425   ret i1 %cmp
428 define i32 @optimize_undef_1(i1 %c) {
429 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
430 ; CHECK-LABEL: define {{[^@]+}}@optimize_undef_1
431 ; CHECK-SAME: (i1 noundef [[C:%.*]]) #[[ATTR0]] {
432 ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
433 ; CHECK:       t:
434 ; CHECK-NEXT:    ret i32 0
435 ; CHECK:       f:
436 ; CHECK-NEXT:    [[UNDEF:%.*]] = add i32 undef, 1
437 ; CHECK-NEXT:    ret i32 [[UNDEF]]
439   br i1 %c, label %t, label %f
441   ret i32 0
443   %undef = add i32 undef, 1
444   ret i32 %undef
447 define i32 @optimize_undef_2(i1 %c) {
448 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
449 ; CHECK-LABEL: define {{[^@]+}}@optimize_undef_2
450 ; CHECK-SAME: (i1 noundef [[C:%.*]]) #[[ATTR0]] {
451 ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
452 ; CHECK:       t:
453 ; CHECK-NEXT:    ret i32 0
454 ; CHECK:       f:
455 ; CHECK-NEXT:    [[UNDEF:%.*]] = sub i32 undef, 1
456 ; CHECK-NEXT:    ret i32 [[UNDEF]]
458   br i1 %c, label %t, label %f
460   ret i32 0
462   %undef = sub i32 undef, 1
463   ret i32 %undef
466 define i32 @optimize_undef_3(i1 %c) {
467 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
468 ; CHECK-LABEL: define {{[^@]+}}@optimize_undef_3
469 ; CHECK-SAME: (i1 noundef [[C:%.*]]) #[[ATTR0]] {
470 ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
471 ; CHECK:       t:
472 ; CHECK-NEXT:    ret i32 0
473 ; CHECK:       f:
474 ; CHECK-NEXT:    ret i32 0
476   br i1 %c, label %t, label %f
478   ret i32 0
480   %undef = icmp eq i32 undef, 0
481   %undef2 = zext i1 %undef to i32
482   ret i32 %undef2
486 ; FIXME: returned value can be simplified to 0
487 define i32 @potential_test11(i1 %c) {
488 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
489 ; TUNIT-LABEL: define {{[^@]+}}@potential_test11
490 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
491 ; TUNIT-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 noundef [[C]]) #[[ATTR1]]
492 ; TUNIT-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 noundef [[C]]) #[[ATTR1]]
493 ; TUNIT-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
494 ; TUNIT-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], 0
495 ; TUNIT-NEXT:    ret i32 [[ACC2]]
497 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
498 ; CGSCC-LABEL: define {{[^@]+}}@potential_test11
499 ; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {
500 ; CGSCC-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 noundef [[C]]) #[[ATTR2]]
501 ; CGSCC-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 noundef [[C]]) #[[ATTR2]]
502 ; CGSCC-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 noundef [[C]]) #[[ATTR2]]
503 ; CGSCC-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
504 ; CGSCC-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
505 ; CGSCC-NEXT:    ret i32 [[ACC2]]
507   %zero1 = call i32 @optimize_undef_1(i1 %c)
508   %zero2 = call i32 @optimize_undef_2(i1 %c)
509   %zero3 = call i32 @optimize_undef_3(i1 %c)
510   %acc1 = add i32 %zero1, %zero2
511   %acc2 = add i32 %acc1, %zero3
512   ret i32 %acc2
515 define i32 @optimize_poison_1(i1 %c) {
516 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
517 ; CHECK-LABEL: define {{[^@]+}}@optimize_poison_1
518 ; CHECK-SAME: (i1 noundef [[C:%.*]]) #[[ATTR0]] {
519 ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
520 ; CHECK:       t:
521 ; CHECK-NEXT:    ret i32 0
522 ; CHECK:       f:
523 ; CHECK-NEXT:    ret i32 0
525   br i1 %c, label %t, label %f
527   ret i32 0
529   %poison = sub nuw i32 0, 1
530   ret i32 %poison
533 ; returned value can be simplified to 0
534 define i32 @potential_test12(i1 %c) {
535 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
536 ; TUNIT-LABEL: define {{[^@]+}}@potential_test12
537 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
538 ; TUNIT-NEXT:    ret i32 0
540 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
541 ; CGSCC-LABEL: define {{[^@]+}}@potential_test12
542 ; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {
543 ; CGSCC-NEXT:    [[ZERO:%.*]] = call noundef i32 @optimize_poison_1(i1 noundef [[C]]) #[[ATTR2]]
544 ; CGSCC-NEXT:    ret i32 [[ZERO]]
546   %zero = call i32 @optimize_poison_1(i1 %c)
547   ret i32 %zero
550 ; Test 13
551 ; Do not simplify %ret in the callee to `%c`.
552 ; The potential value of %c is {0, 1} (undef is merged).
553 ; However, we should not simplify `and i32 %c, 3` to `%c`
555 define internal i32 @potential_test13_callee(i32 %c) {
556 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
557 ; CHECK-LABEL: define {{[^@]+}}@potential_test13_callee
558 ; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
559 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[C]], 3
560 ; CHECK-NEXT:    ret i32 [[RET]]
562   %ret = and i32 %c, 3
563   ret i32 %ret
566 define i32 @potential_test13_caller1() {
567 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
568 ; TUNIT-LABEL: define {{[^@]+}}@potential_test13_caller1
569 ; TUNIT-SAME: () #[[ATTR0]] {
570 ; TUNIT-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR1]]
571 ; TUNIT-NEXT:    ret i32 [[RET]]
573 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
574 ; CGSCC-LABEL: define {{[^@]+}}@potential_test13_caller1
575 ; CGSCC-SAME: () #[[ATTR1]] {
576 ; CGSCC-NEXT:    [[RET:%.*]] = call noundef i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]]
577 ; CGSCC-NEXT:    ret i32 [[RET]]
579   %ret = call i32 @potential_test13_callee(i32 0)
580   ret i32 %ret
583 define i32 @potential_test13_caller2() {
584 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
585 ; TUNIT-LABEL: define {{[^@]+}}@potential_test13_caller2
586 ; TUNIT-SAME: () #[[ATTR0]] {
587 ; TUNIT-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR1]]
588 ; TUNIT-NEXT:    ret i32 [[RET]]
590 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
591 ; CGSCC-LABEL: define {{[^@]+}}@potential_test13_caller2
592 ; CGSCC-SAME: () #[[ATTR1]] {
593 ; CGSCC-NEXT:    [[RET:%.*]] = call noundef i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]]
594 ; CGSCC-NEXT:    ret i32 [[RET]]
596   %ret = call i32 @potential_test13_callee(i32 1)
597   ret i32 %ret
600 define i32 @potential_test13_caller3() {
601 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
602 ; TUNIT-LABEL: define {{[^@]+}}@potential_test13_caller3
603 ; TUNIT-SAME: () #[[ATTR0]] {
604 ; TUNIT-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]]
605 ; TUNIT-NEXT:    ret i32 [[RET]]
607 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
608 ; CGSCC-LABEL: define {{[^@]+}}@potential_test13_caller3
609 ; CGSCC-SAME: () #[[ATTR1]] {
610 ; CGSCC-NEXT:    [[RET:%.*]] = call noundef i32 @potential_test13_callee(i32 undef) #[[ATTR2]]
611 ; CGSCC-NEXT:    ret i32 [[RET]]
613   %ret = call i32 @potential_test13_callee(i32 undef)
614   ret i32 %ret
617 define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) {
618 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
619 ; CHECK-LABEL: define {{[^@]+}}@potential_test14
620 ; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR0]] {
621 ; CHECK-NEXT:    [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
622 ; CHECK-NEXT:    [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
623 ; CHECK-NEXT:    [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7
624 ; CHECK-NEXT:    [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]]
625 ; CHECK-NEXT:    [[RET:%.*]] = icmp slt i32 [[Z3]], 7
626 ; CHECK-NEXT:    ret i1 [[RET]]
628   %x0 = select i1 %c0, i32 0, i32 1
629   %x1 = select i1 %c1, i32 %x0, i32 undef
630   %y2 = select i1 %c2, i32 0, i32 7
631   %z3 = select i1 %c3, i32 %x1, i32 %y2
632   %ret = icmp slt i32 %z3, 7
633   ret i1 %ret
636 define i1 @potential_test15(i1 %c0, i1 %c1) {
637 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
638 ; CHECK-LABEL: define {{[^@]+}}@potential_test15
639 ; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
640 ; CHECK-NEXT:    ret i1 false
642   %x0 = select i1 %c0, i32 0, i32 1
643   %x1 = select i1 %c1, i32 %x0, i32 undef
644   %ret = icmp eq i32 %x1, 7
645   ret i1 %ret
648 define i1 @potential_test16(i1 %c0, i1 %c1) {
649 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
650 ; CHECK-LABEL: define {{[^@]+}}@potential_test16
651 ; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
652 ; CHECK-NEXT:    ret i1 false
654   %x0 = select i1 %c0, i32 0, i32 undef
655   %x1 = select i1 %c1, i32 %x0, i32 1
656   %ret = icmp eq i32 %x1, 7
657   ret i1 %ret
661 ; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
662 ; TUNIT: attributes #[[ATTR1]] = { nofree nosync nounwind willreturn memory(none) }
664 ; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
665 ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
666 ; CGSCC: attributes #[[ATTR2]] = { nofree nosync willreturn }