xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/wrapping-math.ll (revision 13ffde316a8541d77116bd18f73efada236617f3)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4define i1 @wrapping_add_unknown_1(i8 %a) {
5; CHECK-LABEL: @wrapping_add_unknown_1(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[A:%.*]], -1
8; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[SUB]], 0
9; CHECK-NEXT:    ret i1 [[CMP]]
10;
11entry:
12  %sub = add i8 %a, -1
13  %cmp = icmp eq i8 %sub, 0
14  ret i1 %cmp
15}
16
17define i1 @wrapping_add_known_1(i8 %a) {
18; CHECK-LABEL: @wrapping_add_known_1(
19; CHECK-NEXT:  entry:
20; CHECK-NEXT:    [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1
21; CHECK-NEXT:    br i1 [[PRE]], label [[THEN:%.*]], label [[ELSE:%.*]]
22; CHECK:       then:
23; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[A]], -1
24; CHECK-NEXT:    ret i1 true
25; CHECK:       else:
26; CHECK-NEXT:    [[SUB_2:%.*]] = add i8 [[A]], -1
27; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i8 [[SUB_2]], 0
28; CHECK-NEXT:    ret i1 [[C_2]]
29;
30entry:
31  %pre = icmp eq i8 %a, 1
32  br i1 %pre, label %then, label %else
33
34then:
35  %sub.1 = add i8 %a, -1
36  %c.1 = icmp eq i8 %sub.1, 0
37  ret i1 %c.1
38
39else:
40  %sub.2 = add i8 %a, -1
41  %c.2 = icmp eq i8 %sub.2, 0
42  ret i1 %c.2
43}
44
45define i1 @wrapping_add_unknown_2(i8 %a) {
46; CHECK-LABEL: @wrapping_add_unknown_2(
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 0
49; CHECK-NEXT:    br i1 [[PRE]], label [[THEN:%.*]], label [[ELSE:%.*]]
50; CHECK:       then:
51; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[A]], -1
52; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i8 [[SUB_1]], 0
53; CHECK-NEXT:    ret i1 [[C_1]]
54; CHECK:       else:
55; CHECK-NEXT:    [[SUB_2:%.*]] = add i8 [[A]], -1
56; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i8 [[SUB_2]], 0
57; CHECK-NEXT:    ret i1 [[C_2]]
58;
59entry:
60  %pre = icmp eq i8 %a, 0
61  br i1 %pre, label %then, label %else
62
63then:
64  %sub.1 = add i8 %a, -1
65  %c.1 = icmp eq i8 %sub.1, 0
66  ret i1 %c.1
67
68else:
69  %sub.2 = add i8 %a, -1
70  %c.2 = icmp eq i8 %sub.2, 0
71  ret i1 %c.2
72}
73
74; Test from https://github.com/llvm/llvm-project/issues/48253.
75define i1 @test_48253_eq_ne(i8 %a, i8 %b) {
76; CHECK-LABEL: @test_48253_eq_ne(
77; CHECK-NEXT:  entry:
78; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]
79; CHECK-NEXT:    [[CMP_2:%.*]] = icmp eq i8 [[B]], 0
80; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
81; CHECK-NEXT:    br i1 [[OR]], label [[EXIT_1:%.*]], label [[IF_END:%.*]]
82; CHECK:       if.end:
83; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[B]], -1
84; CHECK-NEXT:    [[SUB_2:%.*]] = add i8 [[B]], -2
85; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[SUB_2]], [[A]]
86; CHECK-NEXT:    [[XOR_1:%.*]] = xor i1 true, [[C_2]]
87; CHECK-NEXT:    ret i1 [[XOR_1]]
88; CHECK:       exit.1:
89; CHECK-NEXT:    [[SUB_3:%.*]] = add i8 [[B]], -1
90; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i8 [[SUB_3]], [[A]]
91; CHECK-NEXT:    [[SUB_4:%.*]] = add i8 [[B]], -2
92; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[SUB_4]], [[A]]
93; CHECK-NEXT:    [[XOR_2:%.*]] = xor i1 [[C_3]], [[C_4]]
94; CHECK-NEXT:    ret i1 [[XOR_2]]
95;
96entry:
97  %cmp.1 = icmp ne i8 %a, %b
98  %cmp.2 = icmp eq i8 %b, 0
99  %or = or i1 %cmp.1, %cmp.2
100  br i1 %or, label %exit.1, label %if.end
101
102if.end:
103  %sub.1 = add i8 %b, -1
104  %t.1 = icmp ult i8 %sub.1, %a
105  %sub.2 = add i8 %b, -2
106  %c.2 = icmp ult i8 %sub.2, %a
107  %xor.1 = xor i1 %t.1, %c.2
108  ret i1 %xor.1
109
110exit.1:
111  %sub.3 = add i8 %b, -1
112  %c.3 = icmp ult i8 %sub.3, %a
113  %sub.4 = add i8 %b, -2
114  %c.4 = icmp ult i8 %sub.4, %a
115  %xor.2 = xor i1 %c.3, %c.4
116  ret i1 %xor.2
117}
118
119define i1 @test_ult(i8 %a, i8 %b) {
120; CHECK-LABEL: @test_ult(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[CMP_1:%.*]] = icmp uge i8 [[A:%.*]], 20
123; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i8 [[A]], [[B:%.*]]
124; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
125; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[A]], -1
126; CHECK-NEXT:    [[SUB_2:%.*]] = add i8 [[A]], -2
127; CHECK-NEXT:    [[SUB_3:%.*]] = add i8 [[A]], -20
128; CHECK-NEXT:    [[SUB_4:%.*]] = add i8 [[A]], 21
129; CHECK-NEXT:    [[ADD_1:%.*]] = add i8 [[A]], 1
130; CHECK-NEXT:    br i1 [[AND]], label [[IF_END:%.*]], label [[EXIT_1:%.*]]
131; CHECK:       if.end:
132; CHECK-NEXT:    [[XOR_1:%.*]] = xor i1 true, true
133; CHECK-NEXT:    [[XOR_2:%.*]] = xor i1 [[XOR_1]], true
134; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[SUB_4]], [[B]]
135; CHECK-NEXT:    [[XOR_3:%.*]] = xor i1 [[XOR_2]], [[C_1]]
136; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[ADD_1]], [[B]]
137; CHECK-NEXT:    [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[C_2]]
138; CHECK-NEXT:    ret i1 [[XOR_4]]
139; CHECK:       exit.1:
140; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i8 [[SUB_1]], [[B]]
141; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[SUB_2]], [[B]]
142; CHECK-NEXT:    [[XOR_5:%.*]] = xor i1 [[C_3]], [[C_4]]
143; CHECK-NEXT:    [[C_5:%.*]] = icmp ult i8 [[SUB_3]], [[B]]
144; CHECK-NEXT:    [[XOR_6:%.*]] = xor i1 [[XOR_5]], [[C_5]]
145; CHECK-NEXT:    [[C_6:%.*]] = icmp ult i8 [[SUB_4]], [[B]]
146; CHECK-NEXT:    [[XOR_7:%.*]] = xor i1 [[XOR_6]], [[C_6]]
147; CHECK-NEXT:    [[C_7:%.*]] = icmp ult i8 [[ADD_1]], [[B]]
148; CHECK-NEXT:    [[XOR_8:%.*]] = xor i1 [[XOR_7]], [[C_7]]
149; CHECK-NEXT:    ret i1 [[XOR_8]]
150;
151entry:
152  %cmp.1 = icmp uge i8 %a, 20
153  %cmp.2 = icmp ult i8 %a, %b
154  %and = and i1 %cmp.1, %cmp.2
155  %sub.1 = add i8 %a, -1
156  %sub.2 = add i8 %a, -2
157  %sub.3 = add i8 %a, -20
158  %sub.4 = add i8 %a, 21
159  %add.1 = add i8 %a, 1
160  br i1 %and, label %if.end, label %exit.1
161
162if.end:
163  %t.1 = icmp ult i8 %sub.1, %b
164  %t.2 = icmp ult i8 %sub.2, %b
165  %xor.1 = xor i1 %t.1, %t.2
166
167  %t.3 = icmp ult i8 %sub.3, %b
168  %xor.2 = xor i1 %xor.1, %t.3
169
170  %c.1 = icmp ult i8 %sub.4, %b
171  %xor.3 = xor i1 %xor.2, %c.1
172
173  %c.2 = icmp ult i8 %add.1, %b
174  %xor.4 = xor i1 %xor.3, %c.2
175  ret i1 %xor.4
176
177exit.1:
178  %c.3 = icmp ult i8 %sub.1, %b
179  %c.4 = icmp ult i8 %sub.2, %b
180  %xor.5 = xor i1 %c.3, %c.4
181
182  %c.5 = icmp ult i8 %sub.3, %b
183  %xor.6 = xor i1 %xor.5, %c.5
184
185  %c.6 = icmp ult i8 %sub.4, %b
186  %xor.7 = xor i1 %xor.6, %c.6
187
188  %c.7 = icmp ult i8 %add.1, %b
189  %xor.8 = xor i1 %xor.7, %c.7
190  ret i1 %xor.8
191}
192
193define i1 @test_slt(i8 %a, i8 %b) {
194; CHECK-LABEL: @test_slt(
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    [[CMP_1:%.*]] = icmp sge i8 [[A:%.*]], 20
197; CHECK-NEXT:    [[CMP_2:%.*]] = icmp slt i8 [[A]], [[B:%.*]]
198; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
199; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[A]], -1
200; CHECK-NEXT:    [[SUB_2:%.*]] = add i8 [[A]], -2
201; CHECK-NEXT:    [[SUB_3:%.*]] = add i8 [[A]], -20
202; CHECK-NEXT:    [[SUB_4:%.*]] = add i8 [[A]], 21
203; CHECK-NEXT:    [[ADD_1:%.*]] = add i8 [[A]], 1
204; CHECK-NEXT:    br i1 [[AND]], label [[IF_END:%.*]], label [[EXIT_1:%.*]]
205; CHECK:       if.end:
206; CHECK-NEXT:    [[T_1:%.*]] = icmp slt i8 [[SUB_1]], [[B]]
207; CHECK-NEXT:    [[T_2:%.*]] = icmp slt i8 [[SUB_2]], [[B]]
208; CHECK-NEXT:    [[XOR_1:%.*]] = xor i1 [[T_1]], [[T_2]]
209; CHECK-NEXT:    [[T_3:%.*]] = icmp slt i8 [[SUB_3]], [[B]]
210; CHECK-NEXT:    [[XOR_2:%.*]] = xor i1 [[XOR_1]], [[T_3]]
211; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i8 [[SUB_4]], [[B]]
212; CHECK-NEXT:    [[XOR_3:%.*]] = xor i1 [[XOR_2]], [[C_1]]
213; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i8 [[ADD_1]], [[B]]
214; CHECK-NEXT:    [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[C_2]]
215; CHECK-NEXT:    ret i1 [[XOR_4]]
216; CHECK:       exit.1:
217; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i8 [[SUB_1]], [[B]]
218; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i8 [[SUB_2]], [[B]]
219; CHECK-NEXT:    [[XOR_5:%.*]] = xor i1 [[C_3]], [[C_4]]
220; CHECK-NEXT:    [[C_5:%.*]] = icmp slt i8 [[SUB_3]], [[B]]
221; CHECK-NEXT:    [[XOR_6:%.*]] = xor i1 [[XOR_5]], [[C_5]]
222; CHECK-NEXT:    [[C_6:%.*]] = icmp slt i8 [[SUB_4]], [[B]]
223; CHECK-NEXT:    [[XOR_7:%.*]] = xor i1 [[XOR_6]], [[C_6]]
224; CHECK-NEXT:    [[C_7:%.*]] = icmp slt i8 [[ADD_1]], [[B]]
225; CHECK-NEXT:    [[XOR_8:%.*]] = xor i1 [[XOR_7]], [[C_7]]
226; CHECK-NEXT:    ret i1 [[XOR_8]]
227;
228entry:
229  %cmp.1 = icmp sge i8 %a, 20
230  %cmp.2 = icmp slt i8 %a, %b
231  %and = and i1 %cmp.1, %cmp.2
232  %sub.1 = add i8 %a, -1
233  %sub.2 = add i8 %a, -2
234  %sub.3 = add i8 %a, -20
235  %sub.4 = add i8 %a, 21
236  %add.1 = add i8 %a, 1
237  br i1 %and, label %if.end, label %exit.1
238
239if.end:
240  %t.1 = icmp slt i8 %sub.1, %b
241  %t.2 = icmp slt i8 %sub.2, %b
242  %xor.1 = xor i1 %t.1, %t.2
243
244  %t.3 = icmp slt i8 %sub.3, %b
245  %xor.2 = xor i1 %xor.1, %t.3
246
247  %c.1 = icmp slt i8 %sub.4, %b
248  %xor.3 = xor i1 %xor.2, %c.1
249
250  %c.2 = icmp slt i8 %add.1, %b
251  %xor.4 = xor i1 %xor.3, %c.2
252  ret i1 %xor.4
253
254exit.1:
255  %c.3 = icmp slt i8 %sub.1, %b
256  %c.4 = icmp slt i8 %sub.2, %b
257  %xor.5 = xor i1 %c.3, %c.4
258
259  %c.5 = icmp slt i8 %sub.3, %b
260  %xor.6 = xor i1 %xor.5, %c.5
261
262  %c.6 = icmp slt i8 %sub.4, %b
263  %xor.7 = xor i1 %xor.6, %c.6
264
265  %c.7 = icmp slt i8 %add.1, %b
266  %xor.8 = xor i1 %xor.7, %c.7
267  ret i1 %xor.8
268}
269
270define i1 @wrapping_add_known_1_add_nuw(i8 %a) {
271; CHECK-LABEL: @wrapping_add_known_1_add_nuw(
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1
274; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
275; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[A]], -1
276; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[SUB_1]], 10
277; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
278; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], false
279; CHECK-NEXT:    ret i1 [[RES_2]]
280;
281entry:
282  %pre = icmp eq i8 %a, 1
283  call void @llvm.assume(i1 %pre)
284  %sub.1 = add i8 %a, -1
285  %add = add nuw i8 %sub.1, 10
286  %t.1 = icmp uge i8 %add, 10
287  %t.2 = icmp ule i8 %add, 10
288  %res.1 = xor i1 %t.1, %t.2
289  %f.1 = icmp ult i8 %add, 10
290  %res.2 = xor i1 %res.1, %f.1
291  ret i1 %res.2
292}
293
294define i1 @add_nuw_wrapping_add_known_1(i8 %a) {
295; CHECK-LABEL: @add_nuw_wrapping_add_known_1(
296; CHECK-NEXT:  entry:
297; CHECK-NEXT:    [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1
298; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
299; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[A]], 10
300; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[ADD]], -1
301; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
302; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], false
303; CHECK-NEXT:    ret i1 [[RES_2]]
304;
305entry:
306  %pre = icmp eq i8 %a, 1
307  call void @llvm.assume(i1 %pre)
308  %add = add nuw i8 %a, 10
309  %sub.1 = add i8 %add, -1
310  %t.1 = icmp uge i8 %sub.1, 10
311  %t.2 = icmp ule i8 %sub.1, 10
312  %res.1 = xor i1 %t.1, %t.2
313  %f.1 = icmp ult i8 %sub.1, 10
314  %res.2 = xor i1 %res.1, %f.1
315  ret i1 %res.2
316}
317
318define i1 @add_nuw_wrapping_add_not_known_1(i8 %a) {
319; CHECK-LABEL: @add_nuw_wrapping_add_not_known_1(
320; CHECK-NEXT:  entry:
321; CHECK-NEXT:    [[PRE:%.*]] = icmp sge i8 [[A:%.*]], -1
322; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
323; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[A]], 10
324; CHECK-NEXT:    [[SUB_1:%.*]] = add i8 [[ADD]], -1
325; CHECK-NEXT:    [[T_1:%.*]] = icmp uge i8 [[SUB_1]], 10
326; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[SUB_1]], 10
327; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
328; CHECK-NEXT:    [[F_1:%.*]] = icmp ult i8 [[SUB_1]], 10
329; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[F_1]]
330; CHECK-NEXT:    ret i1 [[RES_2]]
331;
332entry:
333  %pre = icmp sge i8 %a, -1
334  call void @llvm.assume(i1 %pre)
335  %add = add nuw i8 %a, 10
336  %sub.1 = add i8 %add, -1
337  %t.1 = icmp uge i8 %sub.1, 10
338  %t.2 = icmp ule i8 %sub.1, 10
339  %res.1 = xor i1 %t.1, %t.2
340  %f.1 = icmp ult i8 %sub.1, 10
341  %res.2 = xor i1 %res.1, %f.1
342  ret i1 %res.2
343}
344
345declare void @llvm.assume(i1)
346