1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=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, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
17 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
18 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
20 ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], -102
21 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
22 ; CHECK-NEXT: ret i1 false
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, ptr %px
30 %ov = extractvalue {i8, i1} %val_ov, 1
31 br i1 %ov, label %trap, label %no_overflow
34 %c1 = icmp ugt i8 %x, 154
36 %c2 = icmp ugt i8 %x, 155
40 call void @llvm.trap()
44 define i1 @uadd_ov_true(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
49 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
50 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
52 ; CHECK-NEXT: [[C1:%.*]] = icmp samesign ugt i8 [[X]], -100
53 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
54 ; CHECK-NEXT: ret i1 true
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, ptr %px
62 %ov = extractvalue {i8, i1} %val_ov, 1
63 br i1 %ov, label %overflow, label %trap
66 %c1 = icmp ugt i8 %x, 156
68 %c2 = icmp ugt i8 %x, 155
72 call void @llvm.trap()
76 define i1 @sadd_ov_false(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
81 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
82 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
84 ; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 26
85 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
86 ; CHECK-NEXT: ret i1 false
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, ptr %px
94 %ov = extractvalue {i8, i1} %val_ov, 1
95 br i1 %ov, label %trap, label %no_overflow
98 %c1 = icmp sgt i8 %x, 26
100 %c2 = icmp sgt i8 %x, 27
104 call void @llvm.trap()
108 define i1 @sadd_ov_true(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
113 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
114 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
116 ; CHECK-NEXT: [[C1:%.*]] = icmp samesign ugt i8 [[X]], 28
117 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
118 ; CHECK-NEXT: ret i1 true
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, ptr %px
126 %ov = extractvalue {i8, i1} %val_ov, 1
127 br i1 %ov, label %overflow, label %trap
130 %c1 = icmp sgt i8 %x, 28
131 store i1 %c1, ptr %pc
132 %c2 = icmp sgt i8 %x, 27
136 call void @llvm.trap()
140 define i1 @usub_ov_false(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
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]], ptr [[PC:%.*]], align 1
150 ; CHECK-NEXT: ret i1 false
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, ptr %px
158 %ov = extractvalue {i8, i1} %val_ov, 1
159 br i1 %ov, label %trap, label %no_overflow
162 %c1 = icmp ult i8 %x, 101
163 store i1 %c1, ptr %pc
164 %c2 = icmp ult i8 %x, 100
168 call void @llvm.trap()
172 define i1 @usub_ov_true(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
177 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
178 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
180 ; CHECK-NEXT: [[C1:%.*]] = icmp samesign ult i8 [[X]], 99
181 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
182 ; CHECK-NEXT: ret i1 true
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, ptr %px
190 %ov = extractvalue {i8, i1} %val_ov, 1
191 br i1 %ov, label %overflow, label %trap
194 %c1 = icmp ult i8 %x, 99
195 store i1 %c1, ptr %pc
196 %c2 = icmp ult i8 %x, 100
200 call void @llvm.trap()
204 define i1 @ssub_ov_false(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
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]], ptr [[PC:%.*]], align 1
214 ; CHECK-NEXT: ret i1 false
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, ptr %px
222 %ov = extractvalue {i8, i1} %val_ov, 1
223 br i1 %ov, label %trap, label %no_overflow
226 %c1 = icmp slt i8 %x, -27
227 store i1 %c1, ptr %pc
228 %c2 = icmp slt i8 %x, -28
232 call void @llvm.trap()
236 define i1 @ssub_ov_true(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
241 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
242 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
244 ; CHECK-NEXT: [[C1:%.*]] = icmp samesign ult i8 [[X]], -29
245 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
246 ; CHECK-NEXT: ret i1 true
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, ptr %px
254 %ov = extractvalue {i8, i1} %val_ov, 1
255 br i1 %ov, label %overflow, label %trap
258 %c1 = icmp slt i8 %x, -29
259 store i1 %c1, ptr %pc
260 %c2 = icmp slt i8 %x, -28
264 call void @llvm.trap()
268 define i1 @umul_ov_false(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
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 samesign ugt i8 [[X]], 24
277 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
278 ; CHECK-NEXT: ret i1 false
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, ptr %px
286 %ov = extractvalue {i8, i1} %val_ov, 1
287 br i1 %ov, label %trap, label %no_overflow
290 %c1 = icmp ugt i8 %x, 24
291 store i1 %c1, ptr %pc
292 %c2 = icmp ugt i8 %x, 25
296 call void @llvm.trap()
300 define i1 @umul_ov_true(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
305 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
306 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
308 ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], 26
309 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
310 ; CHECK-NEXT: ret i1 true
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, ptr %px
318 %ov = extractvalue {i8, i1} %val_ov, 1
319 br i1 %ov, label %overflow, label %trap
322 %c1 = icmp ugt i8 %x, 26
323 store i1 %c1, ptr %pc
324 %c2 = icmp ugt i8 %x, 25
328 call void @llvm.trap()
332 ; Signed mul is constrained from both sides.
333 define i1 @smul_ov_false_bound1(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
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]], ptr [[PC:%.*]], align 1
343 ; CHECK-NEXT: ret i1 false
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, ptr %px
351 %ov = extractvalue {i8, i1} %val_ov, 1
352 br i1 %ov, label %trap, label %no_overflow
355 %c1 = icmp slt i8 %x, -11
356 store i1 %c1, ptr %pc
357 %c2 = icmp slt i8 %x, -12
361 call void @llvm.trap()
365 define i1 @smul_ov_false_bound2(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
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]], ptr [[PC:%.*]], align 1
375 ; CHECK-NEXT: ret i1 false
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, ptr %px
383 %ov = extractvalue {i8, i1} %val_ov, 1
384 br i1 %ov, label %trap, label %no_overflow
387 %c1 = icmp sgt i8 %x, 11
388 store i1 %c1, ptr %pc
389 %c2 = icmp sgt i8 %x, 12
393 call void @llvm.trap()
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, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
403 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
404 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
406 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], -13
407 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
408 ; CHECK-NEXT: ret i1 false
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, ptr %px
416 %ov = extractvalue {i8, i1} %val_ov, 1
417 br i1 %ov, label %overflow, label %trap
420 %c1 = icmp eq i8 %x, -13
421 store i1 %c1, ptr %pc
422 %c2 = icmp eq i8 %x, -12
426 call void @llvm.trap()
430 define i1 @smul_ov_true_bound2(i8 %x, ptr %px, ptr %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]], ptr [[PX:%.*]], align 1
435 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
436 ; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]]
438 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], 13
439 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
440 ; CHECK-NEXT: ret i1 false
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, ptr %px
448 %ov = extractvalue {i8, i1} %val_ov, 1
449 br i1 %ov, label %overflow, label %trap
452 %c1 = icmp eq i8 %x, 13
453 store i1 %c1, ptr %pc
454 %c2 = icmp eq i8 %x, 12
458 call void @llvm.trap()
462 define i1 @uadd_val(i8 %x, ptr %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: [[C1:%.*]] = icmp ugt i8 [[VAL]], 100
470 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
471 ; CHECK-NEXT: ret i1 true
473 ; CHECK-NEXT: call void @llvm.trap()
474 ; CHECK-NEXT: unreachable
476 %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100)
477 %ov = extractvalue {i8, i1} %val_ov, 1
478 br i1 %ov, label %trap, label %no_overflow
481 %val = extractvalue {i8, i1} %val_ov, 0
482 %c1 = icmp ugt i8 %val, 100
483 store i1 %c1, ptr %pc
484 %c2 = icmp uge i8 %val, 100
488 call void @llvm.trap()
492 define i1 @sadd_val(i8 %x, ptr %pc) {
493 ; CHECK-LABEL: @sadd_val(
494 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100)
495 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
496 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
497 ; CHECK: no_overflow:
498 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
499 ; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[VAL]], -28
500 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
501 ; CHECK-NEXT: ret i1 true
503 ; CHECK-NEXT: call void @llvm.trap()
504 ; CHECK-NEXT: unreachable
506 %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100)
507 %ov = extractvalue {i8, i1} %val_ov, 1
508 br i1 %ov, label %trap, label %no_overflow
511 %val = extractvalue {i8, i1} %val_ov, 0
512 %c1 = icmp sgt i8 %val, -28
513 store i1 %c1, ptr %pc
514 %c2 = icmp sge i8 %val, -28
518 call void @llvm.trap()
522 define i1 @usub_val(i8 %x, ptr %pc) {
523 ; CHECK-LABEL: @usub_val(
524 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100)
525 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
526 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
527 ; CHECK: no_overflow:
528 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
529 ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[VAL]], -101
530 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
531 ; CHECK-NEXT: ret i1 true
533 ; CHECK-NEXT: call void @llvm.trap()
534 ; CHECK-NEXT: unreachable
536 %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100)
537 %ov = extractvalue {i8, i1} %val_ov, 1
538 br i1 %ov, label %trap, label %no_overflow
541 %val = extractvalue {i8, i1} %val_ov, 0
542 %c1 = icmp ult i8 %val, 155
543 store i1 %c1, ptr %pc
544 %c2 = icmp ule i8 %val, 155
548 call void @llvm.trap()
552 define i1 @ssub_val(i8 %x, ptr %pc) {
553 ; CHECK-LABEL: @ssub_val(
554 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100)
555 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
556 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
557 ; CHECK: no_overflow:
558 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
559 ; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[VAL]], 27
560 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
561 ; CHECK-NEXT: ret i1 true
563 ; CHECK-NEXT: call void @llvm.trap()
564 ; CHECK-NEXT: unreachable
566 %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100)
567 %ov = extractvalue {i8, i1} %val_ov, 1
568 br i1 %ov, label %trap, label %no_overflow
571 %val = extractvalue {i8, i1} %val_ov, 0
572 %c1 = icmp slt i8 %val, 27
573 store i1 %c1, ptr %pc
574 %c2 = icmp sle i8 %val, 27
578 call void @llvm.trap()
582 define i1 @umul_val(i8 %x, ptr %pc) {
583 ; CHECK-LABEL: @umul_val(
584 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10)
585 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
586 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
587 ; CHECK: no_overflow:
588 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
589 ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[VAL]], -6
590 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
591 ; CHECK-NEXT: ret i1 true
593 ; CHECK-NEXT: call void @llvm.trap()
594 ; CHECK-NEXT: unreachable
596 %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10)
597 %ov = extractvalue {i8, i1} %val_ov, 1
598 br i1 %ov, label %trap, label %no_overflow
601 %val = extractvalue {i8, i1} %val_ov, 0
602 %c1 = icmp ult i8 %val, 250
603 store i1 %c1, ptr %pc
604 %c2 = icmp ule i8 %val, 250
608 call void @llvm.trap()
612 define i1 @smul_val_bound1(i8 %x, ptr %pc) {
613 ; CHECK-LABEL: @smul_val_bound1(
614 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
615 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
616 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
617 ; CHECK: no_overflow:
618 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
619 ; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[VAL]], 120
620 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
621 ; CHECK-NEXT: ret i1 true
623 ; CHECK-NEXT: call void @llvm.trap()
624 ; CHECK-NEXT: unreachable
626 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
627 %ov = extractvalue {i8, i1} %val_ov, 1
628 br i1 %ov, label %trap, label %no_overflow
631 %val = extractvalue {i8, i1} %val_ov, 0
632 %c1 = icmp slt i8 %val, 120
633 store i1 %c1, ptr %pc
634 %c2 = icmp sle i8 %val, 120
638 call void @llvm.trap()
642 define i1 @smul_val_bound2(i8 %x, ptr %pc) {
643 ; CHECK-LABEL: @smul_val_bound2(
644 ; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10)
645 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1
646 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]]
647 ; CHECK: no_overflow:
648 ; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0
649 ; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[VAL]], -120
650 ; CHECK-NEXT: store i1 [[C1]], ptr [[PC:%.*]], align 1
651 ; CHECK-NEXT: ret i1 true
653 ; CHECK-NEXT: call void @llvm.trap()
654 ; CHECK-NEXT: unreachable
656 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10)
657 %ov = extractvalue {i8, i1} %val_ov, 1
658 br i1 %ov, label %trap, label %no_overflow
661 %val = extractvalue {i8, i1} %val_ov, 0
662 %c1 = icmp sgt i8 %val, -120
663 store i1 %c1, ptr %pc
664 %c2 = icmp sge i8 %val, -120
668 call void @llvm.trap()