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=13 -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=13 -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: (i32 noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
17; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
18; IS__CGSCC____-NEXT:    ret i1 [[CMP]]
19;
20  %cmp = icmp eq i32 %c, 0
21  ret i1 %cmp
22}
23
24define i1 @potential_test1(i1 %c) {
25; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
26; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test1
27; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
28; IS__TUNIT____-NEXT:    ret i1 false
29;
30; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
31; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test1
32; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
33; IS__CGSCC_OPM-NEXT:    [[ARG:%.*]] = select i1 [[C]], i32 -1, i32 1
34; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i1 @iszero1(i32 noundef [[ARG]]) #[[ATTR3:[0-9]+]]
35; IS__CGSCC_OPM-NEXT:    ret i1 [[RET]]
36;
37; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
38; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test1
39; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
40; IS__CGSCC_NPM-NEXT:    [[ARG:%.*]] = select i1 [[C]], i32 -1, i32 1
41; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i1 @iszero1(i32 noundef [[ARG]]) #[[ATTR2:[0-9]+]]
42; IS__CGSCC_NPM-NEXT:    ret i1 [[RET]]
43;
44  %arg = select i1 %c, i32 -1, i32 1
45  %ret = call i1 @iszero1(i32 %arg)
46  ret i1 %ret
47}
48
49
50; potential-test 2
51;
52; potential values of argument of iszero are {1,-1}
53; potential value of returned value of iszero is 0
54;
55; int call_with_two_values(int x) { return iszero(x) + iszero(-x); }
56; int potential_test2(int x) { return call_with_two_values(1) + call_with_two_values(-1); }
57
58define internal i32 @iszero2(i32 %c) {
59; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
60; CHECK-LABEL: define {{[^@]+}}@iszero2
61; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
62; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
63; CHECK-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
64; CHECK-NEXT:    ret i32 [[RET]]
65;
66  %cmp = icmp eq i32 %c, 0
67  %ret = zext i1 %cmp to i32
68  ret i32 %ret
69}
70
71define internal i32 @call_with_two_values(i32 %c) {
72; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
73; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_with_two_values
74; IS__TUNIT_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
75; IS__TUNIT_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR2:[0-9]+]], !range [[RNG0:![0-9]+]]
76; IS__TUNIT_OPM-NEXT:    [[MINUSC:%.*]] = sub i32 0, [[C]]
77; IS__TUNIT_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR2]], !range [[RNG0]]
78; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
79; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
80;
81; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
82; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_with_two_values
83; IS__TUNIT_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
84; IS__TUNIT_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
85; IS__TUNIT_NPM-NEXT:    [[MINUSC:%.*]] = sub i32 0, [[C]]
86; IS__TUNIT_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR1]], !range [[RNG0]]
87; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
88; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
89;
90; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
91; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_with_two_values
92; IS__CGSCC_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
93; IS__CGSCC_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR3]]
94; IS__CGSCC_OPM-NEXT:    [[MINUSC:%.*]] = sub i32 0, [[C]]
95; IS__CGSCC_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR3]]
96; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
97; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
98;
99; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
100; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_with_two_values
101; IS__CGSCC_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
102; IS__CGSCC_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @iszero2(i32 noundef [[C]]) #[[ATTR2]]
103; IS__CGSCC_NPM-NEXT:    [[MINUSC:%.*]] = sub i32 0, [[C]]
104; IS__CGSCC_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @iszero2(i32 [[MINUSC]]) #[[ATTR2]]
105; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
106; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
107;
108  %csret1 = call i32 @iszero2(i32 %c)
109  %minusc = sub i32 0, %c
110  %csret2 = call i32 @iszero2(i32 %minusc)
111  %ret = add i32 %csret1, %csret2
112  ret i32 %ret
113}
114
115define i32 @potential_test2(i1 %c) {
116; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
117; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test2
118; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
119; IS__TUNIT_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR2]], !range [[RNG1:![0-9]+]]
120; IS__TUNIT_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR2]], !range [[RNG1]]
121; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
122; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
123;
124; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
125; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test2
126; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
127; IS__TUNIT_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR1]], !range [[RNG1:![0-9]+]]
128; IS__TUNIT_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR1]], !range [[RNG1]]
129; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
130; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
131;
132; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
133; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test2
134; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
135; IS__CGSCC_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR3]]
136; IS__CGSCC_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR3]]
137; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
138; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
139;
140; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
141; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test2
142; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
143; IS__CGSCC_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @call_with_two_values(i32 noundef 1) #[[ATTR2]]
144; IS__CGSCC_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @call_with_two_values(i32 noundef -1) #[[ATTR2]]
145; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
146; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
147;
148  %csret1 = call i32 @call_with_two_values(i32 1)
149  %csret2 = call i32 @call_with_two_values(i32 -1)
150  %ret = add i32 %csret1, %csret2
151  ret i32 %ret
152}
153
154
155; potential-test 3
156;
157; potential values of returned value of f are {0,1}
158; potential values of argument of g are {0,1}
159; potential value of returned value of g is 1
160; then returned value of g can be simplified
161;
162; int zero_or_one(int c) { return c < 2; }
163; int potential_test3() { return zero_or_one(iszero(0))+zero_or_one(iszero(1)); }
164
165define internal i32 @iszero3(i32 %c) {
166; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
167; IS__CGSCC____-LABEL: define {{[^@]+}}@iszero3
168; IS__CGSCC____-SAME: (i32 noundef [[C:%.*]]) #[[ATTR0]] {
169; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
170; IS__CGSCC____-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
171; IS__CGSCC____-NEXT:    ret i32 [[RET]]
172;
173  %cmp = icmp eq i32 %c, 0
174  %ret = zext i1 %cmp to i32
175  ret i32 %ret
176}
177
178define internal i32 @less_than_two(i32 %c) {
179; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
180; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_two
181; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
182; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 2
183; IS__CGSCC____-NEXT:    [[RET:%.*]] = zext i1 [[CMP]] to i32
184; IS__CGSCC____-NEXT:    ret i32 [[RET]]
185;
186  %cmp = icmp slt i32 %c, 2
187  %ret = zext i1 %cmp to i32
188  ret i32 %ret
189}
190
191define i32 @potential_test3() {
192; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
193; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test3
194; IS__TUNIT____-SAME: () #[[ATTR0]] {
195; IS__TUNIT____-NEXT:    ret i32 2
196;
197; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
198; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test3
199; IS__CGSCC_OPM-SAME: () #[[ATTR1]] {
200; IS__CGSCC_OPM-NEXT:    [[CMP1:%.*]] = call i32 @iszero3(i32 noundef 0) #[[ATTR3]]
201; IS__CGSCC_OPM-NEXT:    [[TRUE1:%.*]] = call i32 @less_than_two(i32 [[CMP1]]) #[[ATTR3]]
202; IS__CGSCC_OPM-NEXT:    [[CMP2:%.*]] = call i32 @iszero3(i32 noundef 1) #[[ATTR3]]
203; IS__CGSCC_OPM-NEXT:    [[TRUE2:%.*]] = call i32 @less_than_two(i32 [[CMP2]]) #[[ATTR3]]
204; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = add i32 [[TRUE1]], [[TRUE2]]
205; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
206;
207; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
208; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test3
209; IS__CGSCC_NPM-SAME: () #[[ATTR1]] {
210; IS__CGSCC_NPM-NEXT:    [[CMP1:%.*]] = call i32 @iszero3(i32 noundef 0) #[[ATTR2]]
211; IS__CGSCC_NPM-NEXT:    [[TRUE1:%.*]] = call i32 @less_than_two(i32 [[CMP1]]) #[[ATTR2]]
212; IS__CGSCC_NPM-NEXT:    [[CMP2:%.*]] = call i32 @iszero3(i32 noundef 1) #[[ATTR2]]
213; IS__CGSCC_NPM-NEXT:    [[TRUE2:%.*]] = call i32 @less_than_two(i32 [[CMP2]]) #[[ATTR2]]
214; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = add i32 [[TRUE1]], [[TRUE2]]
215; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
216;
217  %cmp1 = call i32 @iszero3(i32 0)
218  %true1 = call i32 @less_than_two(i32 %cmp1)
219  %cmp2 = call i32 @iszero3(i32 1)
220  %true2 = call i32 @less_than_two(i32 %cmp2)
221  %ret = add i32 %true1, %true2
222  ret i32 %ret
223}
224
225
226; potential-test 4,5
227;
228; simplified
229; int potential_test4(int c) { return return1or3(c) == 2; }
230; int potential_test5(int c) { return return1or3(c) == return2or4(c); }
231;
232; not simplified
233; int potential_test6(int c) { return return1or3(c) == 3; }
234; int potential_test7(int c) { return return1or3(c) == return3or4(c); }
235
236define i32 @potential_test4(i32 %c) {
237; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
238; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test4
239; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
240; IS__TUNIT_OPM-NEXT:    [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
241; IS__TUNIT_OPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2
242; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
243; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
244;
245; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
246; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test4
247; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
248; IS__TUNIT_NPM-NEXT:    [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]]
249; IS__TUNIT_NPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2
250; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
251; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
252;
253; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
254; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test4
255; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
256; IS__CGSCC_OPM-NEXT:    [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]]
257; IS__CGSCC_OPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2
258; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
259; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
260;
261; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
262; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test4
263; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
264; IS__CGSCC_NPM-NEXT:    [[CSRET:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
265; IS__CGSCC_NPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET]], 2
266; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
267; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
268;
269  %csret = call i32 @return1or3(i32 %c)
270  %false = icmp eq i32 %csret, 2
271  %ret = zext i1 %false to i32
272  ret i32 %ret
273}
274
275define i32 @potential_test5(i32 %c) {
276; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
277; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test5
278; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
279; IS__TUNIT_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
280; IS__TUNIT_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR2]]
281; IS__TUNIT_OPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
282; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
283; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
284;
285; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
286; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test5
287; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
288; IS__TUNIT_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]]
289; IS__TUNIT_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR1]]
290; IS__TUNIT_NPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
291; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
292; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
293;
294; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
295; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test5
296; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
297; IS__CGSCC_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]]
298; IS__CGSCC_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR3]]
299; IS__CGSCC_OPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
300; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
301; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
302;
303; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
304; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test5
305; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
306; IS__CGSCC_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
307; IS__CGSCC_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @return2or4(i32 [[C]]) #[[ATTR2]]
308; IS__CGSCC_NPM-NEXT:    [[FALSE:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
309; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = zext i1 [[FALSE]] to i32
310; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
311;
312  %csret1 = call i32 @return1or3(i32 %c)
313  %csret2 = call i32 @return2or4(i32 %c)
314  %false = icmp eq i32 %csret1, %csret2
315  %ret = zext i1 %false to i32
316  ret i32 %ret
317}
318
319define i1 @potential_test6(i32 %c) {
320; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
321; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test6
322; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
323; IS__TUNIT_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
324; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
325; IS__TUNIT_OPM-NEXT:    ret i1 [[RET]]
326;
327; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
328; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test6
329; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
330; IS__TUNIT_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]]
331; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
332; IS__TUNIT_NPM-NEXT:    ret i1 [[RET]]
333;
334; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
335; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test6
336; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
337; IS__CGSCC_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]]
338; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
339; IS__CGSCC_OPM-NEXT:    ret i1 [[RET]]
340;
341; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
342; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test6
343; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
344; IS__CGSCC_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
345; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], 3
346; IS__CGSCC_NPM-NEXT:    ret i1 [[RET]]
347;
348  %csret1 = call i32 @return1or3(i32 %c)
349  %ret = icmp eq i32 %csret1, 3
350  ret i1 %ret
351}
352
353define i1 @potential_test7(i32 %c) {
354; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
355; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test7
356; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
357; IS__TUNIT_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
358; IS__TUNIT_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]]
359; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
360; IS__TUNIT_OPM-NEXT:    ret i1 [[RET]]
361;
362; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
363; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test7
364; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
365; IS__TUNIT_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]]
366; IS__TUNIT_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]]
367; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
368; IS__TUNIT_NPM-NEXT:    ret i1 [[RET]]
369;
370; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
371; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test7
372; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
373; IS__CGSCC_OPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR3]]
374; IS__CGSCC_OPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR3]]
375; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
376; IS__CGSCC_OPM-NEXT:    ret i1 [[RET]]
377;
378; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
379; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test7
380; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
381; IS__CGSCC_NPM-NEXT:    [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]]
382; IS__CGSCC_NPM-NEXT:    [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]]
383; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]]
384; IS__CGSCC_NPM-NEXT:    ret i1 [[RET]]
385;
386  %csret1 = call i32 @return1or3(i32 %c)
387  %csret2 = call i32 @return3or4(i32 %c)
388  %ret = icmp eq i32 %csret1, %csret2
389  ret i1 %ret
390}
391
392define internal i32 @return1or3(i32 %c) {
393; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
394; CHECK-LABEL: define {{[^@]+}}@return1or3
395; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
396; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
397; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 1, i32 3
398; CHECK-NEXT:    ret i32 [[RET]]
399;
400  %cmp = icmp eq i32 %c, 0
401  %ret = select i1 %cmp, i32 1, i32 3
402  ret i32 %ret
403}
404
405define internal i32 @return2or4(i32 %c) {
406; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
407; CHECK-LABEL: define {{[^@]+}}@return2or4
408; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
409; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
410; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 2, i32 4
411; CHECK-NEXT:    ret i32 [[RET]]
412;
413  %cmp = icmp eq i32 %c, 0
414  %ret = select i1 %cmp, i32 2, i32 4
415  ret i32 %ret
416}
417
418define internal i32 @return3or4(i32 %c) {
419; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
420; CHECK-LABEL: define {{[^@]+}}@return3or4
421; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
422; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 0
423; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 3, i32 4
424; CHECK-NEXT:    ret i32 [[RET]]
425;
426  %cmp = icmp eq i32 %c, 0
427  %ret = select i1 %cmp, i32 3, i32 4
428  ret i32 %ret
429}
430
431; potential-test 8
432;
433; propagate argument to callsite argument
434
435define internal i1 @cmp_with_four(i32 %c) {
436; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
437; IS__CGSCC____-LABEL: define {{[^@]+}}@cmp_with_four
438; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
439; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], 4
440; IS__CGSCC____-NEXT:    ret i1 [[CMP]]
441;
442  %cmp = icmp eq i32 %c, 4
443  ret i1 %cmp
444}
445
446define internal i1 @wrapper(i32 %c) {
447; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
448; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@wrapper
449; IS__CGSCC_OPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
450; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i1 @cmp_with_four(i32 noundef [[C]]) #[[ATTR3]]
451; IS__CGSCC_OPM-NEXT:    ret i1 [[RET]]
452;
453; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
454; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@wrapper
455; IS__CGSCC_NPM-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
456; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i1 @cmp_with_four(i32 noundef [[C]]) #[[ATTR2]]
457; IS__CGSCC_NPM-NEXT:    ret i1 [[RET]]
458;
459  %ret = call i1 @cmp_with_four(i32 %c)
460  ret i1 %ret
461}
462
463define i1 @potential_test8() {
464; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
465; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test8
466; IS__TUNIT____-SAME: () #[[ATTR0]] {
467; IS__TUNIT____-NEXT:    ret i1 false
468;
469; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
470; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test8
471; IS__CGSCC_OPM-SAME: () #[[ATTR1]] {
472; IS__CGSCC_OPM-NEXT:    [[RES1:%.*]] = call i1 @wrapper(i32 noundef 1) #[[ATTR3]]
473; IS__CGSCC_OPM-NEXT:    [[RES3:%.*]] = call i1 @wrapper(i32 noundef 3) #[[ATTR3]]
474; IS__CGSCC_OPM-NEXT:    [[RES5:%.*]] = call i1 @wrapper(i32 noundef 5) #[[ATTR3]]
475; IS__CGSCC_OPM-NEXT:    [[RES13:%.*]] = or i1 [[RES1]], [[RES3]]
476; IS__CGSCC_OPM-NEXT:    [[RES135:%.*]] = or i1 [[RES13]], [[RES5]]
477; IS__CGSCC_OPM-NEXT:    ret i1 [[RES135]]
478;
479; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
480; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test8
481; IS__CGSCC_NPM-SAME: () #[[ATTR1]] {
482; IS__CGSCC_NPM-NEXT:    [[RES1:%.*]] = call i1 @wrapper(i32 noundef 1) #[[ATTR2]]
483; IS__CGSCC_NPM-NEXT:    [[RES3:%.*]] = call i1 @wrapper(i32 noundef 3) #[[ATTR2]]
484; IS__CGSCC_NPM-NEXT:    [[RES5:%.*]] = call i1 @wrapper(i32 noundef 5) #[[ATTR2]]
485; IS__CGSCC_NPM-NEXT:    [[RES13:%.*]] = or i1 [[RES1]], [[RES3]]
486; IS__CGSCC_NPM-NEXT:    [[RES135:%.*]] = or i1 [[RES13]], [[RES5]]
487; IS__CGSCC_NPM-NEXT:    ret i1 [[RES135]]
488;
489  %res1 = call i1 @wrapper(i32 1)
490  %res3 = call i1 @wrapper(i32 3)
491  %res5 = call i1 @wrapper(i32 5)
492  %res13 = or i1 %res1, %res3
493  %res135 =  or i1 %res13, %res5
494  ret i1 %res135
495}
496
497define i1 @potential_test9() {
498; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone
499; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test9
500; IS__TUNIT_OPM-SAME: () #[[ATTR1:[0-9]+]] {
501; IS__TUNIT_OPM-NEXT:  entry:
502; IS__TUNIT_OPM-NEXT:    br label [[COND:%.*]]
503; IS__TUNIT_OPM:       cond:
504; IS__TUNIT_OPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
505; IS__TUNIT_OPM-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
506; IS__TUNIT_OPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
507; IS__TUNIT_OPM-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
508; IS__TUNIT_OPM:       body:
509; IS__TUNIT_OPM-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
510; IS__TUNIT_OPM-NEXT:    br label [[INC]]
511; IS__TUNIT_OPM:       inc:
512; IS__TUNIT_OPM-NEXT:    [[I_1]] = add i32 [[I_0]], 1
513; IS__TUNIT_OPM-NEXT:    br label [[COND]]
514; IS__TUNIT_OPM:       end:
515; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[C_0]], 0
516; IS__TUNIT_OPM-NEXT:    ret i1 [[RET]]
517;
518; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
519; IS________NPM-LABEL: define {{[^@]+}}@potential_test9
520; IS________NPM-SAME: () #[[ATTR0]] {
521; IS________NPM-NEXT:  entry:
522; IS________NPM-NEXT:    br label [[COND:%.*]]
523; IS________NPM:       cond:
524; IS________NPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
525; IS________NPM-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
526; IS________NPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
527; IS________NPM-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
528; IS________NPM:       body:
529; IS________NPM-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
530; IS________NPM-NEXT:    br label [[INC]]
531; IS________NPM:       inc:
532; IS________NPM-NEXT:    [[I_1]] = add i32 [[I_0]], 1
533; IS________NPM-NEXT:    br label [[COND]]
534; IS________NPM:       end:
535; IS________NPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[C_0]], 0
536; IS________NPM-NEXT:    ret i1 [[RET]]
537;
538; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone
539; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test9
540; IS__CGSCC_OPM-SAME: () #[[ATTR2:[0-9]+]] {
541; IS__CGSCC_OPM-NEXT:  entry:
542; IS__CGSCC_OPM-NEXT:    br label [[COND:%.*]]
543; IS__CGSCC_OPM:       cond:
544; IS__CGSCC_OPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_1:%.*]], [[INC:%.*]] ]
545; IS__CGSCC_OPM-NEXT:    [[C_0:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[C_1:%.*]], [[INC]] ]
546; IS__CGSCC_OPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 10
547; IS__CGSCC_OPM-NEXT:    br i1 [[CMP]], label [[BODY:%.*]], label [[END:%.*]]
548; IS__CGSCC_OPM:       body:
549; IS__CGSCC_OPM-NEXT:    [[C_1]] = mul i32 [[C_0]], -1
550; IS__CGSCC_OPM-NEXT:    br label [[INC]]
551; IS__CGSCC_OPM:       inc:
552; IS__CGSCC_OPM-NEXT:    [[I_1]] = add i32 [[I_0]], 1
553; IS__CGSCC_OPM-NEXT:    br label [[COND]]
554; IS__CGSCC_OPM:       end:
555; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = icmp eq i32 [[C_0]], 0
556; IS__CGSCC_OPM-NEXT:    ret i1 [[RET]]
557;
558entry:
559  br label %cond
560cond:
561  %i.0 = phi i32 [0, %entry], [%i.1, %inc]
562  %c.0 = phi i32 [1, %entry], [%c.1, %inc]
563  %cmp = icmp slt i32 %i.0, 10
564  br i1 %cmp, label %body, label %end
565body:
566  %c.1 = mul i32 %c.0, -1
567  br label %inc
568inc:
569  %i.1 = add i32 %i.0, 1
570  br label %cond
571end:
572  %ret = icmp eq i32 %c.0, 0
573  ret i1 %ret
574}
575
576; Test 10
577; FIXME: potential returned values of @may_return_undef is {1, -1}
578;        and returned value of @potential_test10 can be simplified to 0(false)
579
580define internal i32 @may_return_undef(i32 %c) {
581; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
582; CHECK-LABEL: define {{[^@]+}}@may_return_undef
583; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
584; CHECK-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
585; CHECK-NEXT:    i32 1, label [[A:%.*]]
586; CHECK-NEXT:    i32 -1, label [[B:%.*]]
587; CHECK-NEXT:    ]
588; CHECK:       a:
589; CHECK-NEXT:    ret i32 1
590; CHECK:       b:
591; CHECK-NEXT:    ret i32 -1
592; CHECK:       otherwise:
593; CHECK-NEXT:    ret i32 undef
594;
595  switch i32 %c, label %otherwise [i32 1, label %a
596  i32 -1, label %b]
597a:
598  ret i32 1
599b:
600  ret i32 -1
601otherwise:
602  ret i32 undef
603}
604
605define i1 @potential_test10(i32 %c) {
606; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
607; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test10
608; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
609; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR2]]
610; IS__TUNIT_OPM-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RET]], 0
611; IS__TUNIT_OPM-NEXT:    ret i1 [[CMP]]
612;
613; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
614; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test10
615; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
616; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR1]]
617; IS__TUNIT_NPM-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RET]], 0
618; IS__TUNIT_NPM-NEXT:    ret i1 [[CMP]]
619;
620; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
621; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test10
622; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
623; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR3]]
624; IS__CGSCC_OPM-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RET]], 0
625; IS__CGSCC_OPM-NEXT:    ret i1 [[CMP]]
626;
627; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
628; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test10
629; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
630; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i32 @may_return_undef(i32 [[C]]) #[[ATTR2]]
631; IS__CGSCC_NPM-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RET]], 0
632; IS__CGSCC_NPM-NEXT:    ret i1 [[CMP]]
633;
634  %ret = call i32 @may_return_undef(i32 %c)
635  %cmp = icmp eq i32 %ret, 0
636  ret i1 %cmp
637}
638
639define i32 @optimize_undef_1(i1 %c) {
640; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
641; CHECK-LABEL: define {{[^@]+}}@optimize_undef_1
642; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
643; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
644; CHECK:       t:
645; CHECK-NEXT:    ret i32 0
646; CHECK:       f:
647; CHECK-NEXT:    [[UNDEF:%.*]] = add i32 undef, 1
648; CHECK-NEXT:    ret i32 [[UNDEF]]
649;
650  br i1 %c, label %t, label %f
651t:
652  ret i32 0
653f:
654  %undef = add i32 undef, 1
655  ret i32 %undef
656}
657
658define i32 @optimize_undef_2(i1 %c) {
659; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
660; CHECK-LABEL: define {{[^@]+}}@optimize_undef_2
661; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
662; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
663; CHECK:       t:
664; CHECK-NEXT:    ret i32 0
665; CHECK:       f:
666; CHECK-NEXT:    [[UNDEF:%.*]] = sub i32 undef, 1
667; CHECK-NEXT:    ret i32 [[UNDEF]]
668;
669  br i1 %c, label %t, label %f
670t:
671  ret i32 0
672f:
673  %undef = sub i32 undef, 1
674  ret i32 %undef
675}
676
677define i32 @optimize_undef_3(i1 %c) {
678; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
679; CHECK-LABEL: define {{[^@]+}}@optimize_undef_3
680; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
681; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
682; CHECK:       t:
683; CHECK-NEXT:    ret i32 0
684; CHECK:       f:
685; CHECK-NEXT:    [[UNDEF:%.*]] = icmp eq i32 undef, 0
686; CHECK-NEXT:    [[UNDEF2:%.*]] = zext i1 [[UNDEF]] to i32
687; CHECK-NEXT:    ret i32 [[UNDEF2]]
688;
689  br i1 %c, label %t, label %f
690t:
691  ret i32 0
692f:
693  %undef = icmp eq i32 undef, 0
694  %undef2 = zext i1 %undef to i32
695  ret i32 %undef2
696}
697
698
699; FIXME: returned value can be simplified to 0
700define i32 @potential_test11(i1 %c) {
701; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
702; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test11
703; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
704; IS__TUNIT_OPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]], !range [[RNG0]]
705; IS__TUNIT_OPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]], !range [[RNG2:![0-9]+]]
706; IS__TUNIT_OPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]], !range [[RNG0]]
707; IS__TUNIT_OPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
708; IS__TUNIT_OPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
709; IS__TUNIT_OPM-NEXT:    ret i32 [[ACC2]]
710;
711; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
712; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test11
713; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
714; IS__TUNIT_NPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR1]], !range [[RNG0]]
715; IS__TUNIT_NPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR1]], !range [[RNG2:![0-9]+]]
716; IS__TUNIT_NPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR1]], !range [[RNG0]]
717; IS__TUNIT_NPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
718; IS__TUNIT_NPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
719; IS__TUNIT_NPM-NEXT:    ret i32 [[ACC2]]
720;
721; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
722; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test11
723; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
724; IS__CGSCC_OPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR3]]
725; IS__CGSCC_OPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR3]]
726; IS__CGSCC_OPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR3]]
727; IS__CGSCC_OPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
728; IS__CGSCC_OPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
729; IS__CGSCC_OPM-NEXT:    ret i32 [[ACC2]]
730;
731; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
732; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test11
733; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
734; IS__CGSCC_NPM-NEXT:    [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR2]]
735; IS__CGSCC_NPM-NEXT:    [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR2]]
736; IS__CGSCC_NPM-NEXT:    [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR2]]
737; IS__CGSCC_NPM-NEXT:    [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]]
738; IS__CGSCC_NPM-NEXT:    [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]]
739; IS__CGSCC_NPM-NEXT:    ret i32 [[ACC2]]
740;
741  %zero1 = call i32 @optimize_undef_1(i1 %c)
742  %zero2 = call i32 @optimize_undef_2(i1 %c)
743  %zero3 = call i32 @optimize_undef_3(i1 %c)
744  %acc1 = add i32 %zero1, %zero2
745  %acc2 = add i32 %acc1, %zero3
746  ret i32 %acc2
747}
748
749define i32 @optimize_poison_1(i1 %c) {
750; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
751; CHECK-LABEL: define {{[^@]+}}@optimize_poison_1
752; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
753; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
754; CHECK:       t:
755; CHECK-NEXT:    ret i32 0
756; CHECK:       f:
757; CHECK-NEXT:    [[POISON:%.*]] = sub nuw i32 0, 1
758; CHECK-NEXT:    ret i32 [[POISON]]
759;
760  br i1 %c, label %t, label %f
761t:
762  ret i32 0
763f:
764  %poison = sub nuw i32 0, 1
765  ret i32 %poison
766}
767
768; FIXME: returned value can be simplified to 0
769define i32 @potential_test12(i1 %c) {
770; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
771; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test12
772; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
773; IS__TUNIT_OPM-NEXT:    [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG2]]
774; IS__TUNIT_OPM-NEXT:    ret i32 [[ZERO]]
775;
776; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
777; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test12
778; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
779; IS__TUNIT_NPM-NEXT:    ret i32 0
780;
781; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
782; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test12
783; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
784; IS__CGSCC_OPM-NEXT:    [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR3]]
785; IS__CGSCC_OPM-NEXT:    ret i32 [[ZERO]]
786;
787; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
788; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test12
789; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
790; IS__CGSCC_NPM-NEXT:    [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]]
791; IS__CGSCC_NPM-NEXT:    ret i32 [[ZERO]]
792;
793  %zero = call i32 @optimize_poison_1(i1 %c)
794  ret i32 %zero
795}
796
797; Test 13
798; Do not simplify %ret in the callee to `%c`.
799; The potential value of %c is {0, 1} (undef is merged).
800; However, we should not simplify `and i32 %c, 3` to `%c`
801
802define internal i32 @potential_test13_callee(i32 %c) {
803; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
804; CHECK-LABEL: define {{[^@]+}}@potential_test13_callee
805; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
806; CHECK-NEXT:    [[RET:%.*]] = and i32 [[C]], 3
807; CHECK-NEXT:    ret i32 [[RET]]
808;
809  %ret = and i32 %c, 3
810  ret i32 %ret
811}
812
813define i32 @potential_test13_caller1() {
814; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
815; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller1
816; IS__TUNIT_OPM-SAME: () #[[ATTR0]] {
817; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]], !range [[RNG0]]
818; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
819;
820; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
821; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller1
822; IS__TUNIT_NPM-SAME: () #[[ATTR0]] {
823; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR1]], !range [[RNG0]]
824; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
825;
826; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
827; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller1
828; IS__CGSCC_OPM-SAME: () #[[ATTR1]] {
829; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR3]]
830; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
831;
832; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
833; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller1
834; IS__CGSCC_NPM-SAME: () #[[ATTR1]] {
835; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR2]]
836; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
837;
838  %ret = call i32 @potential_test13_callee(i32 0)
839  ret i32 %ret
840}
841
842define i32 @potential_test13_caller2() {
843; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
844; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller2
845; IS__TUNIT_OPM-SAME: () #[[ATTR0]] {
846; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]], !range [[RNG0]]
847; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
848;
849; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
850; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller2
851; IS__TUNIT_NPM-SAME: () #[[ATTR0]] {
852; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR1]], !range [[RNG0]]
853; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
854;
855; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
856; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller2
857; IS__CGSCC_OPM-SAME: () #[[ATTR1]] {
858; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR3]]
859; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
860;
861; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
862; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller2
863; IS__CGSCC_NPM-SAME: () #[[ATTR1]] {
864; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 1) #[[ATTR2]]
865; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
866;
867  %ret = call i32 @potential_test13_callee(i32 1)
868  ret i32 %ret
869}
870
871define i32 @potential_test13_caller3() {
872; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
873; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3
874; IS__TUNIT_OPM-SAME: () #[[ATTR0]] {
875; IS__TUNIT_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG0]]
876; IS__TUNIT_OPM-NEXT:    ret i32 [[RET]]
877;
878; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
879; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3
880; IS__TUNIT_NPM-SAME: () #[[ATTR0]] {
881; IS__TUNIT_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]], !range [[RNG0]]
882; IS__TUNIT_NPM-NEXT:    ret i32 [[RET]]
883;
884; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
885; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3
886; IS__CGSCC_OPM-SAME: () #[[ATTR1]] {
887; IS__CGSCC_OPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR3]]
888; IS__CGSCC_OPM-NEXT:    ret i32 [[RET]]
889;
890; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
891; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3
892; IS__CGSCC_NPM-SAME: () #[[ATTR1]] {
893; IS__CGSCC_NPM-NEXT:    [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]]
894; IS__CGSCC_NPM-NEXT:    ret i32 [[RET]]
895;
896  %ret = call i32 @potential_test13_callee(i32 undef)
897  ret i32 %ret
898}
899
900define i1 @potential_test14(i1 %c0, i1 %c1, i1 %c2, i1 %c3) {
901; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
902; CHECK-LABEL: define {{[^@]+}}@potential_test14
903; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR0]] {
904; CHECK-NEXT:    [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
905; CHECK-NEXT:    [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
906; CHECK-NEXT:    [[Y2:%.*]] = select i1 [[C2]], i32 0, i32 7
907; CHECK-NEXT:    [[Z3:%.*]] = select i1 [[C3]], i32 [[X1]], i32 [[Y2]]
908; CHECK-NEXT:    [[RET:%.*]] = icmp slt i32 [[Z3]], 7
909; CHECK-NEXT:    ret i1 [[RET]]
910;
911  %x0 = select i1 %c0, i32 0, i32 1
912  %x1 = select i1 %c1, i32 %x0, i32 undef
913  %y2 = select i1 %c2, i32 0, i32 7
914  %z3 = select i1 %c3, i32 %x1, i32 %y2
915  %ret = icmp slt i32 %z3, 7
916  ret i1 %ret
917}
918
919define i1 @potential_test15(i1 %c0, i1 %c1) {
920; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
921; CHECK-LABEL: define {{[^@]+}}@potential_test15
922; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
923; CHECK-NEXT:    [[X0:%.*]] = select i1 [[C0]], i32 0, i32 1
924; CHECK-NEXT:    [[X1:%.*]] = select i1 [[C1]], i32 [[X0]], i32 undef
925; CHECK-NEXT:    [[RET:%.*]] = icmp eq i32 [[X1]], 7
926; CHECK-NEXT:    ret i1 [[RET]]
927;
928  %x0 = select i1 %c0, i32 0, i32 1
929  %x1 = select i1 %c1, i32 %x0, i32 undef
930  %ret = icmp eq i32 %x1, 7
931  ret i1 %ret
932}
933
934define i1 @potential_test16(i1 %c0, i1 %c1) {
935; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
936; CHECK-LABEL: define {{[^@]+}}@potential_test16
937; CHECK-SAME: (i1 [[C0:%.*]], i1 [[C1:%.*]]) #[[ATTR0]] {
938; CHECK-NEXT:    [[X1:%.*]] = select i1 [[C1]], i32 0, i32 1
939; CHECK-NEXT:    [[RET:%.*]] = icmp eq i32 [[X1]], 7
940; CHECK-NEXT:    ret i1 [[RET]]
941;
942  %x0 = select i1 %c0, i32 0, i32 undef
943  %x1 = select i1 %c1, i32 %x0, i32 1
944  %ret = icmp eq i32 %x1, 7
945  ret i1 %ret
946}
947
948;.
949; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
950; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone }
951; IS__TUNIT_OPM: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn }
952;.
953; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
954; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
955;.
956; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
957; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
958; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone }
959; IS__CGSCC_OPM: attributes #[[ATTR3]] = { readnone willreturn }
960;.
961; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
962; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
963; IS__CGSCC_NPM: attributes #[[ATTR2]] = { readnone willreturn }
964;.
965; IS__TUNIT____: [[META0:![0-9]+]] = !{i32 0, i32 2}
966; IS__TUNIT____: [[META1:![0-9]+]] = !{i32 0, i32 3}
967; IS__TUNIT____: [[META2:![0-9]+]] = !{i32 -1, i32 1}
968;.
969