xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/usub-with-overflow.ll (revision 98e016d99732dc8fef8cfd61d6ce1edd042309a1)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8)
5
6define i8 @usub_no_overflow_due_to_cmp_condition(i8 %a, i8 %b) {
7; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
10; CHECK-NEXT:    br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
11; CHECK:       math:
12; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
13; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
14; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
15; CHECK:       exit.ok:
16; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
17; CHECK-NEXT:    ret i8 [[RES]]
18; CHECK:       exit.fail:
19; CHECK-NEXT:    ret i8 0
20;
21entry:
22  %c.1 = icmp uge i8 %b, %a
23  br i1 %c.1, label %math, label %exit.fail
24
25math:
26  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
27  %status = extractvalue { i8, i1 } %op, 1
28  br i1 %status, label %exit.fail, label %exit.ok
29
30exit.ok:
31  %res = extractvalue { i8, i1 } %op, 0
32  ret i8 %res
33
34exit.fail:
35  ret i8 0
36}
37
38define i8 @usub_no_overflow_due_to_cmp_condition2(i8 %a, i8 %b) {
39; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition2(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
42; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
43; CHECK:       math:
44; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
45; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
46; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
47; CHECK:       exit.ok:
48; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
49; CHECK-NEXT:    ret i8 [[RES]]
50; CHECK:       exit.fail:
51; CHECK-NEXT:    ret i8 0
52;
53entry:
54  %c.1 = icmp ule i8 %b, %a
55  br i1 %c.1, label %exit.fail, label %math
56
57math:
58  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
59  %status = extractvalue { i8, i1 } %op, 1
60  br i1 %status, label %exit.fail, label %exit.ok
61
62exit.ok:
63  %res = extractvalue { i8, i1 } %op, 0
64  ret i8 %res
65
66exit.fail:
67  ret i8 0
68}
69
70declare void @use_res({ i8, i1 })
71
72define i8 @sub_no_overflow_due_to_cmp_condition_result_used(i8 %a, i8 %b) {
73; CHECK-LABEL: @sub_no_overflow_due_to_cmp_condition_result_used(
74; CHECK-NEXT:  entry:
75; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
76; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
77; CHECK:       math:
78; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
79; CHECK-NEXT:    call void @use_res({ i8, i1 } [[OP]])
80; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
81; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
82; CHECK:       exit.ok:
83; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
84; CHECK-NEXT:    ret i8 [[RES]]
85; CHECK:       exit.fail:
86; CHECK-NEXT:    ret i8 0
87;
88entry:
89  %c.1 = icmp ule i8 %b, %a
90  br i1 %c.1, label %exit.fail, label %math
91
92math:
93  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
94  call void @use_res({ i8, i1 } %op)
95  %status = extractvalue { i8, i1 } %op, 1
96  br i1 %status, label %exit.fail, label %exit.ok
97
98exit.ok:
99  %res = extractvalue { i8, i1 } %op, 0
100  ret i8 %res
101
102exit.fail:
103  ret i8 0
104}
105
106define i8 @usub_no_overflow_due_to_or_conds(i8 %a, i8 %b) {
107; CHECK-LABEL: @usub_no_overflow_due_to_or_conds(
108; CHECK-NEXT:  entry:
109; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
110; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i8 [[A]], 0
111; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
112; CHECK-NEXT:    br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
113; CHECK:       math:
114; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
115; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
116; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
117; CHECK:       exit.ok:
118; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
119; CHECK-NEXT:    ret i8 [[RES]]
120; CHECK:       exit.fail:
121; CHECK-NEXT:    ret i8 0
122;
123entry:
124  %c.1 = icmp ule i8 %b, %a
125  %c.2 = icmp ule i8 %a, 0
126  %or = or i1 %c.2, %c.1
127  br i1 %or, label %exit.fail, label %math
128
129math:
130  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
131  %status = extractvalue { i8, i1 } %op, 1
132  br i1 %status, label %exit.fail, label %exit.ok
133
134exit.ok:
135  %res = extractvalue { i8, i1 } %op, 0
136  ret i8 %res
137
138exit.fail:
139  ret i8 0
140}
141
142define i8 @usub_no_overflow_due_to_or_conds_sub_result_not_used(i8 %a, i8 %b) {
143; CHECK-LABEL: @usub_no_overflow_due_to_or_conds_sub_result_not_used(
144; CHECK-NEXT:  entry:
145; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
146; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i8 [[A]], 0
147; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
148; CHECK-NEXT:    br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
149; CHECK:       math:
150; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
151; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
152; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
153; CHECK:       exit.ok:
154; CHECK-NEXT:    ret i8 20
155; CHECK:       exit.fail:
156; CHECK-NEXT:    ret i8 0
157;
158entry:
159  %c.1 = icmp ule i8 %b, %a
160  %c.2 = icmp ule i8 %a, 0
161  %or = or i1 %c.2, %c.1
162  br i1 %or, label %exit.fail, label %math
163
164math:
165  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
166  %status = extractvalue { i8, i1 } %op, 1
167  br i1 %status, label %exit.fail, label %exit.ok
168
169exit.ok:
170  ret i8 20
171
172exit.fail:
173  ret i8 0
174}
175
176define i8 @usub_no_overflow_due_to_and_conds(i8 %a, i8 %b) {
177; CHECK-LABEL: @usub_no_overflow_due_to_and_conds(
178; CHECK-NEXT:  entry:
179; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
180; CHECK-NEXT:    [[C_2:%.*]] = icmp uge i8 [[A]], -1
181; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
182; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
183; CHECK:       math:
184; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
185; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
186; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
187; CHECK:       exit.ok:
188; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
189; CHECK-NEXT:    ret i8 [[RES]]
190; CHECK:       exit.fail:
191; CHECK-NEXT:    ret i8 0
192;
193entry:
194  %c.1 = icmp uge i8 %b, %a
195  %c.2 = icmp uge i8 %a, -1
196  %and = and i1 %c.2, %c.1
197  br i1 %and, label %math, label %exit.fail
198
199math:
200  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
201  %status = extractvalue { i8, i1 } %op, 1
202  br i1 %status, label %exit.fail, label %exit.ok
203
204exit.ok:
205  %res = extractvalue { i8, i1 } %op, 0
206  ret i8 %res
207
208exit.fail:
209  ret i8 0
210}
211
212define i8 @usub_may_overflow1(i8 %a, i8 %b) {
213; CHECK-LABEL: @usub_may_overflow1(
214; CHECK-NEXT:  entry:
215; CHECK-NEXT:    br i1 true, label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
216; CHECK:       math:
217; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B:%.*]], i8 [[A:%.*]])
218; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
219; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
220; CHECK:       exit.ok:
221; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
222; CHECK-NEXT:    ret i8 [[RES]]
223; CHECK:       exit.fail:
224; CHECK-NEXT:    ret i8 0
225;
226entry:
227  %c.1 = icmp uge i8 %a, 0
228  br i1 %c.1, label %math, label %exit.fail
229
230math:
231  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
232  %status = extractvalue { i8, i1 } %op, 1
233  br i1 %status, label %exit.fail, label %exit.ok
234
235exit.ok:
236  %res = extractvalue { i8, i1 } %op, 0
237  ret i8 %res
238
239exit.fail:
240  ret i8 0
241}
242
243
244define i8 @usub_may_overflow2(i8 %a, i8 %b) {
245; CHECK-LABEL: @usub_may_overflow2(
246; CHECK-NEXT:  entry:
247; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
248; CHECK-NEXT:    br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
249; CHECK:       math:
250; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
251; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
252; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
253; CHECK:       exit.ok:
254; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
255; CHECK-NEXT:    ret i8 [[RES]]
256; CHECK:       exit.fail:
257; CHECK-NEXT:    ret i8 0
258;
259entry:
260  %c.1 = icmp sge i8 %b, %a
261  br i1 %c.1, label %math, label %exit.fail
262
263math:
264  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
265  %status = extractvalue { i8, i1 } %op, 1
266  br i1 %status, label %exit.fail, label %exit.ok
267
268exit.ok:
269  %res = extractvalue { i8, i1 } %op, 0
270  ret i8 %res
271
272exit.fail:
273  ret i8 0
274}
275
276define i8 @usub_may_overflow3(i8 %a, i8 %b) {
277; CHECK-LABEL: @usub_may_overflow3(
278; CHECK-NEXT:  entry:
279; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i8 [[B:%.*]], [[A:%.*]]
280; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
281; CHECK:       math:
282; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
283; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
284; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
285; CHECK:       exit.ok:
286; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
287; CHECK-NEXT:    ret i8 [[RES]]
288; CHECK:       exit.fail:
289; CHECK-NEXT:    ret i8 0
290;
291entry:
292  %c.1 = icmp slt i8 %b, %a
293  br i1 %c.1, label %exit.fail, label %math
294math:
295  %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a)
296  %status = extractvalue { i8, i1 } %op, 1
297  br i1 %status, label %exit.fail, label %exit.ok
298
299exit.ok:
300  %res = extractvalue { i8, i1 } %op, 0
301  ret i8 %res
302
303exit.fail:
304  ret i8 0
305}
306
307