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.usub.with.overflow.i8(i8, i8)
6 define i8 @usub_no_overflow_due_to_cmp_condition(i8 %a, i8 %b) {
7 ; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition(
9 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
10 ; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
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:%.*]]
16 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
17 ; CHECK-NEXT: ret i8 [[RES]]
19 ; CHECK-NEXT: ret i8 0
22 %c.1 = icmp uge i8 %b, %a
23 br i1 %c.1, label %math, label %exit.fail
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
31 %res = extractvalue { i8, i1 } %op, 0
38 define i8 @usub_no_overflow_due_to_cmp_condition2(i8 %a, i8 %b) {
39 ; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition2(
41 ; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
42 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[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:%.*]]
48 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
49 ; CHECK-NEXT: ret i8 [[RES]]
51 ; CHECK-NEXT: ret i8 0
54 %c.1 = icmp ule i8 %b, %a
55 br i1 %c.1, label %exit.fail, label %math
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
63 %res = extractvalue { i8, i1 } %op, 0
70 declare void @use_res({ i8, i1 })
72 define 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(
75 ; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
76 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[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:%.*]]
83 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
84 ; CHECK-NEXT: ret i8 [[RES]]
86 ; CHECK-NEXT: ret i8 0
89 %c.1 = icmp ule i8 %b, %a
90 br i1 %c.1, label %exit.fail, label %math
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
99 %res = extractvalue { i8, i1 } %op, 0
106 define i8 @usub_no_overflow_due_to_or_conds(i8 %a, i8 %b) {
107 ; CHECK-LABEL: @usub_no_overflow_due_to_or_conds(
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:%.*]]
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:%.*]]
118 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
119 ; CHECK-NEXT: ret i8 [[RES]]
121 ; CHECK-NEXT: ret i8 0
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
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
135 %res = extractvalue { i8, i1 } %op, 0
142 define 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(
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:%.*]]
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:%.*]]
154 ; CHECK-NEXT: ret i8 20
156 ; CHECK-NEXT: ret i8 0
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
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
176 define i8 @usub_no_overflow_due_to_and_conds(i8 %a, i8 %b) {
177 ; CHECK-LABEL: @usub_no_overflow_due_to_and_conds(
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:%.*]]
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:%.*]]
188 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
189 ; CHECK-NEXT: ret i8 [[RES]]
191 ; CHECK-NEXT: ret i8 0
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
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
205 %res = extractvalue { i8, i1 } %op, 0
212 define i8 @usub_may_overflow1(i8 %a, i8 %b) {
213 ; CHECK-LABEL: @usub_may_overflow1(
215 ; CHECK-NEXT: br i1 true, label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
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:%.*]]
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 uge i8 %a, 0
228 br i1 %c.1, label %math, label %exit.fail
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
236 %res = extractvalue { i8, i1 } %op, 0
244 define i8 @usub_may_overflow2(i8 %a, i8 %b) {
245 ; CHECK-LABEL: @usub_may_overflow2(
247 ; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]]
248 ; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
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:%.*]]
254 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
255 ; CHECK-NEXT: ret i8 [[RES]]
257 ; CHECK-NEXT: ret i8 0
260 %c.1 = icmp sge i8 %b, %a
261 br i1 %c.1, label %math, label %exit.fail
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
269 %res = extractvalue { i8, i1 } %op, 0
276 define i8 @usub_may_overflow3(i8 %a, i8 %b) {
277 ; CHECK-LABEL: @usub_may_overflow3(
279 ; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[B:%.*]], [[A:%.*]]
280 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[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:%.*]]
286 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
287 ; CHECK-NEXT: ret i8 [[RES]]
289 ; CHECK-NEXT: ret i8 0
292 %c.1 = icmp slt i8 %b, %a
293 br i1 %c.1, label %exit.fail, label %math
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
300 %res = extractvalue { i8, i1 } %op, 0