xref: /llvm-project/llvm/test/Transforms/InstCombine/with_overflow.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare { i8, i1 } @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone
5declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone
6declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone
7declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone
8declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone
9declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone
10declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
11declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
12declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
13declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
14declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
15declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
16
17define i8 @uaddtest1(i8 %A, i8 %B) {
18; CHECK-LABEL: @uaddtest1(
19; CHECK-NEXT:    [[Y:%.*]] = add i8 [[A:%.*]], [[B:%.*]]
20; CHECK-NEXT:    ret i8 [[Y]]
21;
22  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)
23  %y = extractvalue { i8, i1 } %x, 0
24  ret i8 %y
25}
26
27define i8 @uaddtest2(i8 %A, i8 %B, ptr %overflowPtr) {
28; CHECK-LABEL: @uaddtest2(
29; CHECK-NEXT:    [[AND_A:%.*]] = and i8 [[A:%.*]], 127
30; CHECK-NEXT:    [[AND_B:%.*]] = and i8 [[B:%.*]], 127
31; CHECK-NEXT:    [[X:%.*]] = add nuw i8 [[AND_A]], [[AND_B]]
32; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1
33; CHECK-NEXT:    ret i8 [[X]]
34;
35  %and.A = and i8 %A, 127
36  %and.B = and i8 %B, 127
37  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %and.A, i8 %and.B)
38  %y = extractvalue { i8, i1 } %x, 0
39  %z = extractvalue { i8, i1 } %x, 1
40  store i1 %z, ptr %overflowPtr
41  ret i8 %y
42}
43
44define i8 @uaddtest3(i8 %A, i8 %B, ptr %overflowPtr) {
45; CHECK-LABEL: @uaddtest3(
46; CHECK-NEXT:    [[OR_A:%.*]] = or i8 [[A:%.*]], -128
47; CHECK-NEXT:    [[OR_B:%.*]] = or i8 [[B:%.*]], -128
48; CHECK-NEXT:    [[X:%.*]] = add i8 [[OR_A]], [[OR_B]]
49; CHECK-NEXT:    store i1 true, ptr [[OVERFLOWPTR:%.*]], align 1
50; CHECK-NEXT:    ret i8 [[X]]
51;
52  %or.A = or i8 %A, -128
53  %or.B = or i8 %B, -128
54  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %or.A, i8 %or.B)
55  %y = extractvalue { i8, i1 } %x, 0
56  %z = extractvalue { i8, i1 } %x, 1
57  store i1 %z, ptr %overflowPtr
58  ret i8 %y
59}
60
61define i8 @uaddtest4(i8 %A, ptr %overflowPtr) {
62; CHECK-LABEL: @uaddtest4(
63; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1
64; CHECK-NEXT:    ret i8 -1
65;
66  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 undef, i8 %A)
67  %y = extractvalue { i8, i1 } %x, 0
68  %z = extractvalue { i8, i1 } %x, 1
69  store i1 %z, ptr %overflowPtr
70  ret i8 %y
71}
72
73define i8 @uaddtest5(i8 %A, ptr %overflowPtr) {
74; CHECK-LABEL: @uaddtest5(
75; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1
76; CHECK-NEXT:    ret i8 [[A:%.*]]
77;
78  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 0, i8 %A)
79  %y = extractvalue { i8, i1 } %x, 0
80  %z = extractvalue { i8, i1 } %x, 1
81  store i1 %z, ptr %overflowPtr
82  ret i8 %y
83}
84
85define i1 @uaddtest6(i8 %A, i8 %B) {
86; CHECK-LABEL: @uaddtest6(
87; CHECK-NEXT:    [[Z:%.*]] = icmp ugt i8 [[A:%.*]], 3
88; CHECK-NEXT:    ret i1 [[Z]]
89;
90  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 -4)
91  %z = extractvalue { i8, i1 } %x, 1
92  ret i1 %z
93}
94
95define i8 @uaddtest7(i8 %A, i8 %B) {
96; CHECK-LABEL: @uaddtest7(
97; CHECK-NEXT:    [[Z:%.*]] = add i8 [[A:%.*]], [[B:%.*]]
98; CHECK-NEXT:    ret i8 [[Z]]
99;
100  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)
101  %z = extractvalue { i8, i1 } %x, 0
102  ret i8 %z
103}
104
105; PR20194
106define { i32, i1 } @saddtest_nsw(i8 %a, i8 %b) {
107; CHECK-LABEL: @saddtest_nsw(
108; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32
109; CHECK-NEXT:    [[BB:%.*]] = sext i8 [[B:%.*]] to i32
110; CHECK-NEXT:    [[X:%.*]] = add nsw i32 [[AA]], [[BB]]
111; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
112; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
113;
114  %aa = sext i8 %a to i32
115  %bb = sext i8 %b to i32
116  %x = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %aa, i32 %bb)
117  ret { i32, i1 } %x
118}
119
120define { i32, i1 } @uaddtest_nuw(i32 %a, i32 %b) {
121; CHECK-LABEL: @uaddtest_nuw(
122; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 2147483647
123; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 2147483647
124; CHECK-NEXT:    [[X:%.*]] = add nuw i32 [[AA]], [[BB]]
125; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
126; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
127;
128  %aa = and i32 %a, 2147483647
129  %bb = and i32 %b, 2147483647
130  %x = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %aa, i32 %bb)
131  ret { i32, i1 } %x
132}
133
134define { i32, i1 } @ssubtest_nsw(i8 %a, i8 %b) {
135; CHECK-LABEL: @ssubtest_nsw(
136; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32
137; CHECK-NEXT:    [[BB:%.*]] = sext i8 [[B:%.*]] to i32
138; CHECK-NEXT:    [[X:%.*]] = sub nsw i32 [[AA]], [[BB]]
139; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
140; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
141;
142  %aa = sext i8 %a to i32
143  %bb = sext i8 %b to i32
144  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %aa, i32 %bb)
145  ret { i32, i1 } %x
146}
147
148define { i32, i1 } @usubtest_nuw(i32 %a, i32 %b) {
149; CHECK-LABEL: @usubtest_nuw(
150; CHECK-NEXT:    [[AA:%.*]] = or i32 [[A:%.*]], -2147483648
151; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 2147483647
152; CHECK-NEXT:    [[X:%.*]] = sub nuw i32 [[AA]], [[BB]]
153; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
154; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
155;
156  %aa = or i32 %a, 2147483648
157  %bb = and i32 %b, 2147483647
158  %x = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %aa, i32 %bb)
159  ret { i32, i1 } %x
160}
161
162define { i32, i1 } @smultest1_nsw(i32 %a, i32 %b) {
163; CHECK-LABEL: @smultest1_nsw(
164; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 4095
165; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 524287
166; CHECK-NEXT:    [[X:%.*]] = mul nuw nsw i32 [[AA]], [[BB]]
167; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
168; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
169;
170  %aa = and i32 %a, 4095 ; 0xfff
171  %bb = and i32 %b, 524287; 0x7ffff
172  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)
173  ret { i32, i1 } %x
174}
175
176define { i32, i1 } @smultest2_nsw(i32 %a, i32 %b) {
177; CHECK-LABEL: @smultest2_nsw(
178; CHECK-NEXT:    [[AA:%.*]] = ashr i32 [[A:%.*]], 16
179; CHECK-NEXT:    [[BB:%.*]] = ashr i32 [[B:%.*]], 16
180; CHECK-NEXT:    [[X:%.*]] = mul nsw i32 [[AA]], [[BB]]
181; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
182; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
183;
184  %aa = ashr i32 %a, 16
185  %bb = ashr i32 %b, 16
186  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)
187  ret { i32, i1 } %x
188}
189
190define { i32, i1 } @smultest3_sw(i32 %a, i32 %b) {
191; CHECK-LABEL: @smultest3_sw(
192; CHECK-NEXT:    [[AA:%.*]] = ashr i32 [[A:%.*]], 16
193; CHECK-NEXT:    [[BB:%.*]] = ashr i32 [[B:%.*]], 15
194; CHECK-NEXT:    [[X:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[AA]], i32 [[BB]])
195; CHECK-NEXT:    ret { i32, i1 } [[X]]
196;
197  %aa = ashr i32 %a, 16
198  %bb = ashr i32 %b, 15
199  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)
200  ret { i32, i1 } %x
201}
202
203define { i32, i1 } @umultest_nuw(i32 %a, i32 %b) {
204; CHECK-LABEL: @umultest_nuw(
205; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 65535
206; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 65535
207; CHECK-NEXT:    [[X:%.*]] = mul nuw i32 [[AA]], [[BB]]
208; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
209; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
210;
211  %aa = and i32 %a, 65535 ; 0xffff
212  %bb = and i32 %b, 65535 ; 0xffff
213  %x = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %aa, i32 %bb)
214  ret { i32, i1 } %x
215}
216
217define i8 @umultest1(i8 %A, ptr %overflowPtr) {
218; CHECK-LABEL: @umultest1(
219; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1
220; CHECK-NEXT:    ret i8 0
221;
222  %x = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 0, i8 %A)
223  %y = extractvalue { i8, i1 } %x, 0
224  %z = extractvalue { i8, i1 } %x, 1
225  store i1 %z, ptr %overflowPtr
226  ret i8 %y
227}
228
229define i8 @umultest2(i8 %A, ptr %overflowPtr) {
230; CHECK-LABEL: @umultest2(
231; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1
232; CHECK-NEXT:    ret i8 [[A:%.*]]
233;
234  %x = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 %A)
235  %y = extractvalue { i8, i1 } %x, 0
236  %z = extractvalue { i8, i1 } %x, 1
237  store i1 %z, ptr %overflowPtr
238  ret i8 %y
239}
240
241define i32 @umultest3(i32 %n) nounwind {
242; CHECK-LABEL: @umultest3(
243; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[N:%.*]], 2
244; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i32 [[SHR]], 3
245; CHECK-NEXT:    ret i32 [[MUL]]
246;
247  %shr = lshr i32 %n, 2
248  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %shr, i32 3)
249  %ov = extractvalue { i32, i1 } %mul, 1
250  %res = extractvalue { i32, i1 } %mul, 0
251  %ret = select i1 %ov, i32 -1, i32 %res
252  ret i32 %ret
253}
254
255define i32 @umultest4(i32 %n) nounwind {
256; CHECK-LABEL: @umultest4(
257; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[N:%.*]], 1
258; CHECK-NEXT:    [[RES:%.*]] = and i32 [[TMP1]], -4
259; CHECK-NEXT:    [[OV_INV:%.*]] = icmp sgt i32 [[N]], -1
260; CHECK-NEXT:    [[RET:%.*]] = select i1 [[OV_INV]], i32 [[RES]], i32 -1
261; CHECK-NEXT:    ret i32 [[RET]]
262;
263  %shr = lshr i32 %n, 1
264  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %shr, i32 4)
265  %ov = extractvalue { i32, i1 } %mul, 1
266  %res = extractvalue { i32, i1 } %mul, 0
267  %ret = select i1 %ov, i32 -1, i32 %res
268  ret i32 %ret
269}
270
271define { i32, i1 } @umultest5(i32 %x, i32 %y) nounwind {
272; CHECK-LABEL: @umultest5(
273; CHECK-NEXT:    [[OR_X:%.*]] = or i32 [[X:%.*]], -2147483648
274; CHECK-NEXT:    [[OR_Y:%.*]] = or i32 [[Y:%.*]], -2147483648
275; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[OR_X]], [[OR_Y]]
276; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 true }, i32 [[MUL]], 0
277; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
278;
279  %or_x = or i32 %x, 2147483648
280  %or_y = or i32 %y, 2147483648
281  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %or_x, i32 %or_y)
282  ret { i32, i1 } %mul
283}
284
285define i1 @overflow_div_add(i32 %v1, i32 %v2) nounwind {
286; CHECK-LABEL: @overflow_div_add(
287; CHECK-NEXT:    ret i1 false
288;
289  %div = sdiv i32 %v1, 2
290  %t = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %div, i32 1)
291  %obit = extractvalue { i32, i1 } %t, 1
292  ret i1 %obit
293}
294
295define i1 @overflow_div_sub(i32 %v1, i32 %v2) nounwind {
296  ; Check cases where the known sign bits are larger than the word size.
297; CHECK-LABEL: @overflow_div_sub(
298; CHECK-NEXT:    ret i1 false
299;
300  %a = ashr i32 %v1, 18
301  %div = sdiv i32 %a, 65536
302  %t = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %div, i32 1)
303  %obit = extractvalue { i32, i1 } %t, 1
304  ret i1 %obit
305}
306
307define i1 @overflow_mod_mul(i32 %v1, i32 %v2) nounwind {
308; CHECK-LABEL: @overflow_mod_mul(
309; CHECK-NEXT:    ret i1 false
310;
311  %rem = srem i32 %v1, 1000
312  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)
313  %obit = extractvalue { i32, i1 } %t, 1
314  ret i1 %obit
315}
316
317define i1 @overflow_mod_overflow_mul(i32 %v1, i32 %v2) nounwind {
318; CHECK-LABEL: @overflow_mod_overflow_mul(
319; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[V1:%.*]], 65537
320; CHECK-NEXT:    [[T:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[REM]], i32 [[REM]])
321; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i32, i1 } [[T]], 1
322; CHECK-NEXT:    ret i1 [[OBIT]]
323;
324  %rem = srem i32 %v1, 65537
325  ; This may overflow because the result of the mul operands may be greater than 16bits
326  ; and the result greater than 32.
327  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)
328  %obit = extractvalue { i32, i1 } %t, 1
329  ret i1 %obit
330}
331
332define i1 @overflow_mod_mul2(i16 %v1, i32 %v2) nounwind {
333; CHECK-LABEL: @overflow_mod_mul2(
334; CHECK-NEXT:    ret i1 false
335;
336  %a = sext i16 %v1 to i32
337  %rem = srem i32 %a, %v2
338  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)
339  %obit = extractvalue { i32, i1 } %t, 1
340  ret i1 %obit
341}
342
343define { i32, i1 } @ssubtest_reorder(i8 %a) {
344; CHECK-LABEL: @ssubtest_reorder(
345; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32
346; CHECK-NEXT:    [[X:%.*]] = sub nsw i32 0, [[AA]]
347; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0
348; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]
349;
350  %aa = sext i8 %a to i32
351  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 0, i32 %aa)
352  ret { i32, i1 } %x
353}
354
355define { i32, i1 } @never_overflows_ssub_test0(i32 %a) {
356; CHECK-LABEL: @never_overflows_ssub_test0(
357; CHECK-NEXT:    [[X:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[A:%.*]], 0
358; CHECK-NEXT:    ret { i32, i1 } [[X]]
359;
360  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 0)
361  ret { i32, i1 } %x
362}
363
364define i1 @uadd_res_ult_x(i32 %x, i32 %y, ptr %p) nounwind {
365; CHECK-LABEL: @uadd_res_ult_x(
366; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
367; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
368; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
369; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
370; CHECK-NEXT:    ret i1 [[D]]
371;
372  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
373  %b = extractvalue { i32, i1 } %a, 1
374  store i1 %b, ptr %p
375  %c = extractvalue { i32, i1 } %a, 0
376  %d = icmp ult i32 %c, %x
377  ret i1 %d
378}
379
380define i1 @uadd_res_ult_y(i32 %x, i32 %y, ptr %p) nounwind {
381; CHECK-LABEL: @uadd_res_ult_y(
382; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
383; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
384; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
385; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
386; CHECK-NEXT:    ret i1 [[D]]
387;
388  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
389  %b = extractvalue { i32, i1 } %a, 1
390  store i1 %b, ptr %p
391  %c = extractvalue { i32, i1 } %a, 0
392  %d = icmp ult i32 %c, %y
393  ret i1 %d
394}
395
396define i1 @uadd_res_ugt_x(i32 %xx, i32 %y, ptr %p) nounwind {
397; CHECK-LABEL: @uadd_res_ugt_x(
398; CHECK-NEXT:    [[X:%.*]] = urem i32 42, [[XX:%.*]]
399; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X]], i32 [[Y:%.*]])
400; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
401; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
402; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
403; CHECK-NEXT:    ret i1 [[D]]
404;
405  %x = urem i32 42, %xx ; Thwart complexity-based canonicalization
406  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
407  %b = extractvalue { i32, i1 } %a, 1
408  store i1 %b, ptr %p
409  %c = extractvalue { i32, i1 } %a, 0
410  %d = icmp ugt i32 %x, %c
411  ret i1 %d
412}
413
414define i1 @uadd_res_ugt_y(i32 %x, i32 %yy, ptr %p) nounwind {
415; CHECK-LABEL: @uadd_res_ugt_y(
416; CHECK-NEXT:    [[Y:%.*]] = urem i32 42, [[YY:%.*]]
417; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y]])
418; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
419; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
420; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
421; CHECK-NEXT:    ret i1 [[D]]
422;
423  %y = urem i32 42, %yy ; Thwart complexity-based canonicalization
424  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
425  %b = extractvalue { i32, i1 } %a, 1
426  store i1 %b, ptr %p
427  %c = extractvalue { i32, i1 } %a, 0
428  %d = icmp ugt i32 %y, %c
429  ret i1 %d
430}
431
432define i1 @uadd_res_ult_const(i32 %x, ptr %p) nounwind {
433; CHECK-LABEL: @uadd_res_ult_const(
434; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 42)
435; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
436; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
437; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
438; CHECK-NEXT:    ret i1 [[D]]
439;
440  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 42)
441  %b = extractvalue { i32, i1 } %a, 1
442  store i1 %b, ptr %p
443  %c = extractvalue { i32, i1 } %a, 0
444  %d = icmp ult i32 %c, 42
445  ret i1 %d
446}
447
448define i1 @uadd_res_ult_const_one(i32 %x, ptr %p) nounwind {
449; CHECK-LABEL: @uadd_res_ult_const_one(
450; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1)
451; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
452; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
453; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
454; CHECK-NEXT:    ret i1 [[D]]
455;
456  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1)
457  %b = extractvalue { i32, i1 } %a, 1
458  store i1 %b, ptr %p
459  %c = extractvalue { i32, i1 } %a, 0
460  %d = icmp ult i32 %c, 1
461  ret i1 %d
462}
463
464define i1 @uadd_res_ult_const_minus_one(i32 %x, ptr %p) nounwind {
465; CHECK-LABEL: @uadd_res_ult_const_minus_one(
466; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 -1)
467; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1
468; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1
469; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1
470; CHECK-NEXT:    ret i1 [[D]]
471;
472  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 -1)
473  %b = extractvalue { i32, i1 } %a, 1
474  store i1 %b, ptr %p
475  %c = extractvalue { i32, i1 } %a, 0
476  %d = icmp ult i32 %c, -1
477  ret i1 %d
478}
479
480define { i32, i1 } @sadd_canonicalize_constant_arg0(i32 %x) nounwind {
481; CHECK-LABEL: @sadd_canonicalize_constant_arg0(
482; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 42)
483; CHECK-NEXT:    ret { i32, i1 } [[A]]
484;
485  %a = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 42, i32 %x)
486  ret { i32, i1 } %a
487}
488
489define { i32, i1 } @uadd_canonicalize_constant_arg0(i32 %x) nounwind {
490; CHECK-LABEL: @uadd_canonicalize_constant_arg0(
491; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 42)
492; CHECK-NEXT:    ret { i32, i1 } [[A]]
493;
494  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 42, i32 %x)
495  ret { i32, i1 } %a
496}
497
498define { i32, i1 } @ssub_no_canonicalize_constant_arg0(i32 %x) nounwind {
499; CHECK-LABEL: @ssub_no_canonicalize_constant_arg0(
500; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 42, i32 [[X:%.*]])
501; CHECK-NEXT:    ret { i32, i1 } [[A]]
502;
503  %a = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 42, i32 %x)
504  ret { i32, i1 } %a
505}
506
507define { i32, i1 } @usub_no_canonicalize_constant_arg0(i32 %x) nounwind {
508; CHECK-LABEL: @usub_no_canonicalize_constant_arg0(
509; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 42, i32 [[X:%.*]])
510; CHECK-NEXT:    ret { i32, i1 } [[A]]
511;
512  %a = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 42, i32 %x)
513  ret { i32, i1 } %a
514}
515
516define { i32, i1 } @smul_canonicalize_constant_arg0(i32 %x) nounwind {
517; CHECK-LABEL: @smul_canonicalize_constant_arg0(
518; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[X:%.*]], i32 42)
519; CHECK-NEXT:    ret { i32, i1 } [[A]]
520;
521  %a = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 42, i32 %x)
522  ret { i32, i1 } %a
523}
524
525define { i32, i1 } @umul_canonicalize_constant_arg0(i32 %x) nounwind {
526; CHECK-LABEL: @umul_canonicalize_constant_arg0(
527; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[X:%.*]], i32 42)
528; CHECK-NEXT:    ret { i32, i1 } [[A]]
529;
530  %a = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 42, i32 %x)
531  ret { i32, i1 } %a
532}
533
534; Always overflow tests
535
536define { i8, i1 } @uadd_always_overflow(i8 %x) nounwind {
537; CHECK-LABEL: @uadd_always_overflow(
538; CHECK-NEXT:    [[A:%.*]] = and i8 [[X:%.*]], 63
539; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0
540; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
541;
542  %y = or i8 %x, 192
543  %a = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %y, i8 64)
544  ret { i8, i1 } %a
545}
546
547define { i8, i1 } @usub_always_overflow(i8 %x) nounwind {
548; CHECK-LABEL: @usub_always_overflow(
549; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 64
550; CHECK-NEXT:    [[A:%.*]] = sub nsw i8 63, [[Y]]
551; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0
552; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
553;
554  %y = or i8 %x, 64
555  %a = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 63, i8 %y)
556  ret { i8, i1 } %a
557}
558
559define { i8, i1 } @umul_always_overflow(i8 %x) nounwind {
560; CHECK-LABEL: @umul_always_overflow(
561; CHECK-NEXT:    [[A:%.*]] = shl i8 [[X:%.*]], 1
562; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0
563; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
564;
565  %y = or i8 %x, 128
566  %a = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %y, i8 2)
567  ret { i8, i1 } %a
568}
569
570define { i8, i1 } @sadd_always_overflow(i8 %x) nounwind {
571; CHECK-LABEL: @sadd_always_overflow(
572; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 100)
573; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[Y]], 28
574; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0
575; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
576;
577  %c = icmp sgt i8 %x, 100
578  %y = select i1 %c, i8 %x, i8 100
579  %a = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %y, i8 28)
580  ret { i8, i1 } %a
581}
582
583define { i8, i1 } @ssub_always_overflow(i8 %x) nounwind {
584; CHECK-LABEL: @ssub_always_overflow(
585; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 29)
586; CHECK-NEXT:    [[A:%.*]] = sub nuw i8 -100, [[Y]]
587; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0
588; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
589;
590  %c = icmp sgt i8 %x, 29
591  %y = select i1 %c, i8 %x, i8 29
592  %a = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 -100, i8 %y)
593  ret { i8, i1 } %a
594}
595
596define { i8, i1 } @smul_always_overflow(i8 %x) nounwind {
597; CHECK-LABEL: @smul_always_overflow(
598; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 100)
599; CHECK-NEXT:    [[A:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[Y]], i8 2)
600; CHECK-NEXT:    ret { i8, i1 } [[A]]
601;
602  %c = icmp sgt i8 %x, 100
603  %y = select i1 %c, i8 %x, i8 100
604  %a = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %y, i8 2)
605  ret { i8, i1 } %a
606}
607
608declare { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8>, <4 x i8>)
609declare { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8>, <4 x i8>)
610declare { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8>, <4 x i8>)
611declare { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8>, <4 x i8>)
612declare { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8>, <4 x i8>)
613declare { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8>, <4 x i8>)
614
615; Always overflow
616
617define { <4 x i8>, <4 x i1> } @always_sadd_const_vector() nounwind {
618; CHECK-LABEL: @always_sadd_const_vector(
619; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -128), <4 x i1> splat (i1 true) }
620;
621  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
622  ret { <4 x i8>, <4 x i1> } %x
623}
624
625define { <4 x i8>, <4 x i1> } @always_uadd_const_vector() nounwind {
626; CHECK-LABEL: @always_uadd_const_vector(
627; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> zeroinitializer, <4 x i1> splat (i1 true) }
628;
629  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
630  ret { <4 x i8>, <4 x i1> } %x
631}
632
633define { <4 x i8>, <4 x i1> } @always_ssub_const_vector() nounwind {
634; CHECK-LABEL: @always_ssub_const_vector(
635; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 127), <4 x i1> splat (i1 true) }
636;
637  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
638  ret { <4 x i8>, <4 x i1> } %x
639}
640
641define { <4 x i8>, <4 x i1> } @always_usub_const_vector() nounwind {
642; CHECK-LABEL: @always_usub_const_vector(
643; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -1), <4 x i1> splat (i1 true) }
644;
645  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 0, i8 0, i8 0, i8 0>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
646  ret { <4 x i8>, <4 x i1> } %x
647}
648
649; NOTE: LLVM doesn't (yet) detect the multiplication always results in a overflow
650define { <4 x i8>, <4 x i1> } @always_smul_const_vector() nounwind {
651; CHECK-LABEL: @always_smul_const_vector(
652; CHECK-NEXT:    [[X:%.*]] = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> splat (i8 127), <4 x i8> splat (i8 3))
653; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } [[X]]
654;
655  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 3, i8 3, i8 3, i8 3>)
656  ret { <4 x i8>, <4 x i1> } %x
657}
658
659define { <4 x i8>, <4 x i1> } @always_umul_const_vector() nounwind {
660; CHECK-LABEL: @always_umul_const_vector(
661; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -3), <4 x i1> splat (i1 true) }
662;
663  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 3, i8 3, i8 3, i8 3>)
664  ret { <4 x i8>, <4 x i1> } %x
665}
666
667; Never overflow
668
669define { <4 x i8>, <4 x i1> } @never_sadd_const_vector() nounwind {
670; CHECK-LABEL: @never_sadd_const_vector(
671; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -50, i8 -10, i8 0, i8 60>, <4 x i1> zeroinitializer }
672;
673  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 -10, i8 -20, i8 30, i8 40>, <4 x i8> <i8 -40, i8 10, i8 -30, i8 20>)
674  ret { <4 x i8>, <4 x i1> } %x
675}
676
677define { <4 x i8>, <4 x i1> } @never_uadd_const_vector() nounwind {
678; CHECK-LABEL: @never_uadd_const_vector(
679; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 32, i8 64, i8 96, i8 48>, <4 x i1> zeroinitializer }
680;
681  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 0, i8 32, i8 64, i8 16>, <4 x i8> <i8 32, i8 32, i8 32, i8 32>)
682  ret { <4 x i8>, <4 x i1> } %x
683}
684
685define { <4 x i8>, <4 x i1> } @never_ssub_const_vector() nounwind {
686; CHECK-LABEL: @never_ssub_const_vector(
687; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 0, i8 10, i8 20, i8 30>, <4 x i1> zeroinitializer }
688;
689  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 -10, i8 -10, i8 -10, i8 -10>, <4 x i8> <i8 -10, i8 -20, i8 -30, i8 -40>)
690  ret { <4 x i8>, <4 x i1> } %x
691}
692
693define { <4 x i8>, <4 x i1> } @never_usub_const_vector() nounwind {
694; CHECK-LABEL: @never_usub_const_vector(
695; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 127, i8 -1, i8 0, i8 -2>, <4 x i1> zeroinitializer }
696;
697  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 128, i8 0, i8 255, i8 1>)
698  ret { <4 x i8>, <4 x i1> } %x
699}
700
701define { <4 x i8>, <4 x i1> } @never_smul_const_vector() nounwind {
702; CHECK-LABEL: @never_smul_const_vector(
703; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -54, i8 -18, i8 -60, i8 -90>, <4 x i1> zeroinitializer }
704;
705  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 -6, i8 -6, i8 -6, i8 -6>, <4 x i8> <i8 9, i8 3, i8 10, i8 15>)
706  ret { <4 x i8>, <4 x i1> } %x
707}
708
709define { <4 x i8>, <4 x i1> } @never_umul_const_vector() nounwind {
710; CHECK-LABEL: @never_umul_const_vector(
711; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -31, i8 120, i8 60, i8 30>, <4 x i1> zeroinitializer }
712;
713  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 15, i8 15, i8 15, i8 15>, <4 x i8> <i8 15, i8 8, i8 4, i8 2>)
714  ret { <4 x i8>, <4 x i1> } %x
715}
716
717; Neutral value
718
719define { <4 x i8>, <4 x i1> } @neutral_sadd_const_vector() nounwind {
720; CHECK-LABEL: @neutral_sadd_const_vector(
721; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
722;
723  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)
724  ret { <4 x i8>, <4 x i1> } %x
725}
726
727define { <4 x i8>, <4 x i1> } @neutral_uadd_const_vector() nounwind {
728; CHECK-LABEL: @neutral_uadd_const_vector(
729; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
730;
731  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)
732  ret { <4 x i8>, <4 x i1> } %x
733}
734
735define { <4 x i8>, <4 x i1> } @neutral_ssub_const_vector() nounwind {
736; CHECK-LABEL: @neutral_ssub_const_vector(
737; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
738;
739  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)
740  ret { <4 x i8>, <4 x i1> } %x
741}
742
743define { <4 x i8>, <4 x i1> } @neutral_usub_const_vector() nounwind {
744; CHECK-LABEL: @neutral_usub_const_vector(
745; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
746;
747  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)
748  ret { <4 x i8>, <4 x i1> } %x
749}
750
751define { <4 x i8>, <4 x i1> } @neutral_smul_const_vector() nounwind {
752; CHECK-LABEL: @neutral_smul_const_vector(
753; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
754;
755  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
756  ret { <4 x i8>, <4 x i1> } %x
757}
758
759define { <4 x i8>, <4 x i1> } @neutral_umul_const_vector() nounwind {
760; CHECK-LABEL: @neutral_umul_const_vector(
761; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }
762;
763  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)
764  ret { <4 x i8>, <4 x i1> } %x
765}
766
767define i8 @smul_neg1(i8 %x, ptr %p) {
768; CHECK-LABEL: @smul_neg1(
769; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[X:%.*]]
770; CHECK-NEXT:    [[OV:%.*]] = icmp eq i8 [[X]], -128
771; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
772; CHECK-NEXT:    ret i8 [[R]]
773;
774  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 -1)
775  %r = extractvalue { i8, i1 } %m, 0
776  %ov = extractvalue { i8, i1 } %m, 1
777  store i1 %ov, ptr %p
778  ret i8 %r
779}
780
781define <4 x i8> @smul_neg1_vec(<4 x i8> %x, ptr %p) {
782; CHECK-LABEL: @smul_neg1_vec(
783; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
784; CHECK-NEXT:    [[OV:%.*]] = icmp eq <4 x i8> [[X]], splat (i8 -128)
785; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
786; CHECK-NEXT:    ret <4 x i8> [[R]]
787;
788  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>)
789  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
790  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
791  store <4 x i1> %ov, ptr %p
792  ret <4 x i8> %r
793}
794
795define <4 x i8> @smul_neg1_vec_poison(<4 x i8> %x, ptr %p) {
796; CHECK-LABEL: @smul_neg1_vec_poison(
797; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
798; CHECK-NEXT:    [[OV:%.*]] = icmp eq <4 x i8> [[X]], splat (i8 -128)
799; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
800; CHECK-NEXT:    ret <4 x i8> [[R]]
801;
802  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 poison, i8 -1>)
803  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
804  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
805  store <4 x i1> %ov, ptr %p
806  ret <4 x i8> %r
807}
808
809define i8 @smul_neg2(i8 %x, ptr %p) {
810; CHECK-LABEL: @smul_neg2(
811; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 -2)
812; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 0
813; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 1
814; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
815; CHECK-NEXT:    ret i8 [[R]]
816;
817  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 -2)
818  %r = extractvalue { i8, i1 } %m, 0
819  %ov = extractvalue { i8, i1 } %m, 1
820  store i1 %ov, ptr %p
821  ret i8 %r
822}
823
824define i8 @umul_neg1(i8 %x, ptr %p) {
825; CHECK-LABEL: @umul_neg1(
826; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[X:%.*]]
827; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 1
828; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
829; CHECK-NEXT:    ret i8 [[R]]
830;
831  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 -1)
832  %r = extractvalue { i8, i1 } %m, 0
833  %ov = extractvalue { i8, i1 } %m, 1
834  store i1 %ov, ptr %p
835  ret i8 %r
836}
837
838define <4 x i8> @umul_neg1_vec(<4 x i8> %x, ptr %p) {
839; CHECK-LABEL: @umul_neg1_vec(
840; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
841; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 1)
842; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
843; CHECK-NEXT:    ret <4 x i8> [[R]]
844;
845  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>)
846  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
847  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
848  store <4 x i1> %ov, ptr %p
849  ret <4 x i8> %r
850}
851
852define <4 x i8> @umul_neg1_vec_poison(<4 x i8> %x, ptr %p) {
853; CHECK-LABEL: @umul_neg1_vec_poison(
854; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
855; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 1)
856; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
857; CHECK-NEXT:    ret <4 x i8> [[R]]
858;
859  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 -1, i8 -1, i8 poison>)
860  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
861  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
862  store <4 x i1> %ov, ptr %p
863  ret <4 x i8> %r
864}
865
866define <4 x i1> @smul_not_neg1_vec(<4 x i8> %x) {
867; CHECK-LABEL: @smul_not_neg1_vec(
868; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i8> [[X:%.*]], splat (i8 -43)
869; CHECK-NEXT:    [[OV:%.*]] = icmp ult <4 x i8> [[TMP1]], splat (i8 -85)
870; CHECK-NEXT:    ret <4 x i1> [[OV]]
871;
872  %m = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -3, i8 -3, i8 poison, i8 -3>)
873  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
874  ret <4 x i1> %ov
875}
876
877; issue #54053
878
879define i8 @umul_neg1_select(i8 %x) {
880; CHECK-LABEL: @umul_neg1_select(
881; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
882; CHECK-NEXT:    [[R:%.*]] = sext i1 [[TMP1]] to i8
883; CHECK-NEXT:    ret i8 [[R]]
884;
885  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 -1)
886  %m0 = extractvalue { i8, i1 } %m, 0
887  %m1 = extractvalue { i8, i1 } %m, 1
888  %r = select i1 %m1, i8 -1, i8 %m0
889  ret i8 %r
890}
891
892define i8 @umul_2(i8 %x, ptr %p) {
893; CHECK-LABEL: @umul_2(
894; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 1
895; CHECK-NEXT:    [[OV:%.*]] = icmp slt i8 [[X]], 0
896; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
897; CHECK-NEXT:    ret i8 [[R]]
898;
899  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 2)
900  %r = extractvalue { i8, i1 } %m, 0
901  %ov = extractvalue { i8, i1 } %m, 1
902  store i1 %ov, ptr %p
903  ret i8 %r
904}
905
906define i8 @umul_8(i8 %x, ptr %p) {
907; CHECK-LABEL: @umul_8(
908; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 3
909; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 31
910; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
911; CHECK-NEXT:    ret i8 [[R]]
912;
913  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 8)
914  %r = extractvalue { i8, i1 } %m, 0
915  %ov = extractvalue { i8, i1 } %m, 1
916  store i1 %ov, ptr %p
917  ret i8 %r
918}
919
920define i8 @umul_64(i8 %x, ptr %p) {
921; CHECK-LABEL: @umul_64(
922; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 6
923; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 3
924; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
925; CHECK-NEXT:    ret i8 [[R]]
926;
927  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 64)
928  %r = extractvalue { i8, i1 } %m, 0
929  %ov = extractvalue { i8, i1 } %m, 1
930  store i1 %ov, ptr %p
931  ret i8 %r
932}
933
934define i8 @umul_256(i8 %x, ptr %p) {
935; CHECK-LABEL: @umul_256(
936; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1
937; CHECK-NEXT:    ret i8 0
938;
939  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 256)
940  %r = extractvalue { i8, i1 } %m, 0
941  %ov = extractvalue { i8, i1 } %m, 1
942  store i1 %ov, ptr %p
943  ret i8 %r
944}
945
946define <4 x i8> @umul_4_vec_poison(<4 x i8> %x, ptr %p) {
947; CHECK-LABEL: @umul_4_vec_poison(
948; CHECK-NEXT:    [[R:%.*]] = shl <4 x i8> [[X:%.*]], splat (i8 2)
949; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 63)
950; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
951; CHECK-NEXT:    ret <4 x i8> [[R]]
952;
953  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 4, i8 4, i8 poison>)
954  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
955  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
956  store <4 x i1> %ov, ptr %p
957  ret <4 x i8> %r
958}
959
960; Negative test: not PowerOf2
961
962define i8 @umul_3(i8 %x, ptr %p) {
963; CHECK-LABEL: @umul_3(
964; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 3)
965; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 0
966; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 1
967; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
968; CHECK-NEXT:    ret i8 [[R]]
969;
970  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 3)
971  %r = extractvalue { i8, i1 } %m, 0
972  %ov = extractvalue { i8, i1 } %m, 1
973  store i1 %ov, ptr %p
974  ret i8 %r
975}
976
977define i8 @smul_4(i8 %x, ptr %p) {
978; CHECK-LABEL: @smul_4(
979; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 2
980; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -32
981; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -64
982; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
983; CHECK-NEXT:    ret i8 [[R]]
984;
985  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 4)
986  %r = extractvalue { i8, i1 } %m, 0
987  %ov = extractvalue { i8, i1 } %m, 1
988  store i1 %ov, ptr %p
989  ret i8 %r
990}
991
992define i8 @smul_16(i8 %x, ptr %p) {
993; CHECK-LABEL: @smul_16(
994; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 4
995; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -8
996; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -16
997; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
998; CHECK-NEXT:    ret i8 [[R]]
999;
1000  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 16)
1001  %r = extractvalue { i8, i1 } %m, 0
1002  %ov = extractvalue { i8, i1 } %m, 1
1003  store i1 %ov, ptr %p
1004  ret i8 %r
1005}
1006
1007define i8 @smul_32(i8 %x, ptr %p) {
1008; CHECK-LABEL: @smul_32(
1009; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 5
1010; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -4
1011; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -8
1012; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
1013; CHECK-NEXT:    ret i8 [[R]]
1014;
1015  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 32)
1016  %r = extractvalue { i8, i1 } %m, 0
1017  %ov = extractvalue { i8, i1 } %m, 1
1018  store i1 %ov, ptr %p
1019  ret i8 %r
1020}
1021
1022define i8 @smul_128(i8 %x, ptr %p) {
1023; CHECK-LABEL: @smul_128(
1024; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 7
1025; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 1
1026; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
1027; CHECK-NEXT:    ret i8 [[R]]
1028;
1029  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 128)
1030  %r = extractvalue { i8, i1 } %m, 0
1031  %ov = extractvalue { i8, i1 } %m, 1
1032  store i1 %ov, ptr %p
1033  ret i8 %r
1034}
1035
1036define <4 x i8> @smul_2_vec_poison(<4 x i8> %x, ptr %p) {
1037; CHECK-LABEL: @smul_2_vec_poison(
1038; CHECK-NEXT:    [[R:%.*]] = shl <4 x i8> [[X:%.*]], splat (i8 1)
1039; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i8> [[X]], splat (i8 64)
1040; CHECK-NEXT:    [[OV:%.*]] = icmp slt <4 x i8> [[TMP1]], zeroinitializer
1041; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1
1042; CHECK-NEXT:    ret <4 x i8> [[R]]
1043;
1044  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 2, i8 2, i8 poison>)
1045  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0
1046  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
1047  store <4 x i1> %ov, ptr %p
1048  ret <4 x i8> %r
1049}
1050
1051; Negative test: not PowerOf2
1052
1053define i8 @smul_7(i8 %x, ptr %p) {
1054; CHECK-LABEL: @smul_7(
1055; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 7)
1056; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 0
1057; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 1
1058; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1
1059; CHECK-NEXT:    ret i8 [[R]]
1060;
1061  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 7)
1062  %r = extractvalue { i8, i1 } %m, 0
1063  %ov = extractvalue { i8, i1 } %m, 1
1064  store i1 %ov, ptr %p
1065  ret i8 %r
1066}
1067