xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/ssub-with-overflow.ll (revision 8e6d481f3b7da224f8dd28a06fa91602e824db18)
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.ssub.with.overflow.i8(i8, i8)
5
6define i8 @ssub_no_overflow_due_to_or_conds(i8 %a, i8 %b) {
7; CHECK-LABEL: @ssub_no_overflow_due_to_or_conds(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[C_1:%.*]] = icmp sle i8 [[B:%.*]], [[A:%.*]]
10; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i8 [[A]], 0
11; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[C_2]], [[C_1]]
12; CHECK-NEXT:    br i1 [[OR_COND]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
13; CHECK:       math:
14; CHECK-NEXT:    [[TMP0:%.*]] = sub i8 [[B]], [[A]]
15; CHECK-NEXT:    br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
16; CHECK:       exit.ok:
17; CHECK-NEXT:    ret i8 [[TMP0]]
18; CHECK:       exit.fail:
19; CHECK-NEXT:    ret i8 0
20;
21entry:
22  %c.1 = icmp sle i8 %b, %a
23  %c.2 = icmp slt i8 %a, 0
24  %or.cond = or i1 %c.2, %c.1
25  br i1 %or.cond, label %exit.fail, label %math
26
27math:
28  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
29  %status = extractvalue { i8, i1 } %op, 1
30  br i1 %status, label %exit.fail, label %exit.ok
31
32exit.ok:
33  %res = extractvalue { i8, i1 } %op, 0
34  ret i8 %res
35
36exit.fail:
37  ret i8 0
38}
39
40declare void @use_res({ i8, i1 })
41
42define i8 @ssub_no_overflow_due_to_or_conds_result_used(i8 %a, i8 %b) {
43; CHECK-LABEL: @ssub_no_overflow_due_to_or_conds_result_used(
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    [[C_1:%.*]] = icmp sle i8 [[B:%.*]], [[A:%.*]]
46; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i8 [[A]], 0
47; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[C_2]], [[C_1]]
48; CHECK-NEXT:    br i1 [[OR_COND]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
49; CHECK:       math:
50; CHECK-NEXT:    [[TMP0:%.*]] = sub i8 [[B]], [[A]]
51; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B]], i8 [[A]])
52; CHECK-NEXT:    call void @use_res({ i8, i1 } [[OP]])
53; CHECK-NEXT:    br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
54; CHECK:       exit.ok:
55; CHECK-NEXT:    ret i8 [[TMP0]]
56; CHECK:       exit.fail:
57; CHECK-NEXT:    ret i8 0
58;
59entry:
60  %c.1 = icmp sle i8 %b, %a
61  %c.2 = icmp slt i8 %a, 0
62  %or.cond = or i1 %c.2, %c.1
63  br i1 %or.cond, label %exit.fail, label %math
64
65math:
66  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
67  call void @use_res({ i8, i1 } %op)
68  %status = extractvalue { i8, i1 } %op, 1
69  br i1 %status, label %exit.fail, label %exit.ok
70
71exit.ok:
72  %res = extractvalue { i8, i1 } %op, 0
73  ret i8 %res
74
75exit.fail:
76  ret i8 0
77}
78
79define i8 @ssub_no_overflow_due_to_and_conds(i8 %a, i8 %b) {
80; CHECK-LABEL: @ssub_no_overflow_due_to_and_conds(
81; CHECK-NEXT:  entry:
82; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
83; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
84; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
85; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
86; CHECK:       math:
87; CHECK-NEXT:    [[TMP0:%.*]] = sub i8 [[B]], [[A]]
88; CHECK-NEXT:    br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
89; CHECK:       exit.ok:
90; CHECK-NEXT:    ret i8 [[TMP0]]
91; CHECK:       exit.fail:
92; CHECK-NEXT:    ret i8 0
93;
94entry:
95  %c.1 = icmp sge i8 %b, %a
96  %c.2 = icmp sge i8 %a, 0
97  %and = and i1 %c.2, %c.1
98  br i1 %and, label %math, label %exit.fail
99
100math:
101  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
102  %status = extractvalue { i8, i1 } %op, 1
103  br i1 %status, label %exit.fail, label %exit.ok
104
105exit.ok:
106  %res = extractvalue { i8, i1 } %op, 0
107  ret i8 %res
108
109exit.fail:
110  ret i8 0
111}
112
113define i8 @ssub_no_overflow_due_to_and_conds_sub_result_not_used(i8 %a, i8 %b) {
114; CHECK-LABEL: @ssub_no_overflow_due_to_and_conds_sub_result_not_used(
115; CHECK-NEXT:  entry:
116; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
117; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
118; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
119; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
120; CHECK:       math:
121; CHECK-NEXT:    br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
122; CHECK:       exit.ok:
123; CHECK-NEXT:    ret i8 20
124; CHECK:       exit.fail:
125; CHECK-NEXT:    ret i8 0
126;
127entry:
128  %c.1 = icmp sge i8 %b, %a
129  %c.2 = icmp sge i8 %a, 0
130  %and = and i1 %c.2, %c.1
131  br i1 %and, label %math, label %exit.fail
132
133math:
134  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
135  %status = extractvalue { i8, i1 } %op, 1
136  br i1 %status, label %exit.fail, label %exit.ok
137
138exit.ok:
139  ret i8 20
140
141exit.fail:
142  ret i8 0
143}
144
145define i8 @ssub_may_overflow1(i8 %a, i8 %b) {
146; CHECK-LABEL: @ssub_may_overflow1(
147; CHECK-NEXT:  entry:
148; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
149; CHECK-NEXT:    br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
150; CHECK:       math:
151; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B]], i8 [[A]])
152; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
153; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
154; CHECK:       exit.ok:
155; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
156; CHECK-NEXT:    ret i8 [[RES]]
157; CHECK:       exit.fail:
158; CHECK-NEXT:    ret i8 0
159;
160entry:
161  %c.1 = icmp sge i8 %b, %a
162  br i1 %c.1, label %math, label %exit.fail
163
164math:
165  %op = tail call { i8, i1 } @llvm.ssub.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  %res = extractvalue { i8, i1 } %op, 0
171  ret i8 %res
172
173exit.fail:
174  ret i8 0
175}
176
177define i8 @ssub_may_overflow2(i8 %a, i8 %b) {
178; CHECK-LABEL: @ssub_may_overflow2(
179; CHECK-NEXT:  entry:
180; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[A:%.*]], 0
181; CHECK-NEXT:    br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
182; CHECK:       math:
183; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B:%.*]], i8 [[A]])
184; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
185; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
186; CHECK:       exit.ok:
187; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
188; CHECK-NEXT:    ret i8 [[RES]]
189; CHECK:       exit.fail:
190; CHECK-NEXT:    ret i8 0
191;
192entry:
193  %c.1 = icmp sge i8 %a, 0
194  br i1 %c.1, label %math, label %exit.fail
195
196math:
197  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
198  %status = extractvalue { i8, i1 } %op, 1
199  br i1 %status, label %exit.fail, label %exit.ok
200
201exit.ok:
202  %res = extractvalue { i8, i1 } %op, 0
203  ret i8 %res
204
205exit.fail:
206  ret i8 0
207}
208
209define i8 @ssub_may_overflow3(i8 %a, i8 %b) {
210; CHECK-LABEL: @ssub_may_overflow3(
211; CHECK-NEXT:  entry:
212; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
213; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], -1
214; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
215; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
216; CHECK:       math:
217; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.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 sge i8 %b, %a
228  %c.2 = icmp sge i8 %a, -1
229  %and = and i1 %c.2, %c.1
230  br i1 %and, label %math, label %exit.fail
231
232math:
233  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
234  %status = extractvalue { i8, i1 } %op, 1
235  br i1 %status, label %exit.fail, label %exit.ok
236
237exit.ok:
238  %res = extractvalue { i8, i1 } %op, 0
239  ret i8 %res
240
241exit.fail:
242  ret i8 0
243}
244
245define i8 @ssub_may_overflow4(i8 %a, i8 %b) {
246; CHECK-LABEL: @ssub_may_overflow4(
247; CHECK-NEXT:  entry:
248; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
249; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
250; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
251; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
252; CHECK:       math:
253; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B]], i8 [[A]])
254; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
255; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
256; CHECK:       exit.ok:
257; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
258; CHECK-NEXT:    ret i8 [[RES]]
259; CHECK:       exit.fail:
260; CHECK-NEXT:    ret i8 0
261;
262entry:
263  %c.1 = icmp uge i8 %b, %a
264  %c.2 = icmp sge i8 %a, 0
265  %and = and i1 %c.2, %c.1
266  br i1 %and, label %math, label %exit.fail
267
268math:
269  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
270  %status = extractvalue { i8, i1 } %op, 1
271  br i1 %status, label %exit.fail, label %exit.ok
272
273exit.ok:
274  %res = extractvalue { i8, i1 } %op, 0
275  ret i8 %res
276
277exit.fail:
278  ret i8 0
279}
280
281define i8 @ssub_may_overflow5(i8 %a, i8 %b) {
282; CHECK-LABEL: @ssub_may_overflow5(
283; CHECK-NEXT:  entry:
284; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
285; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[B]], 0
286; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
287; CHECK-NEXT:    br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
288; CHECK:       math:
289; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B]], i8 [[A]])
290; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
291; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
292; CHECK:       exit.ok:
293; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
294; CHECK-NEXT:    ret i8 [[RES]]
295; CHECK:       exit.fail:
296; CHECK-NEXT:    ret i8 0
297;
298entry:
299  %c.1 = icmp sge i8 %b, %a
300  %c.2 = icmp sge i8 %b, 0
301  %and = and i1 %c.2, %c.1
302  br i1 %and, label %math, label %exit.fail
303
304math:
305  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
306  %status = extractvalue { i8, i1 } %op, 1
307  br i1 %status, label %exit.fail, label %exit.ok
308
309exit.ok:
310  %res = extractvalue { i8, i1 } %op, 0
311  ret i8 %res
312
313exit.fail:
314  ret i8 0
315}
316
317define i8 @ssub_may_overflow6(i8 %a, i8 %b) {
318; CHECK-LABEL: @ssub_may_overflow6(
319; CHECK-NEXT:  entry:
320; CHECK-NEXT:    [[C_1:%.*]] = icmp sle i8 [[B:%.*]], [[A:%.*]]
321; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i8 [[B]], 0
322; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[C_2]], [[C_1]]
323; CHECK-NEXT:    br i1 [[OR_COND]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
324; CHECK:       math:
325; CHECK-NEXT:    [[OP:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[B]], i8 [[A]])
326; CHECK-NEXT:    [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
327; CHECK-NEXT:    br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
328; CHECK:       exit.ok:
329; CHECK-NEXT:    [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
330; CHECK-NEXT:    ret i8 [[RES]]
331; CHECK:       exit.fail:
332; CHECK-NEXT:    ret i8 0
333;
334entry:
335  %c.1 = icmp sle i8 %b, %a
336  %c.2 = icmp slt i8 %b, 0
337  %or.cond = or i1 %c.2, %c.1
338  br i1 %or.cond, label %exit.fail, label %math
339
340math:
341  %op = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %b, i8 %a)
342  %status = extractvalue { i8, i1 } %op, 1
343  br i1 %status, label %exit.fail, label %exit.ok
344
345exit.ok:
346  %res = extractvalue { i8, i1 } %op, 0
347  ret i8 %res
348
349exit.fail:
350  ret i8 0
351}
352