xref: /llvm-project/llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll (revision f1ec0d12bb0843f0deab83ef2b5cf1339cbc4f0b)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -S < %s | FileCheck %s
3; RUN: opt -enable-debugify -passes='require<profile-summary>,function(codegenprepare)' -S < %s 2>&1 | FileCheck %s -check-prefix=DEBUG
4
5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6target triple = "x86_64-apple-darwin10.0.0"
7
8define i64 @uaddo1_overflow_used(i64 %a, i64 %b) nounwind ssp {
9; CHECK-LABEL: @uaddo1_overflow_used(
10; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
11; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
12; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
13; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
14; CHECK-NEXT:    ret i64 [[Q]]
15;
16  %add = add i64 %b, %a
17  %cmp = icmp ult i64 %add, %a
18  %Q = select i1 %cmp, i64 %b, i64 42
19  ret i64 %Q
20}
21
22define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
23; CHECK-LABEL: @uaddo1_math_overflow_used(
24; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
25; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
26; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
27; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
28; CHECK-NEXT:    store i64 [[MATH]], ptr [[RES:%.*]]
29; CHECK-NEXT:    ret i64 [[Q]]
30;
31  %add = add i64 %b, %a
32  %cmp = icmp ult i64 %add, %a
33  %Q = select i1 %cmp, i64 %b, i64 42
34  store i64 %add, ptr %res
35  ret i64 %Q
36}
37
38define i64 @uaddo2_overflow_used(i64 %a, i64 %b) nounwind ssp {
39; CHECK-LABEL: @uaddo2_overflow_used(
40; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
41; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
42; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
43; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
44; CHECK-NEXT:    ret i64 [[Q]]
45;
46  %add = add i64 %b, %a
47  %cmp = icmp ult i64 %add, %b
48  %Q = select i1 %cmp, i64 %b, i64 42
49  ret i64 %Q
50}
51
52define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
53; CHECK-LABEL: @uaddo2_math_overflow_used(
54; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
55; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
56; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
57; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
58; CHECK-NEXT:    store i64 [[MATH]], ptr [[RES:%.*]]
59; CHECK-NEXT:    ret i64 [[Q]]
60;
61  %add = add i64 %b, %a
62  %cmp = icmp ult i64 %add, %b
63  %Q = select i1 %cmp, i64 %b, i64 42
64  store i64 %add, ptr %res
65  ret i64 %Q
66}
67
68define i64 @uaddo3_overflow_used(i64 %a, i64 %b) nounwind ssp {
69; CHECK-LABEL: @uaddo3_overflow_used(
70; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
71; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
72; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
73; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
74; CHECK-NEXT:    ret i64 [[Q]]
75;
76  %add = add i64 %b, %a
77  %cmp = icmp ugt i64 %b, %add
78  %Q = select i1 %cmp, i64 %b, i64 42
79  ret i64 %Q
80}
81
82define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
83; CHECK-LABEL: @uaddo3_math_overflow_used(
84; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
85; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
86; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
87; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
88; CHECK-NEXT:    store i64 [[MATH]], ptr [[RES:%.*]]
89; CHECK-NEXT:    ret i64 [[Q]]
90;
91  %add = add i64 %b, %a
92  %cmp = icmp ugt i64 %b, %add
93  %Q = select i1 %cmp, i64 %b, i64 42
94  store i64 %add, ptr %res
95  ret i64 %Q
96}
97
98; TODO? CGP sinks the compare before we have a chance to form the overflow intrinsic.
99
100define i64 @uaddo4(i64 %a, i64 %b, i1 %c) nounwind ssp {
101; CHECK-LABEL: @uaddo4(
102; CHECK-NEXT:  entry:
103; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[B:%.*]], [[A:%.*]]
104; CHECK-NEXT:    br i1 [[C:%.*]], label [[NEXT:%.*]], label [[EXIT:%.*]]
105; CHECK:       next:
106; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[B]], [[ADD]]
107; CHECK-NEXT:    [[Q:%.*]] = select i1 [[TMP0]], i64 [[B]], i64 42
108; CHECK-NEXT:    ret i64 [[Q]]
109; CHECK:       exit:
110; CHECK-NEXT:    ret i64 0
111;
112entry:
113  %add = add i64 %b, %a
114  %cmp = icmp ugt i64 %b, %add
115  br i1 %c, label %next, label %exit
116
117next:
118  %Q = select i1 %cmp, i64 %b, i64 42
119  ret i64 %Q
120
121exit:
122  ret i64 0
123}
124
125define i64 @uaddo5(i64 %a, i64 %b, ptr %ptr, i1 %c) nounwind ssp {
126; CHECK-LABEL: @uaddo5(
127; CHECK-NEXT:  entry:
128; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[B:%.*]], [[A:%.*]]
129; CHECK-NEXT:    store i64 [[ADD]], ptr [[PTR:%.*]]
130; CHECK-NEXT:    br i1 [[C:%.*]], label [[NEXT:%.*]], label [[EXIT:%.*]]
131; CHECK:       next:
132; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[B]], [[ADD]]
133; CHECK-NEXT:    [[Q:%.*]] = select i1 [[TMP0]], i64 [[B]], i64 42
134; CHECK-NEXT:    ret i64 [[Q]]
135; CHECK:       exit:
136; CHECK-NEXT:    ret i64 0
137;
138entry:
139  %add = add i64 %b, %a
140  store i64 %add, ptr %ptr
141  %cmp = icmp ugt i64 %b, %add
142  br i1 %c, label %next, label %exit
143
144next:
145  %Q = select i1 %cmp, i64 %b, i64 42
146  ret i64 %Q
147
148exit:
149  ret i64 0
150}
151
152; Instcombine folds (a + b <u a)  to (a ^ -1 <u b). Make sure we match this
153; pattern as well.
154define i64 @uaddo6_xor(i64 %a, i64 %b) {
155; CHECK-LABEL: @uaddo6_xor(
156; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])
157; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
158; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
159; CHECK-NEXT:    ret i64 [[Q]]
160;
161  %x = xor i64 %a, -1
162  %cmp = icmp ult i64 %x, %b
163  %Q = select i1 %cmp, i64 %b, i64 42
164  ret i64 %Q
165}
166
167define i64 @uaddo6_xor_commuted(i64 %a, i64 %b) {
168; CHECK-LABEL: @uaddo6_xor_commuted(
169; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])
170; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
171; CHECK-NEXT:    [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
172; CHECK-NEXT:    ret i64 [[Q]]
173;
174  %x = xor i64 %a, -1
175  %cmp = icmp ult i64 %x, %b
176  %Q = select i1 %cmp, i64 %b, i64 42
177  ret i64 %Q
178}
179
180declare void @use(i64)
181
182define i64 @uaddo6_xor_multi_use(i64 %a, i64 %b) {
183; CHECK-LABEL: @uaddo6_xor_multi_use(
184; CHECK-NEXT:    [[X:%.*]] = xor i64 -1, [[A:%.*]]
185; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[X]], [[B:%.*]]
186; CHECK-NEXT:    [[Q:%.*]] = select i1 [[CMP]], i64 [[B]], i64 42
187; CHECK-NEXT:    call void @use(i64 [[X]])
188; CHECK-NEXT:    ret i64 [[Q]]
189;
190  %x = xor i64 -1, %a
191  %cmp = icmp ult i64 %x, %b
192  %Q = select i1 %cmp, i64 %b, i64 42
193  call void @use(i64 %x)
194  ret i64 %Q
195}
196
197; Make sure we do not use the XOR binary operator as insert point, as it may
198; come before the second operand of the overflow intrinsic.
199define i1 @uaddo6_xor_op_after_XOR(i32 %a, ptr %b.ptr) {
200; CHECK-LABEL: @uaddo6_xor_op_after_XOR(
201; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 8
202; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B]])
203; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
204; CHECK-NEXT:    [[OV:%.*]] = xor i1 [[OV1]], true
205; CHECK-NEXT:    ret i1 [[OV]]
206;
207  %x = xor i32 %a, -1
208  %b = load i32, ptr %b.ptr, align 8
209  %cmp14 = icmp ugt i32 %b, %x
210  %ov = xor i1 %cmp14, true
211  ret i1 %ov
212}
213
214; When adding 1, the general pattern for add-overflow may be different due to icmp canonicalization.
215; PR31754: https://bugs.llvm.org/show_bug.cgi?id=31754
216
217define i1 @uaddo_i64_increment(i64 %x, ptr %p) {
218; CHECK-LABEL: @uaddo_i64_increment(
219; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
220; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
221; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
222; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
223; CHECK-NEXT:    ret i1 [[OV1]]
224;
225  %a = add i64 %x, 1
226  %ov = icmp eq i64 %a, 0
227  store i64 %a, ptr %p
228  ret i1 %ov
229}
230
231define i1 @uaddo_i8_increment_noncanonical_1(i8 %x, ptr %p) {
232; CHECK-LABEL: @uaddo_i8_increment_noncanonical_1(
233; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 1, i8 [[X:%.*]])
234; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
235; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
236; CHECK-NEXT:    store i8 [[MATH]], ptr [[P:%.*]]
237; CHECK-NEXT:    ret i1 [[OV1]]
238;
239  %a = add i8 1, %x        ; commute
240  %ov = icmp eq i8 %a, 0
241  store i8 %a, ptr %p
242  ret i1 %ov
243}
244
245define i1 @uaddo_i32_increment_noncanonical_2(i32 %x, ptr %p) {
246; CHECK-LABEL: @uaddo_i32_increment_noncanonical_2(
247; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1)
248; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
249; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
250; CHECK-NEXT:    store i32 [[MATH]], ptr [[P:%.*]]
251; CHECK-NEXT:    ret i1 [[OV1]]
252;
253  %a = add i32 %x, 1
254  %ov = icmp eq i32 0, %a   ; commute
255  store i32 %a, ptr %p
256  ret i1 %ov
257}
258
259define i1 @uaddo_i16_increment_noncanonical_3(i16 %x, ptr %p) {
260; CHECK-LABEL: @uaddo_i16_increment_noncanonical_3(
261; CHECK-NEXT:    [[TMP1:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 1, i16 [[X:%.*]])
262; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
263; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
264; CHECK-NEXT:    store i16 [[MATH]], ptr [[P:%.*]]
265; CHECK-NEXT:    ret i1 [[OV1]]
266;
267  %a = add i16 1, %x        ; commute
268  %ov = icmp eq i16 0, %a   ; commute
269  store i16 %a, ptr %p
270  ret i1 %ov
271}
272
273; The overflow check may be against the input rather than the sum.
274
275define i1 @uaddo_i64_increment_alt(i64 %x, ptr %p) {
276; CHECK-LABEL: @uaddo_i64_increment_alt(
277; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
278; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
279; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
280; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
281; CHECK-NEXT:    ret i1 [[OV1]]
282;
283  %a = add i64 %x, 1
284  store i64 %a, ptr %p
285  %ov = icmp eq i64 %x, -1
286  ret i1 %ov
287}
288
289; Make sure insertion is done correctly based on dominance.
290
291define i1 @uaddo_i64_increment_alt_dom(i64 %x, ptr %p) {
292; CHECK-LABEL: @uaddo_i64_increment_alt_dom(
293; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
294; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
295; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
296; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
297; CHECK-NEXT:    ret i1 [[OV1]]
298;
299  %ov = icmp eq i64 %x, -1
300  %a = add i64 %x, 1
301  store i64 %a, ptr %p
302  ret i1 %ov
303}
304
305; The overflow check may be against the input rather than the sum.
306
307define i1 @uaddo_i64_decrement_alt(i64 %x, ptr %p) {
308; CHECK-LABEL: @uaddo_i64_decrement_alt(
309; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
310; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
311; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
312; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
313; CHECK-NEXT:    ret i1 [[OV1]]
314;
315  %a = add i64 %x, -1
316  store i64 %a, ptr %p
317  %ov = icmp ne i64 %x, 0
318  ret i1 %ov
319}
320
321; Make sure insertion is done correctly based on dominance.
322
323define i1 @uaddo_i64_decrement_alt_dom(i64 %x, ptr %p) {
324; CHECK-LABEL: @uaddo_i64_decrement_alt_dom(
325; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
326; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
327; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
328; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
329; CHECK-NEXT:    ret i1 [[OV1]]
330;
331  %ov = icmp ne i64 %x, 0
332  %a = add i64 %x, -1
333  store i64 %a, ptr %p
334  ret i1 %ov
335}
336
337; No transform for illegal types.
338
339define i1 @uaddo_i42_increment_illegal_type(i42 %x, ptr %p) {
340; CHECK-LABEL: @uaddo_i42_increment_illegal_type(
341; CHECK-NEXT:    [[A:%.*]] = add i42 [[X:%.*]], 1
342; CHECK-NEXT:    [[OV:%.*]] = icmp eq i42 [[A]], 0
343; CHECK-NEXT:    store i42 [[A]], ptr [[P:%.*]]
344; CHECK-NEXT:    ret i1 [[OV]]
345;
346  %a = add i42 %x, 1
347  %ov = icmp eq i42 %a, 0
348  store i42 %a, ptr %p
349  ret i1 %ov
350}
351
352define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
353; CHECK-LABEL: @usubo_ult_i64_overflow_used(
354; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
355; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
356; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
357; CHECK-NEXT:    ret i1 [[OV1]]
358;
359  %s = sub i64 %x, %y
360  %ov = icmp ult i64 %x, %y
361  ret i1 %ov
362}
363
364define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
365; CHECK-LABEL: @usubo_ult_i64_math_overflow_used(
366; CHECK-NEXT:    [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
367; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
368; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
369; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
370; CHECK-NEXT:    ret i1 [[OV1]]
371;
372  %s = sub i64 %x, %y
373  store i64 %s, ptr %p
374  %ov = icmp ult i64 %x, %y
375  ret i1 %ov
376}
377
378; Verify insertion point for single-BB. Toggle predicate.
379
380define i1 @usubo_ugt_i32(i32 %x, i32 %y, ptr %p) {
381; CHECK-LABEL: @usubo_ugt_i32(
382; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
383; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
384; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
385; CHECK-NEXT:    store i32 [[MATH]], ptr [[P:%.*]]
386; CHECK-NEXT:    ret i1 [[OV1]]
387;
388  %ov = icmp ugt i32 %y, %x
389  %s = sub i32 %x, %y
390  store i32 %s, ptr %p
391  ret i1 %ov
392}
393
394; Constant operand should match.
395
396define i1 @usubo_ugt_constant_op0_i8(i8 %x, ptr %p) {
397; CHECK-LABEL: @usubo_ugt_constant_op0_i8(
398; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 42, i8 [[X:%.*]])
399; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
400; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
401; CHECK-NEXT:    store i8 [[MATH]], ptr [[P:%.*]]
402; CHECK-NEXT:    ret i1 [[OV1]]
403;
404  %s = sub i8 42, %x
405  %ov = icmp ugt i8 %x, 42
406  store i8 %s, ptr %p
407  ret i1 %ov
408}
409
410; Compare with constant operand 0 is canonicalized by commuting, but verify match for non-canonical form.
411
412define i1 @usubo_ult_constant_op0_i16(i16 %x, ptr %p) {
413; CHECK-LABEL: @usubo_ult_constant_op0_i16(
414; CHECK-NEXT:    [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 43, i16 [[X:%.*]])
415; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
416; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
417; CHECK-NEXT:    store i16 [[MATH]], ptr [[P:%.*]]
418; CHECK-NEXT:    ret i1 [[OV1]]
419;
420  %s = sub i16 43, %x
421  %ov = icmp ult i16 43, %x
422  store i16 %s, ptr %p
423  ret i1 %ov
424}
425
426; Subtract with constant operand 1 is canonicalized to add.
427
428define i1 @usubo_ult_constant_op1_i16(i16 %x, ptr %p) {
429; CHECK-LABEL: @usubo_ult_constant_op1_i16(
430; CHECK-NEXT:    [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 [[X:%.*]], i16 44)
431; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
432; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
433; CHECK-NEXT:    store i16 [[MATH]], ptr [[P:%.*]]
434; CHECK-NEXT:    ret i1 [[OV1]]
435;
436  %s = add i16 %x, -44
437  %ov = icmp ult i16 %x, 44
438  store i16 %s, ptr %p
439  ret i1 %ov
440}
441
442define i1 @usubo_ugt_constant_op1_i8(i8 %x, ptr %p) {
443; CHECK-LABEL: @usubo_ugt_constant_op1_i8(
444; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 45)
445; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
446; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
447; CHECK-NEXT:    store i8 [[MATH]], ptr [[P:%.*]]
448; CHECK-NEXT:    ret i1 [[OV1]]
449;
450  %ov = icmp ugt i8 45, %x
451  %s = add i8 %x, -45
452  store i8 %s, ptr %p
453  ret i1 %ov
454}
455
456; Special-case: subtract 1 changes the compare predicate and constant.
457
458define i1 @usubo_eq_constant1_op1_i32(i32 %x, ptr %p) {
459; CHECK-LABEL: @usubo_eq_constant1_op1_i32(
460; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 1)
461; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
462; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
463; CHECK-NEXT:    store i32 [[MATH]], ptr [[P:%.*]]
464; CHECK-NEXT:    ret i1 [[OV1]]
465;
466  %s = add i32 %x, -1
467  %ov = icmp eq i32 %x, 0
468  store i32 %s, ptr %p
469  ret i1 %ov
470}
471
472; Special-case: subtract from 0 (negate) changes the compare predicate.
473
474define i1 @usubo_ne_constant0_op1_i32(i32 %x, ptr %p) {
475; CHECK-LABEL: @usubo_ne_constant0_op1_i32(
476; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 0, i32 [[X:%.*]])
477; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
478; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
479; CHECK-NEXT:    store i32 [[MATH]], ptr [[P:%.*]]
480; CHECK-NEXT:    ret i1 [[OV1]]
481;
482  %s = sub i32 0, %x
483  %ov = icmp ne i32 %x, 0
484  store i32 %s, ptr %p
485  ret i1 %ov
486}
487
488; This used to verify insertion point for multi-BB, but now we just bail out.
489
490declare void @call(i1)
491
492define i1 @usubo_ult_sub_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) {
493; CHECK-LABEL: @usubo_ult_sub_dominates_i64(
494; CHECK-NEXT:  entry:
495; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
496; CHECK:       t:
497; CHECK-NEXT:    [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
498; CHECK-NEXT:    store i64 [[S]], ptr [[P:%.*]]
499; CHECK-NEXT:    br i1 [[COND]], label [[END:%.*]], label [[F]]
500; CHECK:       f:
501; CHECK-NEXT:    ret i1 [[COND]]
502; CHECK:       end:
503; CHECK-NEXT:    [[OV:%.*]] = icmp ult i64 [[X]], [[Y]]
504; CHECK-NEXT:    ret i1 [[OV]]
505;
506entry:
507  br i1 %cond, label %t, label %f
508
509t:
510  %s = sub i64 %x, %y
511  store i64 %s, ptr %p
512  br i1 %cond, label %end, label %f
513
514f:
515  ret i1 %cond
516
517end:
518  %ov = icmp ult i64 %x, %y
519  ret i1 %ov
520}
521
522define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) {
523; CHECK-LABEL: @usubo_ult_cmp_dominates_i64(
524; CHECK-NEXT:  entry:
525; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
526; CHECK:       t:
527; CHECK-NEXT:    [[OV:%.*]] = icmp ult i64 [[X:%.*]], [[Y:%.*]]
528; CHECK-NEXT:    call void @call(i1 [[OV]])
529; CHECK-NEXT:    br i1 [[OV]], label [[END:%.*]], label [[F]]
530; CHECK:       f:
531; CHECK-NEXT:    ret i1 [[COND]]
532; CHECK:       end:
533; CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X]], i64 [[Y]])
534; CHECK-NEXT:    [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0
535; CHECK-NEXT:    [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
536; CHECK-NEXT:    store i64 [[MATH]], ptr [[P:%.*]]
537; CHECK-NEXT:    ret i1 [[OV1]]
538;
539entry:
540  br i1 %cond, label %t, label %f
541
542t:
543  %ov = icmp ult i64 %x, %y
544  call void @call(i1 %ov)
545  br i1 %ov, label %end, label %f
546
547f:
548  ret i1 %cond
549
550end:
551  %s = sub i64 %x, %y
552  store i64 %s, ptr %p
553  ret i1 %ov
554}
555
556; Verify that crazy/non-canonical code does not crash.
557
558define void @bar() {
559; CHECK-LABEL: @bar(
560; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 1, -1
561; CHECK-NEXT:    [[FROMBOOL:%.*]] = zext i1 [[CMP]] to i8
562; CHECK-NEXT:    unreachable
563;
564  %cmp = icmp eq i64 1, -1
565  %frombool = zext i1 %cmp to i8
566  unreachable
567}
568
569define void @foo() {
570; CHECK-LABEL: @foo(
571; CHECK-NEXT:    [[SUB:%.*]] = add nsw i64 1, 1
572; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[SUB]] to i32
573; CHECK-NEXT:    unreachable
574;
575  %sub = add nsw i64 1, 1
576  %conv = trunc i64 %sub to i32
577  unreachable
578}
579
580; Similarly for usubo.
581
582define i1 @bar2() {
583; CHECK-LABEL: @bar2(
584; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 1, 0
585; CHECK-NEXT:    ret i1 [[CMP]]
586;
587  %cmp = icmp eq i64 1, 0
588  ret i1 %cmp
589}
590
591define i64 @foo2(ptr %p) {
592; CHECK-LABEL: @foo2(
593; CHECK-NEXT:    [[SUB:%.*]] = add nsw i64 1, -1
594; CHECK-NEXT:    ret i64 [[SUB]]
595;
596  %sub = add nsw i64 1, -1
597  ret i64 %sub
598}
599
600; Avoid hoisting a math op into a dominating block which would
601; increase the critical path.
602
603define void @PR41129(ptr %p64) {
604; CHECK-LABEL: @PR41129(
605; CHECK-NEXT:  entry:
606; CHECK-NEXT:    [[KEY:%.*]] = load i64, ptr [[P64:%.*]], align 8
607; CHECK-NEXT:    [[COND17:%.*]] = icmp eq i64 [[KEY]], 0
608; CHECK-NEXT:    br i1 [[COND17]], label [[TRUE:%.*]], label [[FALSE:%.*]]
609; CHECK:       false:
610; CHECK-NEXT:    [[ANDVAL:%.*]] = and i64 [[KEY]], 7
611; CHECK-NEXT:    store i64 [[ANDVAL]], ptr [[P64]]
612; CHECK-NEXT:    br label [[EXIT:%.*]]
613; CHECK:       true:
614; CHECK-NEXT:    [[SVALUE:%.*]] = add i64 [[KEY]], -1
615; CHECK-NEXT:    store i64 [[SVALUE]], ptr [[P64]]
616; CHECK-NEXT:    br label [[EXIT]]
617; CHECK:       exit:
618; CHECK-NEXT:    ret void
619;
620entry:
621  %key = load i64, ptr %p64, align 8
622  %cond17 = icmp eq i64 %key, 0
623  br i1 %cond17, label %true, label %false
624
625false:
626  %andval = and i64 %key, 7
627  store i64 %andval, ptr %p64
628  br label %exit
629
630true:
631  %svalue = add i64 %key, -1
632  store i64 %svalue, ptr %p64
633  br label %exit
634
635exit:
636  ret void
637}
638
639; Check that every instruction inserted by -passes='require<profile-summary>,function(codegenprepare)' has a debug location.
640; DEBUG: CheckModuleDebugify: PASS
641
642