[Transforms] Silence a warning in SROA.cpp (NFC)
[llvm-project.git] / llvm / test / Transforms / InstCombine / abs-1.ll
blob7037647d116ba2a3b6c1800bbcfd8bf12f1aaaf6
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 target 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"
6 declare i32 @abs(i32)
7 declare i64 @labs(i64)
8 declare i64 @llabs(i64)
10 ; Test that the abs library call simplifier works correctly.
11 ; abs(x) -> x <s 0 ? -x : x.
13 define 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]]
18   %ret = call i32 @abs(i32 %x)
19   ret i32 %ret
22 define 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]]
27   %ret = call i64 @labs(i64 %x)
28   ret i64 %ret
31 define 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]]
36   %ret = call i64 @llabs(i64 %x)
37   ret i64 %ret
40 ; We have a canonical form of abs to make CSE easier.
42 define 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]]
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
53 ; Vectors should work too.
55 define <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]]
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
66 ; Even if a constant has poison elements.
68 define <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]]
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
79 ; NSW should not change.
81 define 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]]
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
92 define 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]]
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
103 define 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]]
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
116 define 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]]
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
129 define <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]]
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
143 define 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]]
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
154 define 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]]
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
170 define 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]]
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
183 ; We have a canonical form of nabs to make CSE easier.
185 define 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]]
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
197 ; Vectors should work too.
199 define <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]]
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
211 ; Even if a constant has poison elements.
213 define <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]]
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
225 ; NSW should not change.
227 define 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]]
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
239 define 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]]
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
251 define 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]]
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
265 define 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]]
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
279 define <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]]
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
293 define 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]]
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
305 define 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]]
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
321 define 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]]
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
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
339 define 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]]
344   %signbit = ashr i8 %x, 7
345   %add = add i8 %signbit, %x
346   %abs = xor i8 %add, %signbit
347   ret i8 %abs
350 define 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]]
355   %signbit = ashr i8 %x, 7
356   %add = add nsw i8 %signbit, %x
357   %abs = xor i8 %add, %signbit
358   ret i8 %abs
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.
364 define 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]]
369   %signbit = ashr i8 %x, 7
370   %add = add nuw i8 %signbit, %x
371   %abs = xor i8 %add, %signbit
372   ret i8 %abs
375 define <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]]
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
386 define <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]]
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
399 define 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]]
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
412 ; Negative test - don't transform if it would increase instruction count.
414 declare void @extra_use(i8)
415 declare void @extra_use_i1(i1)
417 define 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]]
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
432 ; There's another way to make abs() using shift, xor, and subtract.
433 ; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036
435 define 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]]
440   %sh = ashr i8 %x, 7
441   %xor = xor i8 %x, %sh
442   %r = sub i8 %xor, %sh
443   ret i8 %r
446 define 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]]
451   %sh = ashr i8 %x, 7
452   %xor = xor i8 %sh, %x
453   %r = sub nsw i8 %xor, %sh
454   ret i8 %r
457 define <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]]
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
468 define 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]]
473   %sh = ashr i12 %x, 11
474   %xor = xor i12 %x, %sh
475   %r = sub nsw nuw i12 %xor, %sh
476   ret i12 %r
479 define 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]]
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
492 define <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]]
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
504 define i1 @abs_must_be_positive(i32 %x) {
505 ; CHECK-LABEL: @abs_must_be_positive(
506 ; CHECK-NEXT:    ret i1 true
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
515 define 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]]
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
529 define 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]]
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
544 define 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]]
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
558 define 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]]
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
573 @g = external global i64
575 ; PR45539 - https://bugs.llvm.org/show_bug.cgi?id=45539
577 define 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]]
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
590 define 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]]
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
604 define 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]]
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
618 define 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]]
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
635 define 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]]
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
650 define 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]]
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
665 define 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]]
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
682 ; TODO: negate-of-abs-diff
684 define 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]]
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
699 ; TODO: negate-of-abs-diff
701 define <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]]
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
716 define 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]]
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
731 define 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]]
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
749 ; negative test - need nsw
751 define 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]]
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
766 ; bonus nuw - it's fine to match the pattern, but nuw can't propagate
768 define 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]]
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
781 ; this is absolute diff, but nuw can't propagate and nsw can be set.
783 define 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]]
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
796 ; same as above
798 define 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]]
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
814 ; nuw can't propagate, and the extra use prevents applying nsw
816 define 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]]
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
831 ; same as above
833 define 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]]
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
851 ; negative test - wrong predicate
853 define 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]]
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
865 ; negative test - wrong predicate
867 define 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]]
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
882 ; negative test - need common operands
884 define 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]]
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
899 define 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]]
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
912 define <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]]
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
925 ; TODO: negate-of-abs-diff
927 define 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]]
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
944 ; TODO: negate-of-abs-diff, but too many uses?
946 define 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]]
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
965 ; negative test - need nsw
967 define 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]]
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