1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -enable-new-pm=0 -attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=20 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=20 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -enable-new-pm=0 -attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6;
7; Test for multiple potential values
8;
9; potential-test 1
10; bool iszero(int c) { return c == 0; }
11; bool potential_test1(bool c) { return iszero(c ? 1 : -1); }
12
13define internal i1 @iszero1(i32 %c) {
14; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
15; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero1
16; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] {
17; IS__CGSCC____-NEXT:    ret i1 false
18;
19  %cmp = icmp eq i32 %c, 0
20  ret i1 %cmp
21}
22
23define i1 @potential_test1(i1 %c) {
24; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
25; CHECK-LABEL: define {{[^@]+}}@potential_test1
26; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
27; CHECK-NEXT:    ret i1 false
28;
29  %arg = select i1 %c, i32 -1, i32 1
30  %ret = call i1 @iszero1(i32 %arg)
31  ret i1 %ret
32}
33
34
35; potential-test 2
36;
37; potential values of argument of iszero are {1,-1}
38; potential value of returned value of iszero is 0
39;
40; int call_with_two_values(int x) { return iszero(x) + iszero(-x); }
41; int potential_test2(int x) { return call_with_two_values(1) + call_with_two_values(-1); }
42
43define internal i32 @iszero2(i32 %c) {
44; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
45; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero2
46; IS__CGSCC____-SAME: () #[[ATTR0]] {
47; IS__CGSCC____-NEXT:    ret i32 0
48;
49  %cmp = icmp eq i32 %c, 0
50  %ret = zext i1 %cmp to i32
51  ret i32 %ret
52}
53
54define internal i32 @call_with_two_values(i32 %c) {
55; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
56; IS__CGSCC____-LABEL: define {{[^@]+}}@call_with_two_values
57; IS__CGSCC____-SAME: () #[[ATTR0]] {
58; IS__CGSCC____-NEXT:    ret i32 0
59;
60  %csret1 = call i32 @iszero2(i32 %c)
61  %minusc = sub i32 0, %c
62  %csret2 = call i32 @iszero2(i32 %minusc)
63  %ret = add i32 %csret1, %csret2
64  ret i32 %ret
65}
66
67define i32 @potential_test2(i1 %c) {
68; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
69; CHECK-LABEL: define {{[^@]+}}@potential_test2
70; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
71; CHECK-NEXT:    ret i32 0
72;
73  %csret1 = call i32 @call_with_two_values(i32 1)
74  %csret2 = call i32 @call_with_two_values(i32 -1)
75  %ret = add i32 %csret1, %csret2
76  ret i32 %ret
77}
78
79
80; potential-test 3
81;
82; potential values of returned value of f are {0,1}
83; potential values of argument of g are {0,1}
84; potential value of returned value of g is 1
85; then returned value of g can be simplified
86;
87; int zero_or_one(int c) { return c < 2; }
88; int potential_test3() { return zero_or_one(iszero(0))+zero_or_one(iszero(1)); }
89
90define internal i32 @iszero3(i32 %c) {
91; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
92; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero3
93; IS__CGSCC____-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
94; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
95; IS__CGSCC____-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
96; IS__CGSCC____-NEXT:    ret i32 [[RET]]
97;
98  %cmp = icmp eq i32 %c, 0
99  %ret = zext i1 %cmp to i32
100  ret i32 %ret
101}
102
103define internal i32 @less_than_two(i32 %c) {
104; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
105; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_two
106; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
107; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 2
108; IS__CGSCC____-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
109; IS__CGSCC____-NEXT:    ret i32 [[RET]]
110;
111  %cmp = icmp slt i32 %c, 2
112  %ret = zext i1 %cmp to i32
113  ret i32 %ret
114}
115
116define i32 @potential_test3() {
117; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
118; CHECK-LABEL: define {{[^@]+}}@potential_test3
119; CHECK-SAME: () #[[ATTR0]] {
120; CHECK-NEXT:    ret i32 2
121;
122  %cmp1 = call i32 @iszero3(i32 0)
123  %true1 = call i32 @less_than_two(i32 %cmp1)
124  %cmp2 = call i32 @iszero3(i32 1)
125  %true2 = call i32 @less_than_two(i32 %cmp2)
126  %ret = add i32 %true1, %true2
127  ret i32 %ret
128}
129
130
131; potential-test 4,5
132;
133; simplified
134; int potential_test4(int c) { return return1or3(c) == 2; }
135; int potential_test5(int c) { return return1or3(c) == return2or4(c); }
136;
137; not simplified
138; int potential_test6(int c) { return return1or3(c) == 3; }
139; int potential_test7(int c) { return return1or3(c) == return3or4(c); }
140
141define i32 @potential_test4(i32 %c) {
142; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
143; CHECK-LABEL: define {{[^@]+}}@potential_test4
144; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
145; CHECK-NEXT:    ret i32 0
146;
147  %csret = call i32 @return1or3(i32 %c)
148  %false = icmp eq i32 %csret, 2
149  %ret = zext i1 %false to i32
150  ret i32 %ret
151}
152
153define i32 @potential_test5(i32 %c) {
154; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
155; CHECK-LABEL: define {{[^@]+}}@potential_test5
156; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
157; CHECK-NEXT:    ret i32 0
158;
159  %csret1 = call i32 @return1or3(i32 %c)
160  %csret2 = call i32 @return2or4(i32 %c)
161  %false = icmp eq i32 %csret1, %csret2
162  %ret = zext i1 %false to i32
163  ret i32 %ret
164}
165
166define i1 @potential_test6(i32 %c) {
167; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
168; IS________OPM-LABEL: define {{[^@]+}}@potential_test6
169; IS________OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
170; IS________OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2:[0-9]+]], !range [[RNG0:![0-9]+]]
171; IS________OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
172; IS________OPM-NEXT:    ret i1 [[RET]]
173;
174; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
175; IS________NPM-LABEL: define {{[^@]+}}@potential_test6
176; IS________NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
177; IS________NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
178; IS________NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
179; IS________NPM-NEXT:    ret i1 [[RET]]
180;
181  %csret1 = call i32 @return1or3(i32 %c)
182  %ret = icmp eq i32 %csret1, 3
183  ret i1 %ret
184}
185
186define i1 @potential_test7(i32 %c) {
187; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
188; IS________OPM-LABEL: define {{[^@]+}}@potential_test7
189; IS________OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
190; IS________OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]], !range [[RNG0]]
191; IS________OPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]], !range [[RNG1:![0-9]+]]
192; IS________OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
193; IS________OPM-NEXT:    ret i1 [[RET]]
194;
195; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
196; IS________NPM-LABEL: define {{[^@]+}}@potential_test7
197; IS________NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
198; IS________NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]], !range [[RNG0]]
199; IS________NPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
200; IS________NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
201; IS________NPM-NEXT:    ret i1 [[RET]]
202;
203  %csret1 = call i32 @return1or3(i32 %c)
204  %csret2 = call i32 @return3or4(i32 %c)
205  %ret = icmp eq i32 %csret1, %csret2
206  ret i1 %ret
207}
208
209define internal i32 @return1or3(i32 %c) {
210; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
211; CHECK-LABEL: define {{[^@]+}}@return1or3
212; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
213; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
214; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 1, i32 3
215; CHECK-NEXT:    ret i32 [[RET]]
216;
217  %cmp = icmp eq i32 %c, 0
218  %ret = select i1 %cmp, i32 1, i32 3
219  ret i32 %ret
220}
221
222define internal i32 @return2or4(i32 %c) {
223; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
224; IS__CGSCC____-LABEL: define {{[^@]+}}@return2or4
225; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
226; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
227; IS__CGSCC____-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 2, i32 4
228; IS__CGSCC____-NEXT:    ret i32 [[RET]]
229;
230  %cmp = icmp eq i32 %c, 0
231  %ret = select i1 %cmp, i32 2, i32 4
232  ret i32 %ret
233}
234
235define internal i32 @return3or4(i32 %c) {
236; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
237; CHECK-LABEL: define {{[^@]+}}@return3or4
238; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
239; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
240; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 3, i32 4
241; CHECK-NEXT:    ret i32 [[RET]]
242;
243  %cmp = icmp eq i32 %c, 0
244  %ret = select i1 %cmp, i32 3, i32 4
245  ret i32 %ret
246}
247
248; potential-test 8
249;
250; propagate argument to callsite argument
251
252define internal i1 @cmp_with_four(i32 %c) {
253; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
254; IS__CGSCC____-LABEL: define {{[^@]+}}@cmp_with_four
255; IS__CGSCC____-SAME: () #[[ATTR0]] {
256; IS__CGSCC____-NEXT:    ret i1 false
257;
258  %cmp = icmp eq i32 %c, 4
259  ret i1 %cmp
260}
261
262define internal i1 @wrapper(i32 %c) {
263; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
264; IS__CGSCC____-LABEL: define {{[^@]+}}@wrapper
265; IS__CGSCC____-SAME: () #[[ATTR0]] {
266; IS__CGSCC____-NEXT:    ret i1 false
267;
268  %ret = call i1 @cmp_with_four(i32 %c)
269  ret i1 %ret
270}
271
272define i1 @potential_test8() {
273; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
274; CHECK-LABEL: define {{[^@]+}}@potential_test8
275; CHECK-SAME: () #[[ATTR0]] {
276; CHECK-NEXT:    ret i1 false
277;
278  %res1 = call i1 @wrapper(i32 1)
279  %res3 = call i1 @wrapper(i32 3)
280  %res5 = call i1 @wrapper(i32 5)
281  %res13 = or i1 %res1, %res3
282  %res135 =  or i1 %res13, %res5
283  ret i1 %res135
284}
285
286define i1 @potential_test9() {
287; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone
288; IS________OPM-LABEL: define {{[^@]+}}@potential_test9
289; IS________OPM-SAME: () #[[ATTR1:[0-9]+]] {
290; IS________OPM-NEXT:  entry:
291; IS________OPM-NEXT:    br label [[COND:%.*]]
292; IS________OPM:       cond:
293; IS________OPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
294; IS________OPM-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
295; IS________OPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
296; IS________OPM-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
297; IS________OPM:       body:
298; IS________OPM-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
299; IS________OPM-NEXT:    br label [[INC]]
300; IS________OPM:       inc:
301; IS________OPM-NEXT:    [[I_1]] = add i32 [[I_0]], 1
302; IS________OPM-NEXT:    br label [[COND]]
303; IS________OPM:       end:
304; IS________OPM-NEXT:    ret i1 false
305;
306; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
307; IS________NPM-LABEL: define {{[^@]+}}@potential_test9
308; IS________NPM-SAME: () #[[ATTR0]] {
309; IS________NPM-NEXT:  entry:
310; IS________NPM-NEXT:    br label [[COND:%.*]]
311; IS________NPM:       cond:
312; IS________NPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
313; IS________NPM-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
314; IS________NPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
315; IS________NPM-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
316; IS________NPM:       body:
317; IS________NPM-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
318; IS________NPM-NEXT:    br label [[INC]]
319; IS________NPM:       inc:
320; IS________NPM-NEXT:    [[I_1]] = add i32 [[I_0]], 1
321; IS________NPM-NEXT:    br label [[COND]]
322; IS________NPM:       end:
323; IS________NPM-NEXT:    ret i1 false
324;
325entry:
326  br label %cond
327cond:
328  %i.0 = phi i32 [0, %entry], [%i.1, %inc]
329  %c.0 = phi i32 [1, %entry], [%c.1, %inc]
330  %cmp = icmp slt i32 %i.0, 10
331  br i1 %cmp, label %body, label %end
332body:
333  %c.1 = mul i32 %c.0, -1
334  br label %inc
335inc:
336  %i.1 = add i32 %i.0, 1
337  br label %cond
338end:
339  %ret = icmp eq i32 %c.0, 0
340  ret i1 %ret
341}
342
343; Test 10
344; FIXME: potential returned values of @may_return_undef is {1, -1}
345;        and returned value of @potential_test10 can be simplified to 0(false)
346
347define internal i32 @may_return_undef(i32 %c) {
348; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
349; IS__CGSCC____-LABEL: define {{[^@]+}}@may_return_undef
350; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
351; IS__CGSCC____-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
352; IS__CGSCC____-NEXT:    i32 1, label [[A:%.*]]
353; IS__CGSCC____-NEXT:    i32 -1, label [[B:%.*]]
354; IS__CGSCC____-NEXT:    ]
355; IS__CGSCC____:       a:
356; IS__CGSCC____-NEXT:    ret i32 1
357; IS__CGSCC____:       b:
358; IS__CGSCC____-NEXT:    ret i32 -1
359; IS__CGSCC____:       otherwise:
360; IS__CGSCC____-NEXT:    ret i32 undef
361;
362  switch i32 %c, label %otherwise [i32 1, label %a
363  i32 -1, label %b]
364a:
365  ret i32 1
366b:
367  ret i32 -1
368otherwise:
369  ret i32 undef
370}
371
372define i1 @potential_test10(i32 %c) {
373; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
374; CHECK-LABEL: define {{[^@]+}}@potential_test10
375; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
376; CHECK-NEXT:    ret i1 false
377;
378  %ret = call i32 @may_return_undef(i32 %c)
379  %cmp = icmp eq i32 %ret, 0
380  ret i1 %cmp
381}
382
383define i32 @optimize_undef_1(i1 %c) {
384; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
385; CHECK-LABEL: define {{[^@]+}}@optimize_undef_1
386; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
387; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
388; CHECK:       t:
389; CHECK-NEXT:    ret i32 0
390; CHECK:       f:
391; CHECK-NEXT:    ret i32 1
392;
393  br i1 %c, label %t, label %f
394t:
395  ret i32 0
396f:
397  %undef = add i32 undef, 1
398  ret i32 %undef
399}
400
401define i32 @optimize_undef_2(i1 %c) {
402; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
403; CHECK-LABEL: define {{[^@]+}}@optimize_undef_2
404; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
405; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
406; CHECK:       t:
407; CHECK-NEXT:    ret i32 0
408; CHECK:       f:
409; CHECK-NEXT:    ret i32 -1
410;
411  br i1 %c, label %t, label %f
412t:
413  ret i32 0
414f:
415  %undef = sub i32 undef, 1
416  ret i32 %undef
417}
418
419define i32 @optimize_undef_3(i1 %c) {
420; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
421; CHECK-LABEL: define {{[^@]+}}@optimize_undef_3
422; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
423; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
424; CHECK:       t:
425; CHECK-NEXT:    ret i32 0
426; CHECK:       f:
427; CHECK-NEXT:    ret i32 1
428;
429  br i1 %c, label %t, label %f
430t:
431  ret i32 0
432f:
433  %undef = icmp eq i32 undef, 0
434  %undef2 = zext i1 %undef to i32
435  ret i32 %undef2
436}
437
438
439; FIXME: returned value can be simplified to 0
440define i32 @potential_test11(i1 %c) {
441; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
442; IS________OPM-LABEL: define {{[^@]+}}@potential_test11
443; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
444; IS________OPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]], !range [[RNG2:![0-9]+]]
445; IS________OPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]], !range [[RNG3:![0-9]+]]
446; IS________OPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]], !range [[RNG2]]
447; IS________OPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
448; IS________OPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
449; IS________OPM-NEXT:    ret i32 [[ACC2]]
450;
451; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
452; IS________NPM-LABEL: define {{[^@]+}}@potential_test11
453; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
454; IS________NPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR1]], !range [[RNG2:![0-9]+]]
455; IS________NPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR1]], !range [[RNG3:![0-9]+]]
456; IS________NPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR1]], !range [[RNG2]]
457; IS________NPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
458; IS________NPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
459; IS________NPM-NEXT:    ret i32 [[ACC2]]
460;
461  %zero1 = call i32 @optimize_undef_1(i1 %c)
462  %zero2 = call i32 @optimize_undef_2(i1 %c)
463  %zero3 = call i32 @optimize_undef_3(i1 %c)
464  %acc1 = add i32 %zero1, %zero2
465  %acc2 = add i32 %acc1, %zero3
466  ret i32 %acc2
467}
468
469define i32 @optimize_poison_1(i1 %c) {
470; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
471; IS________OPM-LABEL: define {{[^@]+}}@optimize_poison_1
472; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
473; IS________OPM-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
474; IS________OPM:       t:
475; IS________OPM-NEXT:    ret i32 0
476; IS________OPM:       f:
477; IS________OPM-NEXT:    ret i32 -1
478;
479; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
480; IS________NPM-LABEL: define {{[^@]+}}@optimize_poison_1
481; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
482; IS________NPM-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
483; IS________NPM:       t:
484; IS________NPM-NEXT:    ret i32 0
485; IS________NPM:       f:
486; IS________NPM-NEXT:    ret i32 undef
487;
488  br i1 %c, label %t, label %f
489t:
490  ret i32 0
491f:
492  %poison = sub nuw i32 0, 1
493  ret i32 %poison
494}
495
496; FIXME: returned value can be simplified to 0
497define i32 @potential_test12(i1 %c) {
498; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
499; IS________OPM-LABEL: define {{[^@]+}}@potential_test12
500; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
501; IS________OPM-NEXT:    [[ZERO:%.*]] = call noundef i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG3]]
502; IS________OPM-NEXT:    ret i32 [[ZERO]]
503;
504; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
505; IS________NPM-LABEL: define {{[^@]+}}@potential_test12
506; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
507; IS________NPM-NEXT:    ret i32 0
508;
509  %zero = call i32 @optimize_poison_1(i1 %c)
510  ret i32 %zero
511}
512
513; Test 13
514; Do not simplify %ret in the callee to `%c`.
515; The potential value of %c is {0, 1} (undef is merged).
516; However, we should not simplify `and i32 %c, 3` to `%c`
517
518define internal i32 @potential_test13_callee(i32 %c) {
519; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
520; CHECK-LABEL: define {{[^@]+}}@potential_test13_callee
521; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
522; CHECK-NEXT:    [[RET:%.*]] = and i32 [[C]], 3
523; CHECK-NEXT:    ret i32 [[RET]]
524;
525  %ret = and i32 %c, 3
526  ret i32 %ret
527}
528
529define i32 @potential_test13_caller1() {
530; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
531; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller1
532; IS________OPM-SAME: () #[[ATTR0]] {
533; IS________OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]], !range [[RNG2]]
534; IS________OPM-NEXT:    ret i32 [[RET]]
535;
536; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
537; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller1
538; IS________NPM-SAME: () #[[ATTR0]] {
539; IS________NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
540; IS________NPM-NEXT:    ret i32 [[RET]]
541;
542  %ret = call i32 @potential_test13_callee(i32 0)
543  ret i32 %ret
544}
545
546define i32 @potential_test13_caller2() {
547; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
548; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller2
549; IS________OPM-SAME: () #[[ATTR0]] {
550; IS________OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]], !range [[RNG2]]
551; IS________OPM-NEXT:    ret i32 [[RET]]
552;
553; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
554; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller2
555; IS________NPM-SAME: () #[[ATTR0]] {
556; IS________NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
557; IS________NPM-NEXT:    ret i32 [[RET]]
558;
559  %ret = call i32 @potential_test13_callee(i32 1)
560  ret i32 %ret
561}
562
563define i32 @potential_test13_caller3() {
564; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
565; IS________OPM-LABEL: define {{[^@]+}}@potential_test13_caller3
566; IS________OPM-SAME: () #[[ATTR0]] {
567; IS________OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG2]]
568; IS________OPM-NEXT:    ret i32 [[RET]]
569;
570; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
571; IS________NPM-LABEL: define {{[^@]+}}@potential_test13_caller3
572; IS________NPM-SAME: () #[[ATTR0]] {
573; IS________NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]], !range [[RNG2]]
574; IS________NPM-NEXT:    ret i32 [[RET]]
575;
576  %ret = call i32 @potential_test13_callee(i32 undef)
577  ret i32 %ret
578}
579
580define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) {
581; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
582; CHECK-LABEL: define {{[^@]+}}@potential_test14
583; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR0]] {
584; CHECK-NEXT:    [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
585; CHECK-NEXT:    [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
586; CHECK-NEXT:    [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7
587; CHECK-NEXT:    [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]]
588; CHECK-NEXT:    [[RET:%.*]] = icmp slt i32 [[Z3]], 7
589; CHECK-NEXT:    ret i1 [[RET]]
590;
591  %x0 = select i1 %c0, i32 0, i32 1
592  %x1 = select i1 %c1, i32 %x0, i32 undef
593  %y2 = select i1 %c2, i32 0, i32 7
594  %z3 = select i1 %c3, i32 %x1, i32 %y2
595  %ret = icmp slt i32 %z3, 7
596  ret i1 %ret
597}
598
599define i1 @potential_test15(i1 %c0, i1 %c1) {
600; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
601; CHECK-LABEL: define {{[^@]+}}@potential_test15
602; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
603; CHECK-NEXT:    ret i1 false
604;
605  %x0 = select i1 %c0, i32 0, i32 1
606  %x1 = select i1 %c1, i32 %x0, i32 undef
607  %ret = icmp eq i32 %x1, 7
608  ret i1 %ret
609}
610
611define i1 @potential_test16(i1 %c0, i1 %c1) {
612; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
613; CHECK-LABEL: define {{[^@]+}}@potential_test16
614; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
615; CHECK-NEXT:    ret i1 false
616;
617  %x0 = select i1 %c0, i32 0, i32 undef
618  %x1 = select i1 %c1, i32 %x0, i32 1
619  %ret = icmp eq i32 %x1, 7
620  ret i1 %ret
621}
622
623;.
624; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
625; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone }
626; IS__TUNIT_OPM: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn }
627;.
628; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
629; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
630;.
631; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
632; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone }
633; IS__CGSCC_OPM: attributes #[[ATTR2]] = { readnone willreturn }
634;.
635; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
636; IS__CGSCC_NPM: attributes #[[ATTR1]] = { readnone willreturn }
637;.
638; CHECK: [[META0:![0-9]+]] = !{i32 1, i32 4}
639; CHECK: [[META1:![0-9]+]] = !{i32 3, i32 5}
640; CHECK: [[META2:![0-9]+]] = !{i32 0, i32 2}
641; CHECK: [[META3:![0-9]+]] = !{i32 -1, i32 1}
642;.
643