xref: /llvm-project/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll (revision 72121a20cda4dc91d0ef5548f93046e71c5ec6f6)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=ipsccp -S | FileCheck %s
3
4declare void @use(i1)
5
6; We can simplify the conditions in the true block, because the condition
7; allows us to replace all uses of %a in the block with a  constant.
8define void @val_undef_eq() {
9; CHECK-LABEL: @val_undef_eq(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    [[A:%.*]] = add nuw nsw i32 undef, 0
12; CHECK-NEXT:    [[BC_1:%.*]] = icmp eq i32 [[A]], 10
13; CHECK-NEXT:    br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
14; CHECK:       true:
15; CHECK-NEXT:    call void @use(i1 false)
16; CHECK-NEXT:    call void @use(i1 true)
17; CHECK-NEXT:    ret void
18; CHECK:       false:
19; CHECK-NEXT:    ret void
20;
21entry:
22  %a = add i32 undef, 0
23  %bc.1 = icmp eq i32 %a, 10
24  br i1 %bc.1, label %true, label %false
25
26true:
27  %f.1 = icmp ne i32 %a, 10
28  call void @use(i1 %f.1)
29  %f.2 = icmp eq i32 %a,  10
30  call void @use(i1 %f.2)
31  ret void
32
33false:
34  ret void
35}
36
37declare void @use.i32(i32)
38
39; It is not allowed to use the range information from the condition to remove
40; %a.127 = and ... in the true block, as %a could be undef.
41define void @val_undef_range() {
42; CHECK-LABEL: @val_undef_range(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[A:%.*]] = add nuw nsw i32 undef, 0
45; CHECK-NEXT:    [[BC_1:%.*]] = icmp ult i32 [[A]], 127
46; CHECK-NEXT:    br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
47; CHECK:       true:
48; CHECK-NEXT:    call void @use(i1 false)
49; CHECK-NEXT:    [[A_127:%.*]] = and i32 [[A]], 127
50; CHECK-NEXT:    call void @use.i32(i32 [[A_127]])
51; CHECK-NEXT:    ret void
52; CHECK:       false:
53; CHECK-NEXT:    ret void
54;
55entry:
56  %a = add i32 undef, 0
57  %bc.1 = icmp ult i32 %a, 127
58  br i1 %bc.1, label %true, label %false
59
60true:
61  %f.1 = icmp eq i32 %a, 128
62  call void @use(i1 %f.1)
63
64  %a.127 = and i32 %a, 127
65  call void @use.i32(i32 %a.127)
66  ret void
67
68false:
69  ret void
70}
71
72; All uses of %p can be replaced by a constant (10).
73define void @val_singlecrfromundef_range(i1 %cond) {
74; CHECK-LABEL: @val_singlecrfromundef_range(
75; CHECK-NEXT:  entry:
76; CHECK-NEXT:    br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]]
77; CHECK:       inc1:
78; CHECK-NEXT:    br label [[IF:%.*]]
79; CHECK:       inc2:
80; CHECK-NEXT:    br label [[IF]]
81; CHECK:       if:
82; CHECK-NEXT:    br label [[TRUE:%.*]]
83; CHECK:       true:
84; CHECK-NEXT:    call void @use(i1 false)
85; CHECK-NEXT:    [[P_127:%.*]] = and i32 10, 127
86; CHECK-NEXT:    call void @use.i32(i32 [[P_127]])
87; CHECK-NEXT:    ret void
88;
89entry:
90
91  br i1 %cond, label %inc1, label %inc2
92
93inc1:
94  br label %if
95
96inc2:
97  br label %if
98
99if:
100  %p = phi i32 [ 10, %inc1 ], [ undef, %inc2 ]
101  %bc.1 = icmp ult i32 %p, 127
102  br i1 %bc.1, label %true, label %false
103
104true:
105  %f.1 = icmp eq i32 %p, 128
106  call void @use(i1 %f.1)
107
108  %p.127 = and i32 %p, 127
109  call void @use.i32(i32 %p.127)
110  ret void
111
112false:
113  ret void
114}
115
116
117; It is not allowed to use the information from the condition ([0, 128))
118; to remove a.127.2 = and i32 %p, 127, as %p might be undef.
119define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
120; CHECK-LABEL: @val_undef_to_cr_to_overdef_range(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[A_127:%.*]] = and i32 [[A:%.*]], 127
123; CHECK-NEXT:    br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]]
124; CHECK:       inc1:
125; CHECK-NEXT:    br label [[IF:%.*]]
126; CHECK:       inc2:
127; CHECK-NEXT:    br label [[IF]]
128; CHECK:       if:
129; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[A_127]], [[INC1]] ], [ undef, [[INC2]] ]
130; CHECK-NEXT:    [[BC_1:%.*]] = icmp ult i32 [[P]], 100
131; CHECK-NEXT:    br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
132; CHECK:       true:
133; CHECK-NEXT:    call void @use(i1 false)
134; CHECK-NEXT:    [[P_127:%.*]] = and i32 [[P]], 127
135; CHECK-NEXT:    call void @use.i32(i32 [[P_127]])
136; CHECK-NEXT:    ret void
137; CHECK:       false:
138; CHECK-NEXT:    ret void
139;
140entry:
141  %a.127 = and i32 %a, 127
142  br i1 %cond, label %inc1, label %inc2
143
144inc1:
145  br label %if
146
147inc2:
148  br label %if
149
150if:
151  %p = phi i32 [ %a.127, %inc1 ], [ undef, %inc2 ]
152  %bc.1 = icmp ult i32 %p, 100
153  br i1 %bc.1, label %true, label %false
154
155true:
156  %f.1 = icmp eq i32 %p, 128
157  call void @use(i1 %f.1)
158
159  %p.127 = and i32 %p, 127
160  call void @use.i32(i32 %p.127)
161  ret void
162
163false:
164  ret void
165}
166
167; All uses of %p can be replaced by a constant (10), we are allowed to use it
168; as a bound too.
169define void @bound_singlecrfromundef(i32 %a, i1 %cond) {
170; CHECK-LABEL: @bound_singlecrfromundef(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
173; CHECK:       bb1:
174; CHECK-NEXT:    br label [[PRED:%.*]]
175; CHECK:       bb2:
176; CHECK-NEXT:    br label [[PRED]]
177; CHECK:       pred:
178; CHECK-NEXT:    [[BC_1:%.*]] = icmp ugt i32 [[A:%.*]], 10
179; CHECK-NEXT:    br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
180; CHECK:       true:
181; CHECK-NEXT:    call void @use(i1 false)
182; CHECK-NEXT:    call void @use(i1 true)
183; CHECK-NEXT:    [[A_127:%.*]] = and i32 [[A]], 127
184; CHECK-NEXT:    call void @use.i32(i32 [[A_127]])
185; CHECK-NEXT:    ret void
186; CHECK:       false:
187; CHECK-NEXT:    ret void
188;
189entry:
190  br i1 %cond, label %bb1, label %bb2
191
192bb1:
193  br label %pred
194
195bb2:
196  br label %pred
197
198pred:
199  %p = phi i32 [ undef, %bb1 ], [ 10, %bb2 ]
200  %bc.1 = icmp ugt i32 %a, %p
201  br i1 %bc.1, label %true, label %false
202
203true:
204  %f.1 = icmp eq i32 %a, 5
205  call void @use(i1 %f.1)
206
207  %t.1 = icmp ne i32 %a,  5
208  call void @use(i1 %t.1)
209
210  %a.127 = and i32 %a, 127
211  call void @use.i32(i32 %a.127)
212
213  ret void
214
215false:
216  ret void
217}
218
219; It is not allowed to use the information from %p as a bound, because an
220; incoming value is undef.
221define void @bound_range_and_undef(i32 %a, i1 %cond) {
222; CHECK-LABEL: @bound_range_and_undef(
223; CHECK-NEXT:  entry:
224; CHECK-NEXT:    [[A_10:%.*]] = and i32 [[A:%.*]], 127
225; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
226; CHECK:       bb1:
227; CHECK-NEXT:    br label [[PRED:%.*]]
228; CHECK:       bb2:
229; CHECK-NEXT:    br label [[PRED]]
230; CHECK:       pred:
231; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[A_10]], [[BB1]] ], [ undef, [[BB2]] ]
232; CHECK-NEXT:    [[BC_1:%.*]] = icmp ugt i32 [[A]], [[P]]
233; CHECK-NEXT:    br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
234; CHECK:       true:
235; CHECK-NEXT:    [[F_1:%.*]] = icmp eq i32 [[A]], 300
236; CHECK-NEXT:    call void @use(i1 [[F_1]])
237; CHECK-NEXT:    [[A_127_2:%.*]] = and i32 [[P]], 127
238; CHECK-NEXT:    call void @use.i32(i32 [[A_127_2]])
239; CHECK-NEXT:    ret void
240; CHECK:       false:
241; CHECK-NEXT:    ret void
242;
243entry:
244  %a.10 = and i32 %a, 127
245  br i1 %cond, label %bb1, label %bb2
246
247bb1:
248  br label %pred
249
250bb2:
251  br label %pred
252
253pred:
254  %p = phi i32 [ %a.10, %bb1 ], [ undef, %bb2 ]
255  %bc.1 = icmp ugt i32 %a, %p
256  br i1 %bc.1, label %true, label %false
257
258true:
259  %f.1 = icmp eq i32 %a, 300
260  call void @use(i1 %f.1)
261
262  %a.127.2 = and i32 %p, 127
263  call void @use.i32(i32 %a.127.2)
264
265  ret void
266
267false:
268  ret void
269}
270