[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / CorrelatedValuePropagation / overflow_predicate.ll
blobaff6e035534051c84884fd114c6f7b247c369627
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -correlated-propagation < %s | FileCheck %s
4 declare void @llvm.trap()
5 declare {i8, i1} @llvm.uadd.with.overflow(i8, i8)
6 declare {i8, i1} @llvm.sadd.with.overflow(i8, i8)
7 declare {i8, i1} @llvm.usub.with.overflow(i8, i8)
8 declare {i8, i1} @llvm.ssub.with.overflow(i8, i8)
9 declare {i8, i1} @llvm.umul.with.overflow(i8, i8)
10 declare {i8, i1} @llvm.smul.with.overflow(i8, i8)
12 define i1 @uadd_ov_false(i8 %x, i8* %px, i1* %pc) {
13 ; CHECK-LABEL: @uadd_ov_false(
14 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
15 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
16 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
17 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
18 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
19 ; CHECK:       no_overflow:
20 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[X]], -102
21 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
22 ; CHECK-NEXT:    ret i1 false
23 ; CHECK:       trap:
24 ; CHECK-NEXT:    call void @llvm.trap()
25 ; CHECK-NEXT:    unreachable
27   %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100)
28   %val = extractvalue {i8, i1} %val_ov, 0
29   store i8 %val, i8* %px
30   %ov = extractvalue {i8, i1} %val_ov, 1
31   br i1 %ov, label %trap, label %no_overflow
33 no_overflow:
34   %c1 = icmp ugt i8 %x, 154
35   store i1 %c1, i1* %pc
36   %c2 = icmp ugt i8 %x, 155
37   ret i1 %c2
39 trap:
40   call void @llvm.trap()
41   unreachable
44 define i1 @uadd_ov_true(i8 %x, i8* %px, i1* %pc) {
45 ; CHECK-LABEL: @uadd_ov_true(
46 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
47 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
48 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
49 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
50 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
51 ; CHECK:       overflow:
52 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[X]], -100
53 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
54 ; CHECK-NEXT:    ret i1 true
55 ; CHECK:       trap:
56 ; CHECK-NEXT:    call void @llvm.trap()
57 ; CHECK-NEXT:    unreachable
59   %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100)
60   %val = extractvalue {i8, i1} %val_ov, 0
61   store i8 %val, i8* %px
62   %ov = extractvalue {i8, i1} %val_ov, 1
63   br i1 %ov, label %overflow, label %trap
65 overflow:
66   %c1 = icmp ugt i8 %x, 156
67   store i1 %c1, i1* %pc
68   %c2 = icmp ugt i8 %x, 155
69   ret i1 %c2
71 trap:
72   call void @llvm.trap()
73   unreachable
76 define i1 @sadd_ov_false(i8 %x, i8* %px, i1* %pc) {
77 ; CHECK-LABEL: @sadd_ov_false(
78 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
79 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
80 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
81 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
82 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
83 ; CHECK:       no_overflow:
84 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 [[X]], 26
85 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
86 ; CHECK-NEXT:    ret i1 false
87 ; CHECK:       trap:
88 ; CHECK-NEXT:    call void @llvm.trap()
89 ; CHECK-NEXT:    unreachable
91   %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100)
92   %val = extractvalue {i8, i1} %val_ov, 0
93   store i8 %val, i8* %px
94   %ov = extractvalue {i8, i1} %val_ov, 1
95   br i1 %ov, label %trap, label %no_overflow
97 no_overflow:
98   %c1 = icmp sgt i8 %x, 26
99   store i1 %c1, i1* %pc
100   %c2 = icmp sgt i8 %x, 27
101   ret i1 %c2
103 trap:
104   call void @llvm.trap()
105   unreachable
108 define i1 @sadd_ov_true(i8 %x, i8* %px, i1* %pc) {
109 ; CHECK-LABEL: @sadd_ov_true(
110 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
111 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
112 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
113 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
114 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
115 ; CHECK:       overflow:
116 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 [[X]], 28
117 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
118 ; CHECK-NEXT:    ret i1 true
119 ; CHECK:       trap:
120 ; CHECK-NEXT:    call void @llvm.trap()
121 ; CHECK-NEXT:    unreachable
123   %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100)
124   %val = extractvalue {i8, i1} %val_ov, 0
125   store i8 %val, i8* %px
126   %ov = extractvalue {i8, i1} %val_ov, 1
127   br i1 %ov, label %overflow, label %trap
129 overflow:
130   %c1 = icmp sgt i8 %x, 28
131   store i1 %c1, i1* %pc
132   %c2 = icmp sgt i8 %x, 27
133   ret i1 %c2
135 trap:
136   call void @llvm.trap()
137   unreachable
140 define i1 @usub_ov_false(i8 %x, i8* %px, i1* %pc) {
141 ; CHECK-LABEL: @usub_ov_false(
142 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100)
143 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
144 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
145 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
146 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
147 ; CHECK:       no_overflow:
148 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[X]], 101
149 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
150 ; CHECK-NEXT:    ret i1 false
151 ; CHECK:       trap:
152 ; CHECK-NEXT:    call void @llvm.trap()
153 ; CHECK-NEXT:    unreachable
155   %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100)
156   %val = extractvalue {i8, i1} %val_ov, 0
157   store i8 %val, i8* %px
158   %ov = extractvalue {i8, i1} %val_ov, 1
159   br i1 %ov, label %trap, label %no_overflow
161 no_overflow:
162   %c1 = icmp ult i8 %x, 101
163   store i1 %c1, i1* %pc
164   %c2 = icmp ult i8 %x, 100
165   ret i1 %c2
167 trap:
168   call void @llvm.trap()
169   unreachable
172 define i1 @usub_ov_true(i8 %x, i8* %px, i1* %pc) {
173 ; CHECK-LABEL: @usub_ov_true(
174 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100)
175 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
176 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
177 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
178 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
179 ; CHECK:       overflow:
180 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[X]], 99
181 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
182 ; CHECK-NEXT:    ret i1 true
183 ; CHECK:       trap:
184 ; CHECK-NEXT:    call void @llvm.trap()
185 ; CHECK-NEXT:    unreachable
187   %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100)
188   %val = extractvalue {i8, i1} %val_ov, 0
189   store i8 %val, i8* %px
190   %ov = extractvalue {i8, i1} %val_ov, 1
191   br i1 %ov, label %overflow, label %trap
193 overflow:
194   %c1 = icmp ult i8 %x, 99
195   store i1 %c1, i1* %pc
196   %c2 = icmp ult i8 %x, 100
197   ret i1 %c2
199 trap:
200   call void @llvm.trap()
201   unreachable
204 define i1 @ssub_ov_false(i8 %x, i8* %px, i1* %pc) {
205 ; CHECK-LABEL: @ssub_ov_false(
206 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100)
207 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
208 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
209 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
210 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
211 ; CHECK:       no_overflow:
212 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i8 [[X]], -27
213 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
214 ; CHECK-NEXT:    ret i1 false
215 ; CHECK:       trap:
216 ; CHECK-NEXT:    call void @llvm.trap()
217 ; CHECK-NEXT:    unreachable
219   %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100)
220   %val = extractvalue {i8, i1} %val_ov, 0
221   store i8 %val, i8* %px
222   %ov = extractvalue {i8, i1} %val_ov, 1
223   br i1 %ov, label %trap, label %no_overflow
225 no_overflow:
226   %c1 = icmp slt i8 %x, -27
227   store i1 %c1, i1* %pc
228   %c2 = icmp slt i8 %x, -28
229   ret i1 %c2
231 trap:
232   call void @llvm.trap()
233   unreachable
236 define i1 @ssub_ov_true(i8 %x, i8* %px, i1* %pc) {
237 ; CHECK-LABEL: @ssub_ov_true(
238 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100)
239 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
240 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
241 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
242 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
243 ; CHECK:       overflow:
244 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i8 [[X]], -29
245 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
246 ; CHECK-NEXT:    ret i1 true
247 ; CHECK:       trap:
248 ; CHECK-NEXT:    call void @llvm.trap()
249 ; CHECK-NEXT:    unreachable
251   %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100)
252   %val = extractvalue {i8, i1} %val_ov, 0
253   store i8 %val, i8* %px
254   %ov = extractvalue {i8, i1} %val_ov, 1
255   br i1 %ov, label %overflow, label %trap
257 overflow:
258   %c1 = icmp slt i8 %x, -29
259   store i1 %c1, i1* %pc
260   %c2 = icmp slt i8 %x, -28
261   ret i1 %c2
263 trap:
264   call void @llvm.trap()
265   unreachable
268 define i1 @umul_ov_false(i8 %x, i8* %px, i1* %pc) {
269 ; CHECK-LABEL: @umul_ov_false(
270 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10)
271 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
272 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
273 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
274 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
275 ; CHECK:       no_overflow:
276 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[X]], 24
277 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
278 ; CHECK-NEXT:    ret i1 false
279 ; CHECK:       trap:
280 ; CHECK-NEXT:    call void @llvm.trap()
281 ; CHECK-NEXT:    unreachable
283   %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10)
284   %val = extractvalue {i8, i1} %val_ov, 0
285   store i8 %val, i8* %px
286   %ov = extractvalue {i8, i1} %val_ov, 1
287   br i1 %ov, label %trap, label %no_overflow
289 no_overflow:
290   %c1 = icmp ugt i8 %x, 24
291   store i1 %c1, i1* %pc
292   %c2 = icmp ugt i8 %x, 25
293   ret i1 %c2
295 trap:
296   call void @llvm.trap()
297   unreachable
300 define i1 @umul_ov_true(i8 %x, i8* %px, i1* %pc) {
301 ; CHECK-LABEL: @umul_ov_true(
302 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10)
303 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
304 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
305 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
306 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
307 ; CHECK:       overflow:
308 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[X]], 26
309 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
310 ; CHECK-NEXT:    ret i1 true
311 ; CHECK:       trap:
312 ; CHECK-NEXT:    call void @llvm.trap()
313 ; CHECK-NEXT:    unreachable
315   %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10)
316   %val = extractvalue {i8, i1} %val_ov, 0
317   store i8 %val, i8* %px
318   %ov = extractvalue {i8, i1} %val_ov, 1
319   br i1 %ov, label %overflow, label %trap
321 overflow:
322   %c1 = icmp ugt i8 %x, 26
323   store i1 %c1, i1* %pc
324   %c2 = icmp ugt i8 %x, 25
325   ret i1 %c2
327 trap:
328   call void @llvm.trap()
329   unreachable
332 ; Signed mul is constrained from both sides.
333 define i1 @smul_ov_false_bound1(i8 %x, i8* %px, i1* %pc) {
334 ; CHECK-LABEL: @smul_ov_false_bound1(
335 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
336 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
337 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
338 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
339 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
340 ; CHECK:       no_overflow:
341 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i8 [[X]], -11
342 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
343 ; CHECK-NEXT:    ret i1 false
344 ; CHECK:       trap:
345 ; CHECK-NEXT:    call void @llvm.trap()
346 ; CHECK-NEXT:    unreachable
348   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
349   %val = extractvalue {i8, i1} %val_ov, 0
350   store i8 %val, i8* %px
351   %ov = extractvalue {i8, i1} %val_ov, 1
352   br i1 %ov, label %trap, label %no_overflow
354 no_overflow:
355   %c1 = icmp slt i8 %x, -11
356   store i1 %c1, i1* %pc
357   %c2 = icmp slt i8 %x, -12
358   ret i1 %c2
360 trap:
361   call void @llvm.trap()
362   unreachable
365 define i1 @smul_ov_false_bound2(i8 %x, i8* %px, i1* %pc) {
366 ; CHECK-LABEL: @smul_ov_false_bound2(
367 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
368 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
369 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
370 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
371 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
372 ; CHECK:       no_overflow:
373 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 [[X]], 11
374 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
375 ; CHECK-NEXT:    ret i1 false
376 ; CHECK:       trap:
377 ; CHECK-NEXT:    call void @llvm.trap()
378 ; CHECK-NEXT:    unreachable
380   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
381   %val = extractvalue {i8, i1} %val_ov, 0
382   store i8 %val, i8* %px
383   %ov = extractvalue {i8, i1} %val_ov, 1
384   br i1 %ov, label %trap, label %no_overflow
386 no_overflow:
387   %c1 = icmp sgt i8 %x, 11
388   store i1 %c1, i1* %pc
389   %c2 = icmp sgt i8 %x, 12
390   ret i1 %c2
392 trap:
393   call void @llvm.trap()
394   unreachable
397 ; Can't use slt/sgt to test for a hole in the range, check equality instead.
398 define i1 @smul_ov_true_bound1(i8 %x, i8* %px, i1* %pc) {
399 ; CHECK-LABEL: @smul_ov_true_bound1(
400 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
401 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
402 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
403 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
404 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
405 ; CHECK:       overflow:
406 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[X]], -13
407 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
408 ; CHECK-NEXT:    ret i1 false
409 ; CHECK:       trap:
410 ; CHECK-NEXT:    call void @llvm.trap()
411 ; CHECK-NEXT:    unreachable
413   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
414   %val = extractvalue {i8, i1} %val_ov, 0
415   store i8 %val, i8* %px
416   %ov = extractvalue {i8, i1} %val_ov, 1
417   br i1 %ov, label %overflow, label %trap
419 overflow:
420   %c1 = icmp eq i8 %x, -13
421   store i1 %c1, i1* %pc
422   %c2 = icmp eq i8 %x, -12
423   ret i1 %c2
425 trap:
426   call void @llvm.trap()
427   unreachable
430 define i1 @smul_ov_true_bound2(i8 %x, i8* %px, i1* %pc) {
431 ; CHECK-LABEL: @smul_ov_true_bound2(
432 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
433 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
434 ; CHECK-NEXT:    store i8 [[VAL]], i8* [[PX:%.*]]
435 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
436 ; CHECK-NEXT:    br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
437 ; CHECK:       overflow:
438 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[X]], 13
439 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
440 ; CHECK-NEXT:    ret i1 false
441 ; CHECK:       trap:
442 ; CHECK-NEXT:    call void @llvm.trap()
443 ; CHECK-NEXT:    unreachable
445   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
446   %val = extractvalue {i8, i1} %val_ov, 0
447   store i8 %val, i8* %px
448   %ov = extractvalue {i8, i1} %val_ov, 1
449   br i1 %ov, label %overflow, label %trap
451 overflow:
452   %c1 = icmp eq i8 %x, 13
453   store i1 %c1, i1* %pc
454   %c2 = icmp eq i8 %x, 12
455   ret i1 %c2
457 trap:
458   call void @llvm.trap()
459   unreachable
462 define i1 @uadd_val(i8 %x, i1* %pc) {
463 ; CHECK-LABEL: @uadd_val(
464 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
465 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
466 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
467 ; CHECK:       no_overflow:
468 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
469 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
470 ; CHECK:       split:
471 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[VAL]], 100
472 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
473 ; CHECK-NEXT:    ret i1 true
474 ; CHECK:       trap:
475 ; CHECK-NEXT:    call void @llvm.trap()
476 ; CHECK-NEXT:    unreachable
478   %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100)
479   %ov = extractvalue {i8, i1} %val_ov, 1
480   br i1 %ov, label %trap, label %no_overflow
482 no_overflow:
483   %val = extractvalue {i8, i1} %val_ov, 0
484   br label %split
486 split:
487   %c1 = icmp ugt i8 %val, 100
488   store i1 %c1, i1* %pc
489   %c2 = icmp uge i8 %val, 100
490   ret i1 %c2
492 trap:
493   call void @llvm.trap()
494   unreachable
497 define i1 @sadd_val(i8 %x, i1* %pc) {
498 ; CHECK-LABEL: @sadd_val(
499 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
500 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
501 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
502 ; CHECK:       no_overflow:
503 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
504 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
505 ; CHECK:       split:
506 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 [[VAL]], -28
507 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
508 ; CHECK-NEXT:    ret i1 true
509 ; CHECK:       trap:
510 ; CHECK-NEXT:    call void @llvm.trap()
511 ; CHECK-NEXT:    unreachable
513   %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100)
514   %ov = extractvalue {i8, i1} %val_ov, 1
515   br i1 %ov, label %trap, label %no_overflow
517 no_overflow:
518   %val = extractvalue {i8, i1} %val_ov, 0
519   br label %split
521 split:
522   %c1 = icmp sgt i8 %val, -28
523   store i1 %c1, i1* %pc
524   %c2 = icmp sge i8 %val, -28
525   ret i1 %c2
527 trap:
528   call void @llvm.trap()
529   unreachable
532 define i1 @usub_val(i8 %x, i1* %pc) {
533 ; CHECK-LABEL: @usub_val(
534 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100)
535 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
536 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
537 ; CHECK:       no_overflow:
538 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
539 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
540 ; CHECK:       split:
541 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[VAL]], -101
542 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
543 ; CHECK-NEXT:    ret i1 true
544 ; CHECK:       trap:
545 ; CHECK-NEXT:    call void @llvm.trap()
546 ; CHECK-NEXT:    unreachable
548   %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100)
549   %ov = extractvalue {i8, i1} %val_ov, 1
550   br i1 %ov, label %trap, label %no_overflow
552 no_overflow:
553   %val = extractvalue {i8, i1} %val_ov, 0
554   br label %split
556 split:
557   %c1 = icmp ult i8 %val, 155
558   store i1 %c1, i1* %pc
559   %c2 = icmp ule i8 %val, 155
560   ret i1 %c2
562 trap:
563   call void @llvm.trap()
564   unreachable
567 define i1 @ssub_val(i8 %x, i1* %pc) {
568 ; CHECK-LABEL: @ssub_val(
569 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100)
570 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
571 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
572 ; CHECK:       no_overflow:
573 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
574 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
575 ; CHECK:       split:
576 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i8 [[VAL]], 27
577 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
578 ; CHECK-NEXT:    ret i1 true
579 ; CHECK:       trap:
580 ; CHECK-NEXT:    call void @llvm.trap()
581 ; CHECK-NEXT:    unreachable
583   %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100)
584   %ov = extractvalue {i8, i1} %val_ov, 1
585   br i1 %ov, label %trap, label %no_overflow
587 no_overflow:
588   %val = extractvalue {i8, i1} %val_ov, 0
589   br label %split
591 split:
592   %c1 = icmp slt i8 %val, 27
593   store i1 %c1, i1* %pc
594   %c2 = icmp sle i8 %val, 27
595   ret i1 %c2
597 trap:
598   call void @llvm.trap()
599   unreachable
602 define i1 @umul_val(i8 %x, i1* %pc) {
603 ; CHECK-LABEL: @umul_val(
604 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10)
605 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
606 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
607 ; CHECK:       no_overflow:
608 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
609 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
610 ; CHECK:       split:
611 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[VAL]], -6
612 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
613 ; CHECK-NEXT:    ret i1 true
614 ; CHECK:       trap:
615 ; CHECK-NEXT:    call void @llvm.trap()
616 ; CHECK-NEXT:    unreachable
618   %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10)
619   %ov = extractvalue {i8, i1} %val_ov, 1
620   br i1 %ov, label %trap, label %no_overflow
622 no_overflow:
623   %val = extractvalue {i8, i1} %val_ov, 0
624   br label %split
626 split:
627   %c1 = icmp ult i8 %val, 250
628   store i1 %c1, i1* %pc
629   %c2 = icmp ule i8 %val, 250
630   ret i1 %c2
632 trap:
633   call void @llvm.trap()
634   unreachable
637 define i1 @smul_val_bound1(i8 %x, i1* %pc) {
638 ; CHECK-LABEL: @smul_val_bound1(
639 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
640 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
641 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
642 ; CHECK:       no_overflow:
643 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
644 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
645 ; CHECK:       split:
646 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i8 [[VAL]], 120
647 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
648 ; CHECK-NEXT:    ret i1 true
649 ; CHECK:       trap:
650 ; CHECK-NEXT:    call void @llvm.trap()
651 ; CHECK-NEXT:    unreachable
653   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
654   %ov = extractvalue {i8, i1} %val_ov, 1
655   br i1 %ov, label %trap, label %no_overflow
657 no_overflow:
658   %val = extractvalue {i8, i1} %val_ov, 0
659   br label %split
661 split:
662   %c1 = icmp slt i8 %val, 120
663   store i1 %c1, i1* %pc
664   %c2 = icmp sle i8 %val, 120
665   ret i1 %c2
667 trap:
668   call void @llvm.trap()
669   unreachable
672 define i1 @smul_val_bound2(i8 %x, i1* %pc) {
673 ; CHECK-LABEL: @smul_val_bound2(
674 ; CHECK-NEXT:    [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
675 ; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
676 ; CHECK-NEXT:    br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
677 ; CHECK:       no_overflow:
678 ; CHECK-NEXT:    [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
679 ; CHECK-NEXT:    br label [[SPLIT:%.*]]
680 ; CHECK:       split:
681 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 [[VAL]], -120
682 ; CHECK-NEXT:    store i1 [[C1]], i1* [[PC:%.*]]
683 ; CHECK-NEXT:    ret i1 true
684 ; CHECK:       trap:
685 ; CHECK-NEXT:    call void @llvm.trap()
686 ; CHECK-NEXT:    unreachable
688   %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
689   %ov = extractvalue {i8, i1} %val_ov, 1
690   br i1 %ov, label %trap, label %no_overflow
692 no_overflow:
693   %val = extractvalue {i8, i1} %val_ov, 0
694   br label %split
696 split:
697   %c1 = icmp sgt i8 %val, -120
698   store i1 %c1, i1* %pc
699   %c2 = icmp sge i8 %val, -120
700   ret i1 %c2
702 trap:
703   call void @llvm.trap()
704   unreachable