[win/asan] GetInstructionSize: Fix `83 E4 XX` to return 3. (#119644)
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / overflow_predicate.ll
blob8591ab73ebfeb8fb50235ad2406ae8170cf0dce5
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:%.*]]
19 ; CHECK:       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
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, ptr %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, ptr %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, 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:%.*]]
51 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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:%.*]]
83 ; CHECK:       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
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, ptr %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, ptr %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, 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:%.*]]
115 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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
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, ptr %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, ptr %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, 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:%.*]]
179 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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
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, ptr %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, ptr %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, 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:%.*]]
243 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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
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, ptr %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, ptr %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, 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:%.*]]
307 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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
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, ptr %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, ptr %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, 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
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, ptr %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, ptr %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, 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:%.*]]
405 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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:%.*]]
437 ; CHECK:       overflow:
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
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, ptr %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, ptr %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, 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
472 ; CHECK:       trap:
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
480 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
485   ret i1 %c2
487 trap:
488   call void @llvm.trap()
489   unreachable
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
502 ; CHECK:       trap:
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
510 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
515   ret i1 %c2
517 trap:
518   call void @llvm.trap()
519   unreachable
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
532 ; CHECK:       trap:
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
540 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
545   ret i1 %c2
547 trap:
548   call void @llvm.trap()
549   unreachable
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
562 ; CHECK:       trap:
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
570 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
575   ret i1 %c2
577 trap:
578   call void @llvm.trap()
579   unreachable
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
592 ; CHECK:       trap:
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
600 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
605   ret i1 %c2
607 trap:
608   call void @llvm.trap()
609   unreachable
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
622 ; CHECK:       trap:
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
630 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
635   ret i1 %c2
637 trap:
638   call void @llvm.trap()
639   unreachable
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
652 ; CHECK:       trap:
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
660 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
665   ret i1 %c2
667 trap:
668   call void @llvm.trap()
669   unreachable