xref: /llvm-project/llvm/test/Transforms/InstCombine/abs-1.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
5
6declare i32 @abs(i32)
7declare i64 @labs(i64)
8declare i64 @llabs(i64)
9
10; Test that the abs library call simplifier works correctly.
11; abs(x) -> x <s 0 ? -x : x.
12
13define i32 @test_abs(i32 %x) {
14; CHECK-LABEL: @test_abs(
15; CHECK-NEXT:    [[RET:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
16; CHECK-NEXT:    ret i32 [[RET]]
17;
18  %ret = call i32 @abs(i32 %x)
19  ret i32 %ret
20}
21
22define i64 @test_labs(i64 %x) {
23; CHECK-LABEL: @test_labs(
24; CHECK-NEXT:    [[RET:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true)
25; CHECK-NEXT:    ret i64 [[RET]]
26;
27  %ret = call i64 @labs(i64 %x)
28  ret i64 %ret
29}
30
31define i64 @test_llabs(i64 %x) {
32; CHECK-LABEL: @test_llabs(
33; CHECK-NEXT:    [[RET:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true)
34; CHECK-NEXT:    ret i64 [[RET]]
35;
36  %ret = call i64 @llabs(i64 %x)
37  ret i64 %ret
38}
39
40; We have a canonical form of abs to make CSE easier.
41
42define i8 @abs_canonical_1(i8 %x) {
43; CHECK-LABEL: @abs_canonical_1(
44; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
45; CHECK-NEXT:    ret i8 [[ABS]]
46;
47  %cmp = icmp sgt i8 %x, 0
48  %neg = sub i8 0, %x
49  %abs = select i1 %cmp, i8 %x, i8 %neg
50  ret i8 %abs
51}
52
53; Vectors should work too.
54
55define <2 x i8> @abs_canonical_2(<2 x i8> %x) {
56; CHECK-LABEL: @abs_canonical_2(
57; CHECK-NEXT:    [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
58; CHECK-NEXT:    ret <2 x i8> [[ABS]]
59;
60  %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
61  %neg = sub <2 x i8> zeroinitializer, %x
62  %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg
63  ret <2 x i8> %abs
64}
65
66; Even if a constant has poison elements.
67
68define <2 x i8> @abs_canonical_2_vec_poison_elts(<2 x i8> %x) {
69; CHECK-LABEL: @abs_canonical_2_vec_poison_elts(
70; CHECK-NEXT:    [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
71; CHECK-NEXT:    ret <2 x i8> [[ABS]]
72;
73  %cmp = icmp sgt <2 x i8> %x, <i8 poison, i8 -1>
74  %neg = sub <2 x i8> zeroinitializer, %x
75  %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg
76  ret <2 x i8> %abs
77}
78
79; NSW should not change.
80
81define i8 @abs_canonical_3(i8 %x) {
82; CHECK-LABEL: @abs_canonical_3(
83; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
84; CHECK-NEXT:    ret i8 [[ABS]]
85;
86  %cmp = icmp slt i8 %x, 0
87  %neg = sub nsw i8 0, %x
88  %abs = select i1 %cmp, i8 %neg, i8 %x
89  ret i8 %abs
90}
91
92define i8 @abs_canonical_4(i8 %x) {
93; CHECK-LABEL: @abs_canonical_4(
94; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
95; CHECK-NEXT:    ret i8 [[ABS]]
96;
97  %cmp = icmp slt i8 %x, 1
98  %neg = sub i8 0, %x
99  %abs = select i1 %cmp, i8 %neg, i8 %x
100  ret i8 %abs
101}
102
103define i32 @abs_canonical_5(i8 %x) {
104; CHECK-LABEL: @abs_canonical_5(
105; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
106; CHECK-NEXT:    [[ABS:%.*]] = zext i8 [[TMP1]] to i32
107; CHECK-NEXT:    ret i32 [[ABS]]
108;
109  %cmp = icmp sgt i8 %x, 0
110  %conv = sext i8 %x to i32
111  %neg = sub i32 0, %conv
112  %abs = select i1 %cmp, i32 %conv, i32 %neg
113  ret i32 %abs
114}
115
116define i32 @abs_canonical_6(i32 %a, i32 %b) {
117; CHECK-LABEL: @abs_canonical_6(
118; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
119; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
120; CHECK-NEXT:    ret i32 [[ABS]]
121;
122  %t1 = sub i32 %a, %b
123  %cmp = icmp sgt i32 %t1, -1
124  %t2 = sub i32 %b, %a
125  %abs = select i1 %cmp, i32 %t1, i32 %t2
126  ret i32 %abs
127}
128
129define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
130; CHECK-LABEL: @abs_canonical_7(
131; CHECK-NEXT:    [[T1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
132; CHECK-NEXT:    [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[T1]], i1 false)
133; CHECK-NEXT:    ret <2 x i8> [[ABS]]
134;
135
136  %t1 = sub <2 x i8> %a, %b
137  %cmp = icmp sgt <2 x i8> %t1, <i8 -1, i8 -1>
138  %t2 = sub <2 x i8> %b, %a
139  %abs = select <2 x i1> %cmp, <2 x i8> %t1, <2 x i8> %t2
140  ret <2 x i8> %abs
141}
142
143define i32 @abs_canonical_8(i32 %a) {
144; CHECK-LABEL: @abs_canonical_8(
145; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false)
146; CHECK-NEXT:    ret i32 [[ABS]]
147;
148  %t = sub i32 0, %a
149  %cmp = icmp slt i32 %t, 0
150  %abs = select i1 %cmp, i32 %a, i32 %t
151  ret i32 %abs
152}
153
154define i32 @abs_canonical_9(i32 %a, i32 %b) {
155; CHECK-LABEL: @abs_canonical_9(
156; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
157; CHECK-NEXT:    [[T2:%.*]] = sub i32 [[B]], [[A]]
158; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
159; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[ABS]], [[T2]]
160; CHECK-NEXT:    ret i32 [[ADD]]
161;
162  %t1 = sub i32 %a, %b
163  %cmp = icmp sgt i32 %t1, -1
164  %t2 = sub i32 %b, %a
165  %abs = select i1 %cmp, i32 %t1, i32 %t2
166  %add = add i32 %abs, %t2 ; increase use count for %t2.
167  ret i32 %add
168}
169
170define i32 @abs_canonical_10(i32 %a, i32 %b) {
171; CHECK-LABEL: @abs_canonical_10(
172; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
173; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
174; CHECK-NEXT:    ret i32 [[ABS]]
175;
176  %t2 = sub i32 %b, %a
177  %t1 = sub i32 %a, %b
178  %cmp = icmp sgt i32 %t1, -1
179  %abs = select i1 %cmp, i32 %t1, i32 %t2
180  ret i32 %abs
181}
182
183; We have a canonical form of nabs to make CSE easier.
184
185define i8 @nabs_canonical_1(i8 %x) {
186; CHECK-LABEL: @nabs_canonical_1(
187; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
188; CHECK-NEXT:    [[ABS:%.*]] = sub i8 0, [[TMP1]]
189; CHECK-NEXT:    ret i8 [[ABS]]
190;
191  %cmp = icmp sgt i8 %x, 0
192  %neg = sub i8 0, %x
193  %abs = select i1 %cmp, i8 %neg, i8 %x
194  ret i8 %abs
195}
196
197; Vectors should work too.
198
199define <2 x i8> @nabs_canonical_2(<2 x i8> %x) {
200; CHECK-LABEL: @nabs_canonical_2(
201; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
202; CHECK-NEXT:    [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
203; CHECK-NEXT:    ret <2 x i8> [[ABS]]
204;
205  %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
206  %neg = sub <2 x i8> zeroinitializer, %x
207  %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
208  ret <2 x i8> %abs
209}
210
211; Even if a constant has poison elements.
212
213define <2 x i8> @nabs_canonical_2_vec_poison_elts(<2 x i8> %x) {
214; CHECK-LABEL: @nabs_canonical_2_vec_poison_elts(
215; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
216; CHECK-NEXT:    [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
217; CHECK-NEXT:    ret <2 x i8> [[ABS]]
218;
219  %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 poison>
220  %neg = sub <2 x i8> zeroinitializer, %x
221  %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
222  ret <2 x i8> %abs
223}
224
225; NSW should not change.
226
227define i8 @nabs_canonical_3(i8 %x) {
228; CHECK-LABEL: @nabs_canonical_3(
229; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
230; CHECK-NEXT:    [[ABS:%.*]] = sub i8 0, [[TMP1]]
231; CHECK-NEXT:    ret i8 [[ABS]]
232;
233  %cmp = icmp slt i8 %x, 0
234  %neg = sub nsw i8 0, %x
235  %abs = select i1 %cmp, i8 %x, i8 %neg
236  ret i8 %abs
237}
238
239define i8 @nabs_canonical_4(i8 %x) {
240; CHECK-LABEL: @nabs_canonical_4(
241; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
242; CHECK-NEXT:    [[ABS:%.*]] = sub i8 0, [[TMP1]]
243; CHECK-NEXT:    ret i8 [[ABS]]
244;
245  %cmp = icmp slt i8 %x, 1
246  %neg = sub i8 0, %x
247  %abs = select i1 %cmp, i8 %x, i8 %neg
248  ret i8 %abs
249}
250
251define i32 @nabs_canonical_5(i8 %x) {
252; CHECK-LABEL: @nabs_canonical_5(
253; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
254; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
255; CHECK-NEXT:    [[ABS:%.*]] = sub nsw i32 0, [[TMP2]]
256; CHECK-NEXT:    ret i32 [[ABS]]
257;
258  %cmp = icmp sgt i8 %x, 0
259  %conv = sext i8 %x to i32
260  %neg = sub i32 0, %conv
261  %abs = select i1 %cmp, i32 %neg, i32 %conv
262  ret i32 %abs
263}
264
265define i32 @nabs_canonical_6(i32 %a, i32 %b) {
266; CHECK-LABEL: @nabs_canonical_6(
267; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
268; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
269; CHECK-NEXT:    [[ABS:%.*]] = sub i32 0, [[TMP1]]
270; CHECK-NEXT:    ret i32 [[ABS]]
271;
272  %t1 = sub i32 %a, %b
273  %cmp = icmp sgt i32 %t1, -1
274  %t2 = sub i32 %b, %a
275  %abs = select i1 %cmp, i32 %t2, i32 %t1
276  ret i32 %abs
277}
278
279define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
280; CHECK-LABEL: @nabs_canonical_7(
281; CHECK-NEXT:    [[T1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
282; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[T1]], i1 false)
283; CHECK-NEXT:    [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
284; CHECK-NEXT:    ret <2 x i8> [[ABS]]
285;
286  %t1 = sub <2 x i8> %a, %b
287  %cmp = icmp sgt <2 x i8> %t1, <i8 -1, i8 -1>
288  %t2 = sub <2 x i8> %b, %a
289  %abs = select <2 x i1> %cmp, <2 x i8> %t2, <2 x i8> %t1
290  ret <2 x i8> %abs
291}
292
293define i32 @nabs_canonical_8(i32 %a) {
294; CHECK-LABEL: @nabs_canonical_8(
295; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false)
296; CHECK-NEXT:    [[ABS:%.*]] = sub i32 0, [[TMP1]]
297; CHECK-NEXT:    ret i32 [[ABS]]
298;
299  %t = sub i32 0, %a
300  %cmp = icmp slt i32 %t, 0
301  %abs = select i1 %cmp, i32 %t, i32 %a
302  ret i32 %abs
303}
304
305define i32 @nabs_canonical_9(i32 %a, i32 %b) {
306; CHECK-LABEL: @nabs_canonical_9(
307; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
308; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
309; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[A]], [[TMP1]]
310; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[B]], [[TMP2]]
311; CHECK-NEXT:    ret i32 [[ADD]]
312;
313  %t1 = sub i32 %a, %b
314  %cmp = icmp sgt i32 %t1, -1
315  %t2 = sub i32 %b, %a
316  %abs = select i1 %cmp, i32 %t2, i32 %t1
317  %add = add i32 %t2, %abs ; increase use count for %t2
318  ret i32 %add
319}
320
321define i32 @nabs_canonical_10(i32 %a, i32 %b) {
322; CHECK-LABEL: @nabs_canonical_10(
323; CHECK-NEXT:    [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
324; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false)
325; CHECK-NEXT:    [[ABS:%.*]] = sub i32 0, [[TMP1]]
326; CHECK-NEXT:    ret i32 [[ABS]]
327;
328  %t2 = sub i32 %b, %a
329  %t1 = sub i32 %a, %b
330  %cmp = icmp slt i32 %t1, 1
331  %abs = select i1 %cmp, i32 %t1, i32 %t2
332  ret i32 %abs
333}
334
335; The following 5 tests use a shift+add+xor to implement abs():
336; B = ashr i8 A, 7  -- smear the sign bit.
337; xor (add A, B), B -- add -1 and flip bits if negative
338
339define i8 @shifty_abs_commute0(i8 %x) {
340; CHECK-LABEL: @shifty_abs_commute0(
341; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
342; CHECK-NEXT:    ret i8 [[ABS]]
343;
344  %signbit = ashr i8 %x, 7
345  %add = add i8 %signbit, %x
346  %abs = xor i8 %add, %signbit
347  ret i8 %abs
348}
349
350define i8 @shifty_abs_commute0_nsw(i8 %x) {
351; CHECK-LABEL: @shifty_abs_commute0_nsw(
352; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
353; CHECK-NEXT:    ret i8 [[ABS]]
354;
355  %signbit = ashr i8 %x, 7
356  %add = add nsw i8 %signbit, %x
357  %abs = xor i8 %add, %signbit
358  ret i8 %abs
359}
360
361; The nuw flag creates a contradiction. If the shift produces all 1s, the only
362; way for the add to not wrap is for %x to be 0, but then the shift couldn't
363; have produced all 1s. We partially optimize this.
364define i8 @shifty_abs_commute0_nuw(i8 %x) {
365; CHECK-LABEL: @shifty_abs_commute0_nuw(
366; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 0)
367; CHECK-NEXT:    ret i8 [[ABS]]
368;
369  %signbit = ashr i8 %x, 7
370  %add = add nuw i8 %signbit, %x
371  %abs = xor i8 %add, %signbit
372  ret i8 %abs
373}
374
375define <2 x i8> @shifty_abs_commute1(<2 x i8> %x) {
376; CHECK-LABEL: @shifty_abs_commute1(
377; CHECK-NEXT:    [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
378; CHECK-NEXT:    ret <2 x i8> [[ABS]]
379;
380  %signbit = ashr <2 x i8> %x, <i8 7, i8 7>
381  %add = add <2 x i8> %signbit, %x
382  %abs = xor <2 x i8> %signbit, %add
383  ret <2 x i8> %abs
384}
385
386define <2 x i8> @shifty_abs_commute2(<2 x i8> %x) {
387; CHECK-LABEL: @shifty_abs_commute2(
388; CHECK-NEXT:    [[Y:%.*]] = mul <2 x i8> [[X:%.*]], splat (i8 3)
389; CHECK-NEXT:    [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[Y]], i1 false)
390; CHECK-NEXT:    ret <2 x i8> [[ABS]]
391;
392  %y = mul <2 x i8> %x, <i8 3, i8 3>   ; extra op to thwart complexity-based canonicalization
393  %signbit = ashr <2 x i8> %y, <i8 7, i8 7>
394  %add = add <2 x i8> %y, %signbit
395  %abs = xor <2 x i8> %signbit, %add
396  ret <2 x i8> %abs
397}
398
399define i8 @shifty_abs_commute3(i8 %x) {
400; CHECK-LABEL: @shifty_abs_commute3(
401; CHECK-NEXT:    [[Y:%.*]] = mul i8 [[X:%.*]], 3
402; CHECK-NEXT:    [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[Y]], i1 false)
403; CHECK-NEXT:    ret i8 [[ABS]]
404;
405  %y = mul i8 %x, 3                    ; extra op to thwart complexity-based canonicalization
406  %signbit = ashr i8 %y, 7
407  %add = add i8 %y, %signbit
408  %abs = xor i8 %add, %signbit
409  ret i8 %abs
410}
411
412; Negative test - don't transform if it would increase instruction count.
413
414declare void @extra_use(i8)
415declare void @extra_use_i1(i1)
416
417define i8 @shifty_abs_too_many_uses(i8 %x) {
418; CHECK-LABEL: @shifty_abs_too_many_uses(
419; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i8 [[X:%.*]], 7
420; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], [[SIGNBIT]]
421; CHECK-NEXT:    [[ABS:%.*]] = xor i8 [[ADD]], [[SIGNBIT]]
422; CHECK-NEXT:    call void @extra_use(i8 [[SIGNBIT]])
423; CHECK-NEXT:    ret i8 [[ABS]]
424;
425  %signbit = ashr i8 %x, 7
426  %add = add i8 %x, %signbit
427  %abs = xor i8 %add, %signbit
428  call void @extra_use(i8 %signbit)
429  ret i8 %abs
430}
431
432; There's another way to make abs() using shift, xor, and subtract.
433; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036
434
435define i8 @shifty_sub(i8 %x) {
436; CHECK-LABEL: @shifty_sub(
437; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
438; CHECK-NEXT:    ret i8 [[R]]
439;
440  %sh = ashr i8 %x, 7
441  %xor = xor i8 %x, %sh
442  %r = sub i8 %xor, %sh
443  ret i8 %r
444}
445
446define i8 @shifty_sub_nsw_commute(i8 %x) {
447; CHECK-LABEL: @shifty_sub_nsw_commute(
448; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
449; CHECK-NEXT:    ret i8 [[R]]
450;
451  %sh = ashr i8 %x, 7
452  %xor = xor i8 %sh, %x
453  %r = sub nsw i8 %xor, %sh
454  ret i8 %r
455}
456
457define <4 x i32> @shifty_sub_nuw_vec_commute(<4 x i32> %x) {
458; CHECK-LABEL: @shifty_sub_nuw_vec_commute(
459; CHECK-NEXT:    [[R:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[X:%.*]], <4 x i32> zeroinitializer)
460; CHECK-NEXT:    ret <4 x i32> [[R]]
461;
462  %sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
463  %xor = xor <4 x i32> %sh, %x
464  %r = sub nuw <4 x i32> %xor, %sh
465  ret <4 x i32> %r
466}
467
468define i12 @shifty_sub_nsw_nuw(i12 %x) {
469; CHECK-LABEL: @shifty_sub_nsw_nuw(
470; CHECK-NEXT:    [[R:%.*]] = call i12 @llvm.smax.i12(i12 [[X:%.*]], i12 0)
471; CHECK-NEXT:    ret i12 [[R]]
472;
473  %sh = ashr i12 %x, 11
474  %xor = xor i12 %x, %sh
475  %r = sub nsw nuw i12 %xor, %sh
476  ret i12 %r
477}
478
479define i8 @negate_abs(i8 %x) {
480; CHECK-LABEL: @negate_abs(
481; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
482; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[S]]
483; CHECK-NEXT:    ret i8 [[R]]
484;
485  %n = sub i8 0, %x
486  %c = icmp slt i8 %x, 0
487  %s = select i1 %c, i8 %n, i8 %x
488  %r = sub i8 0, %s
489  ret i8 %r
490}
491
492define <2 x i8> @negate_nabs(<2 x i8> %x) {
493; CHECK-LABEL: @negate_nabs(
494; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false)
495; CHECK-NEXT:    ret <2 x i8> [[TMP1]]
496;
497  %n = sub <2 x i8> zeroinitializer, %x
498  %c = icmp slt <2 x i8> %x, zeroinitializer
499  %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n
500  %r = sub <2 x i8> zeroinitializer, %s
501  ret <2 x i8> %r
502}
503
504define i1 @abs_must_be_positive(i32 %x) {
505; CHECK-LABEL: @abs_must_be_positive(
506; CHECK-NEXT:    ret i1 true
507;
508  %negx = sub nsw i32 0, %x
509  %c = icmp sge i32 %x, 0
510  %sel = select i1 %c, i32 %x, i32 %negx
511  %c2 = icmp sge i32 %sel, 0
512  ret i1 %c2
513}
514
515define i8 @abs_swapped(i8 %a) {
516; CHECK-LABEL: @abs_swapped(
517; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
518; CHECK-NEXT:    call void @extra_use(i8 [[NEG]])
519; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false)
520; CHECK-NEXT:    ret i8 [[M1]]
521;
522  %neg = sub i8 0, %a
523  call void @extra_use(i8 %neg)
524  %cmp1 = icmp sgt i8 %a, 0
525  %m1 = select i1 %cmp1, i8 %a, i8 %neg
526  ret i8 %m1
527}
528
529define i8 @nabs_swapped(i8 %a) {
530; CHECK-LABEL: @nabs_swapped(
531; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
532; CHECK-NEXT:    call void @extra_use(i8 [[NEG]])
533; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false)
534; CHECK-NEXT:    [[M2:%.*]] = sub i8 0, [[TMP1]]
535; CHECK-NEXT:    ret i8 [[M2]]
536;
537  %neg = sub i8 0, %a
538  call void @extra_use(i8 %neg)
539  %cmp2 = icmp sgt i8 %a, 0
540  %m2 = select i1 %cmp2, i8 %neg, i8 %a
541  ret i8 %m2
542}
543
544define i8 @abs_different_constants(i8 %a) {
545; CHECK-LABEL: @abs_different_constants(
546; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
547; CHECK-NEXT:    call void @extra_use(i8 [[NEG]])
548; CHECK-NEXT:    [[M1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false)
549; CHECK-NEXT:    ret i8 [[M1]]
550;
551  %neg = sub i8 0, %a
552  call void @extra_use(i8 %neg)
553  %cmp1 = icmp sgt i8 %a, -1
554  %m1 = select i1 %cmp1, i8 %a, i8 %neg
555  ret i8 %m1
556}
557
558define i8 @nabs_different_constants(i8 %a) {
559; CHECK-LABEL: @nabs_different_constants(
560; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
561; CHECK-NEXT:    call void @extra_use(i8 [[NEG]])
562; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false)
563; CHECK-NEXT:    [[M2:%.*]] = sub i8 0, [[TMP1]]
564; CHECK-NEXT:    ret i8 [[M2]]
565;
566  %neg = sub i8 0, %a
567  call void @extra_use(i8 %neg)
568  %cmp2 = icmp sgt i8 %a, -1
569  %m2 = select i1 %cmp2, i8 %neg, i8 %a
570  ret i8 %m2
571}
572
573@g = external global i64
574
575; PR45539 - https://bugs.llvm.org/show_bug.cgi?id=45539
576
577define i64 @infinite_loop_constant_expression_abs(i64 %arg) {
578; CHECK-LABEL: @infinite_loop_constant_expression_abs(
579; CHECK-NEXT:    [[T:%.*]] = sub i64 ptrtoint (ptr @g to i64), [[ARG:%.*]]
580; CHECK-NEXT:    [[T3:%.*]] = call i64 @llvm.abs.i64(i64 [[T]], i1 true)
581; CHECK-NEXT:    ret i64 [[T3]]
582;
583  %t = sub i64 ptrtoint (ptr @g to i64), %arg
584  %t1 = icmp slt i64 %t, 0
585  %t2 = sub nsw i64 0, %t
586  %t3 = select i1 %t1, i64 %t2, i64 %t
587  ret i64 %t3
588}
589
590define i8 @abs_extra_use_icmp(i8 %x) {
591; CHECK-LABEL: @abs_extra_use_icmp(
592; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], 0
593; CHECK-NEXT:    call void @extra_use_i1(i1 [[C]])
594; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
595; CHECK-NEXT:    ret i8 [[S]]
596;
597  %c = icmp slt i8 %x, 0
598  call void @extra_use_i1(i1 %c)
599  %n = sub i8 0, %x
600  %s = select i1 %c, i8 %n, i8 %x
601  ret i8 %s
602}
603
604define i8 @abs_extra_use_sub(i8 %x) {
605; CHECK-LABEL: @abs_extra_use_sub(
606; CHECK-NEXT:    [[N:%.*]] = sub i8 0, [[X:%.*]]
607; CHECK-NEXT:    call void @extra_use(i8 [[N]])
608; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
609; CHECK-NEXT:    ret i8 [[S]]
610;
611  %c = icmp slt i8 %x, 0
612  %n = sub i8 0, %x
613  call void @extra_use(i8 %n)
614  %s = select i1 %c, i8 %n, i8 %x
615  ret i8 %s
616}
617
618define i8 @abs_extra_use_icmp_sub(i8 %x) {
619; CHECK-LABEL: @abs_extra_use_icmp_sub(
620; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], 0
621; CHECK-NEXT:    call void @extra_use_i1(i1 [[C]])
622; CHECK-NEXT:    [[N:%.*]] = sub i8 0, [[X]]
623; CHECK-NEXT:    call void @extra_use(i8 [[N]])
624; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i8 [[N]], i8 [[X]]
625; CHECK-NEXT:    ret i8 [[S]]
626;
627  %c = icmp slt i8 %x, 0
628  call void @extra_use_i1(i1 %c)
629  %n = sub i8 0, %x
630  call void @extra_use(i8 %n)
631  %s = select i1 %c, i8 %n, i8 %x
632  ret i8 %s
633}
634
635define i8 @nabs_extra_use_icmp(i8 %x) {
636; CHECK-LABEL: @nabs_extra_use_icmp(
637; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], 0
638; CHECK-NEXT:    call void @extra_use_i1(i1 [[C]])
639; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
640; CHECK-NEXT:    [[S:%.*]] = sub i8 0, [[TMP1]]
641; CHECK-NEXT:    ret i8 [[S]]
642;
643  %c = icmp slt i8 %x, 0
644  call void @extra_use_i1(i1 %c)
645  %n = sub i8 0, %x
646  %s = select i1 %c, i8 %x, i8 %n
647  ret i8 %s
648}
649
650define i8 @nabs_extra_use_sub(i8 %x) {
651; CHECK-LABEL: @nabs_extra_use_sub(
652; CHECK-NEXT:    [[N:%.*]] = sub i8 0, [[X:%.*]]
653; CHECK-NEXT:    call void @extra_use(i8 [[N]])
654; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)
655; CHECK-NEXT:    [[S:%.*]] = sub i8 0, [[TMP1]]
656; CHECK-NEXT:    ret i8 [[S]]
657;
658  %c = icmp slt i8 %x, 0
659  %n = sub i8 0, %x
660  call void @extra_use(i8 %n)
661  %s = select i1 %c, i8 %x, i8 %n
662  ret i8 %s
663}
664
665define i8 @nabs_extra_use_icmp_sub(i8 %x) {
666; CHECK-LABEL: @nabs_extra_use_icmp_sub(
667; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], 0
668; CHECK-NEXT:    call void @extra_use_i1(i1 [[C]])
669; CHECK-NEXT:    [[N:%.*]] = sub i8 0, [[X]]
670; CHECK-NEXT:    call void @extra_use(i8 [[N]])
671; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[N]]
672; CHECK-NEXT:    ret i8 [[S]]
673;
674  %c = icmp slt i8 %x, 0
675  call void @extra_use_i1(i1 %c)
676  %n = sub i8 0, %x
677  call void @extra_use(i8 %n)
678  %s = select i1 %c, i8 %x, i8 %n
679  ret i8 %s
680}
681
682; TODO: negate-of-abs-diff
683
684define i32 @nabs_diff_signed_slt(i32 %a, i32 %b) {
685; CHECK-LABEL: @nabs_diff_signed_slt(
686; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
687; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]]
688; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]]
689; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_AB]], i32 [[SUB_BA]]
690; CHECK-NEXT:    ret i32 [[COND]]
691;
692  %cmp = icmp slt i32 %a, %b
693  %sub_ba = sub nsw i32 %b, %a
694  %sub_ab = sub nsw i32 %a, %b
695  %cond = select i1 %cmp, i32 %sub_ab, i32 %sub_ba
696  ret i32 %cond
697}
698
699; TODO: negate-of-abs-diff
700
701define <2 x i8> @nabs_diff_signed_sle(<2 x i8> %a, <2 x i8> %b) {
702; CHECK-LABEL: @nabs_diff_signed_sle(
703; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt <2 x i8> [[A:%.*]], [[B:%.*]]
704; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw <2 x i8> [[B]], [[A]]
705; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]
706; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[SUB_BA]], <2 x i8> [[SUB_AB]]
707; CHECK-NEXT:    ret <2 x i8> [[COND]]
708;
709  %cmp = icmp sle <2 x i8> %a, %b
710  %sub_ba = sub nsw <2 x i8> %b, %a
711  %sub_ab = sub nsw <2 x i8> %a, %b
712  %cond = select <2 x i1> %cmp, <2 x i8> %sub_ab, <2 x i8> %sub_ba
713  ret <2 x i8> %cond
714}
715
716define i8 @abs_diff_signed_sgt(i8 %a, i8 %b) {
717; CHECK-LABEL: @abs_diff_signed_sgt(
718; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
719; CHECK-NEXT:    call void @extra_use(i8 [[SUB_AB]])
720; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
721; CHECK-NEXT:    ret i8 [[COND]]
722;
723  %cmp = icmp sgt i8 %a, %b
724  %sub_ba = sub nsw i8 %b, %a
725  %sub_ab = sub nsw i8 %a, %b
726  call void @extra_use(i8 %sub_ab)
727  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
728  ret i8 %cond
729}
730
731define i8 @abs_diff_signed_sge(i8 %a, i8 %b) {
732; CHECK-LABEL: @abs_diff_signed_sge(
733; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i8 [[B:%.*]], [[A:%.*]]
734; CHECK-NEXT:    call void @extra_use(i8 [[SUB_BA]])
735; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]]
736; CHECK-NEXT:    call void @extra_use(i8 [[SUB_AB]])
737; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
738; CHECK-NEXT:    ret i8 [[COND]]
739;
740  %cmp = icmp sge i8 %a, %b
741  %sub_ba = sub nsw i8 %b, %a
742  call void @extra_use(i8 %sub_ba)
743  %sub_ab = sub nsw i8 %a, %b
744  call void @extra_use(i8 %sub_ab)
745  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
746  ret i8 %cond
747}
748
749; negative test - need nsw
750
751define i32 @abs_diff_signed_slt_no_nsw(i32 %a, i32 %b) {
752; CHECK-LABEL: @abs_diff_signed_slt_no_nsw(
753; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
754; CHECK-NEXT:    [[SUB_BA:%.*]] = sub i32 [[B]], [[A]]
755; CHECK-NEXT:    [[SUB_AB:%.*]] = sub i32 [[A]], [[B]]
756; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_AB]], i32 [[SUB_BA]]
757; CHECK-NEXT:    ret i32 [[COND]]
758;
759  %cmp = icmp slt i32 %a, %b
760  %sub_ba = sub i32 %b, %a
761  %sub_ab = sub i32 %a, %b
762  %cond = select i1 %cmp, i32 %sub_ab, i32 %sub_ba
763  ret i32 %cond
764}
765
766; bonus nuw - it's fine to match the pattern, but nuw can't propagate
767
768define i8 @abs_diff_signed_sgt_nsw_nuw(i8 %a, i8 %b) {
769; CHECK-LABEL: @abs_diff_signed_sgt_nsw_nuw(
770; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
771; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
772; CHECK-NEXT:    ret i8 [[COND]]
773;
774  %cmp = icmp sgt i8 %a, %b
775  %sub_ba = sub nsw nuw i8 %b, %a
776  %sub_ab = sub nsw nuw i8 %a, %b
777  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
778  ret i8 %cond
779}
780
781; this is absolute diff, but nuw can't propagate and nsw can be set.
782
783define i8 @abs_diff_signed_sgt_nuw(i8 %a, i8 %b) {
784; CHECK-LABEL: @abs_diff_signed_sgt_nuw(
785; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
786; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
787; CHECK-NEXT:    ret i8 [[COND]]
788;
789  %cmp = icmp sgt i8 %a, %b
790  %sub_ba = sub nuw i8 %b, %a
791  %sub_ab = sub nuw i8 %a, %b
792  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
793  ret i8 %cond
794}
795
796; same as above
797
798define i8 @abs_diff_signed_sgt_nuw_extra_use1(i8 %a, i8 %b) {
799; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use1(
800; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nuw i8 [[B:%.*]], [[A:%.*]]
801; CHECK-NEXT:    call void @extra_use(i8 [[SUB_BA]])
802; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]]
803; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
804; CHECK-NEXT:    ret i8 [[COND]]
805;
806  %cmp = icmp sgt i8 %a, %b
807  %sub_ba = sub nuw i8 %b, %a
808  call void @extra_use(i8 %sub_ba)
809  %sub_ab = sub nuw i8 %a, %b
810  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
811  ret i8 %cond
812}
813
814; nuw can't propagate, and the extra use prevents applying nsw
815
816define i8 @abs_diff_signed_sgt_nuw_extra_use2(i8 %a, i8 %b) {
817; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use2(
818; CHECK-NEXT:    [[SUB_AB:%.*]] = sub i8 [[A:%.*]], [[B:%.*]]
819; CHECK-NEXT:    call void @extra_use(i8 [[SUB_AB]])
820; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
821; CHECK-NEXT:    ret i8 [[COND]]
822;
823  %cmp = icmp sgt i8 %a, %b
824  %sub_ba = sub nuw i8 %b, %a
825  %sub_ab = sub nuw i8 %a, %b
826  call void @extra_use(i8 %sub_ab)
827  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
828  ret i8 %cond
829}
830
831; same as above
832
833define i8 @abs_diff_signed_sgt_nuw_extra_use3(i8 %a, i8 %b) {
834; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use3(
835; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nuw i8 [[B:%.*]], [[A:%.*]]
836; CHECK-NEXT:    call void @extra_use(i8 [[SUB_BA]])
837; CHECK-NEXT:    [[SUB_AB:%.*]] = sub i8 [[A]], [[B]]
838; CHECK-NEXT:    call void @extra_use(i8 [[SUB_AB]])
839; CHECK-NEXT:    [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true)
840; CHECK-NEXT:    ret i8 [[COND]]
841;
842  %cmp = icmp sgt i8 %a, %b
843  %sub_ba = sub nuw i8 %b, %a
844  call void @extra_use(i8 %sub_ba)
845  %sub_ab = sub nuw i8 %a, %b
846  call void @extra_use(i8 %sub_ab)
847  %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba
848  ret i8 %cond
849}
850
851; negative test - wrong predicate
852
853define i32 @abs_diff_signed_slt_swap_wrong_pred1(i32 %a, i32 %b) {
854; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_pred1(
855; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i32 [[A:%.*]], [[B:%.*]]
856; CHECK-NEXT:    ret i32 [[SUB_AB]]
857;
858  %cmp = icmp eq i32 %a, %b
859  %sub_ba = sub nsw i32 %b, %a
860  %sub_ab = sub nsw i32 %a, %b
861  %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab
862  ret i32 %cond
863}
864
865; negative test - wrong predicate
866
867define i32 @abs_diff_signed_slt_swap_wrong_pred2(i32 %a, i32 %b) {
868; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_pred2(
869; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
870; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]]
871; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]]
872; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BA]], i32 [[SUB_AB]]
873; CHECK-NEXT:    ret i32 [[COND]]
874;
875  %cmp = icmp ult i32 %a, %b
876  %sub_ba = sub nsw i32 %b, %a
877  %sub_ab = sub nsw i32 %a, %b
878  %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab
879  ret i32 %cond
880}
881
882; negative test - need common operands
883
884define i32 @abs_diff_signed_slt_swap_wrong_op(i32 %a, i32 %b, i32 %z) {
885; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_op(
886; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
887; CHECK-NEXT:    [[SUB_BZ:%.*]] = sub nsw i32 [[B]], [[Z:%.*]]
888; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]]
889; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BZ]], i32 [[SUB_AB]]
890; CHECK-NEXT:    ret i32 [[COND]]
891;
892  %cmp = icmp eq i32 %a, %b
893  %sub_bz = sub nsw i32 %b, %z
894  %sub_ab = sub nsw i32 %a, %b
895  %cond = select i1 %cmp, i32 %sub_bz, i32 %sub_ab
896  ret i32 %cond
897}
898
899define i32 @abs_diff_signed_slt_swap(i32 %a, i32 %b) {
900; CHECK-LABEL: @abs_diff_signed_slt_swap(
901; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i32 [[A:%.*]], [[B:%.*]]
902; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB_AB]], i1 true)
903; CHECK-NEXT:    ret i32 [[COND]]
904;
905  %cmp = icmp slt i32 %a, %b
906  %sub_ba = sub nsw i32 %b, %a
907  %sub_ab = sub nsw i32 %a, %b
908  %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab
909  ret i32 %cond
910}
911
912define <2 x i8> @abs_diff_signed_sle_swap(<2 x i8> %a, <2 x i8> %b) {
913; CHECK-LABEL: @abs_diff_signed_sle_swap(
914; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw <2 x i8> [[A:%.*]], [[B:%.*]]
915; CHECK-NEXT:    [[COND:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB_AB]], i1 true)
916; CHECK-NEXT:    ret <2 x i8> [[COND]]
917;
918  %cmp = icmp sle <2 x i8> %a, %b
919  %sub_ba = sub nsw <2 x i8> %b, %a
920  %sub_ab = sub nsw <2 x i8> %a, %b
921  %cond = select <2 x i1> %cmp, <2 x i8> %sub_ba, <2 x i8> %sub_ab
922  ret <2 x i8> %cond
923}
924
925; TODO: negate-of-abs-diff
926
927define i8 @nabs_diff_signed_sgt_swap(i8 %a, i8 %b) {
928; CHECK-LABEL: @nabs_diff_signed_sgt_swap(
929; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
930; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i8 [[B]], [[A]]
931; CHECK-NEXT:    call void @extra_use(i8 [[SUB_BA]])
932; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]]
933; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[SUB_BA]], i8 [[SUB_AB]]
934; CHECK-NEXT:    ret i8 [[COND]]
935;
936  %cmp = icmp sgt i8 %a, %b
937  %sub_ba = sub nsw i8 %b, %a
938  call void @extra_use(i8 %sub_ba)
939  %sub_ab = sub nsw i8 %a, %b
940  %cond = select i1 %cmp, i8 %sub_ba, i8 %sub_ab
941  ret i8 %cond
942}
943
944; TODO: negate-of-abs-diff, but too many uses?
945
946define i8 @nabs_diff_signed_sge_swap(i8 %a, i8 %b) {
947; CHECK-LABEL: @nabs_diff_signed_sge_swap(
948; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
949; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i8 [[B]], [[A]]
950; CHECK-NEXT:    call void @extra_use(i8 [[SUB_BA]])
951; CHECK-NEXT:    [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]]
952; CHECK-NEXT:    call void @extra_use(i8 [[SUB_AB]])
953; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[SUB_AB]], i8 [[SUB_BA]]
954; CHECK-NEXT:    ret i8 [[COND]]
955;
956  %cmp = icmp sge i8 %a, %b
957  %sub_ba = sub nsw i8 %b, %a
958  call void @extra_use(i8 %sub_ba)
959  %sub_ab = sub nsw i8 %a, %b
960  call void @extra_use(i8 %sub_ab)
961  %cond = select i1 %cmp, i8 %sub_ba, i8 %sub_ab
962  ret i8 %cond
963}
964
965; negative test - need nsw
966
967define i32 @abs_diff_signed_slt_no_nsw_swap(i32 %a, i32 %b) {
968; CHECK-LABEL: @abs_diff_signed_slt_no_nsw_swap(
969; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
970; CHECK-NEXT:    [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]]
971; CHECK-NEXT:    [[SUB_AB:%.*]] = sub i32 [[A]], [[B]]
972; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BA]], i32 [[SUB_AB]]
973; CHECK-NEXT:    ret i32 [[COND]]
974;
975  %cmp = icmp slt i32 %a, %b
976  %sub_ba = sub nsw i32 %b, %a
977  %sub_ab = sub i32 %a, %b
978  %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab
979  ret i32 %cond
980}
981