1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8)
6 define i8 @ssub_no_overflow_due_to_or_conds(i8 %a, i8 %b) {
7 ; CHECK-LABEL: @ssub_no_overflow_due_to_or_conds(
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:%.*]]
14 ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[B]], [[A]]
15 ; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
17 ; CHECK-NEXT: ret i8 [[TMP0]]
19 ; CHECK-NEXT: ret i8 0
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
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
33 %res = extractvalue { i8, i1 } %op, 0
40 declare void @use_res({ i8, i1 })
42 define 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(
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:%.*]]
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:%.*]]
55 ; CHECK-NEXT: ret i8 [[TMP0]]
57 ; CHECK-NEXT: ret i8 0
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
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
72 %res = extractvalue { i8, i1 } %op, 0
79 define i8 @ssub_no_overflow_due_to_and_conds(i8 %a, i8 %b) {
80 ; CHECK-LABEL: @ssub_no_overflow_due_to_and_conds(
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:%.*]]
87 ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[B]], [[A]]
88 ; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
90 ; CHECK-NEXT: ret i8 [[TMP0]]
92 ; CHECK-NEXT: ret i8 0
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
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
106 %res = extractvalue { i8, i1 } %op, 0
113 define 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(
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:%.*]]
121 ; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
123 ; CHECK-NEXT: ret i8 20
125 ; CHECK-NEXT: ret i8 0
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
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
145 define i8 @ssub_may_overflow1(i8 %a, i8 %b) {
146 ; CHECK-LABEL: @ssub_may_overflow1(
148 ; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
149 ; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
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:%.*]]
155 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
156 ; CHECK-NEXT: ret i8 [[RES]]
158 ; CHECK-NEXT: ret i8 0
161 %c.1 = icmp sge i8 %b, %a
162 br i1 %c.1, label %math, label %exit.fail
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
170 %res = extractvalue { i8, i1 } %op, 0
177 define i8 @ssub_may_overflow2(i8 %a, i8 %b) {
178 ; CHECK-LABEL: @ssub_may_overflow2(
180 ; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[A:%.*]], 0
181 ; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
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:%.*]]
187 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
188 ; CHECK-NEXT: ret i8 [[RES]]
190 ; CHECK-NEXT: ret i8 0
193 %c.1 = icmp sge i8 %a, 0
194 br i1 %c.1, label %math, label %exit.fail
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
202 %res = extractvalue { i8, i1 } %op, 0
209 define i8 @ssub_may_overflow3(i8 %a, i8 %b) {
210 ; CHECK-LABEL: @ssub_may_overflow3(
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:%.*]]
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:%.*]]
221 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
222 ; CHECK-NEXT: ret i8 [[RES]]
224 ; CHECK-NEXT: ret i8 0
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
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
238 %res = extractvalue { i8, i1 } %op, 0
245 define i8 @ssub_may_overflow4(i8 %a, i8 %b) {
246 ; CHECK-LABEL: @ssub_may_overflow4(
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:%.*]]
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:%.*]]
257 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
258 ; CHECK-NEXT: ret i8 [[RES]]
260 ; CHECK-NEXT: ret i8 0
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
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
274 %res = extractvalue { i8, i1 } %op, 0
281 define i8 @ssub_may_overflow5(i8 %a, i8 %b) {
282 ; CHECK-LABEL: @ssub_may_overflow5(
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:%.*]]
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:%.*]]
293 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
294 ; CHECK-NEXT: ret i8 [[RES]]
296 ; CHECK-NEXT: ret i8 0
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
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
310 %res = extractvalue { i8, i1 } %op, 0
317 define i8 @ssub_may_overflow6(i8 %a, i8 %b) {
318 ; CHECK-LABEL: @ssub_may_overflow6(
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:%.*]]
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:%.*]]
329 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
330 ; CHECK-NEXT: ret i8 [[RES]]
332 ; CHECK-NEXT: ret i8 0
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
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
346 %res = extractvalue { i8, i1 } %op, 0