Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / ssub-with-overflow.ll
blob254a6a662025e62254ffcf04961964caa449019d
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(
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
21 entry:
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
27 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
32 exit.ok:
33   %res = extractvalue { i8, i1 } %op, 0
34   ret i8 %res
36 exit.fail:
37   ret i8 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(
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
59 entry:
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
65 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
71 exit.ok:
72   %res = extractvalue { i8, i1 } %op, 0
73   ret i8 %res
75 exit.fail:
76   ret i8 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(
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
94 entry:
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
100 math:
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
105 exit.ok:
106   %res = extractvalue { i8, i1 } %op, 0
107   ret i8 %res
109 exit.fail:
110   ret i8 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(
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
127 entry:
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
133 math:
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
138 exit.ok:
139   ret i8 20
141 exit.fail:
142   ret i8 0
145 define 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
160 entry:
161   %c.1 = icmp sge i8 %b, %a
162   br i1 %c.1, label %math, label %exit.fail
164 math:
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
169 exit.ok:
170   %res = extractvalue { i8, i1 } %op, 0
171   ret i8 %res
173 exit.fail:
174   ret i8 0
177 define 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
192 entry:
193   %c.1 = icmp sge i8 %a, 0
194   br i1 %c.1, label %math, label %exit.fail
196 math:
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
201 exit.ok:
202   %res = extractvalue { i8, i1 } %op, 0
203   ret i8 %res
205 exit.fail:
206   ret i8 0
209 define 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
226 entry:
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
232 math:
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
237 exit.ok:
238   %res = extractvalue { i8, i1 } %op, 0
239   ret i8 %res
241 exit.fail:
242   ret i8 0
245 define 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
262 entry:
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
268 math:
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
273 exit.ok:
274   %res = extractvalue { i8, i1 } %op, 0
275   ret i8 %res
277 exit.fail:
278   ret i8 0
281 define 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
298 entry:
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
304 math:
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
309 exit.ok:
310   %res = extractvalue { i8, i1 } %op, 0
311   ret i8 %res
313 exit.fail:
314   ret i8 0
317 define 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
334 entry:
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
340 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
345 exit.ok:
346   %res = extractvalue { i8, i1 } %op, 0
347   ret i8 %res
349 exit.fail:
350   ret i8 0