[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / abs-1.ll
blob8bbc833d5d4457be21e851fcf41bbb976a74b755
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -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:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0
16 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i32 0, [[X]]
17 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[NEG]], i32 [[X]]
18 ; CHECK-NEXT:    ret i32 [[TMP2]]
20   %ret = call i32 @abs(i32 %x)
21   ret i32 %ret
24 define i64 @test_labs(i64 %x) {
25 ; CHECK-LABEL: @test_labs(
26 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i64 [[X:%.*]], 0
27 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i64 0, [[X]]
28 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i64 [[NEG]], i64 [[X]]
29 ; CHECK-NEXT:    ret i64 [[TMP2]]
31   %ret = call i64 @labs(i64 %x)
32   ret i64 %ret
35 define i64 @test_llabs(i64 %x) {
36 ; CHECK-LABEL: @test_llabs(
37 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i64 [[X:%.*]], 0
38 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i64 0, [[X]]
39 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i64 [[NEG]], i64 [[X]]
40 ; CHECK-NEXT:    ret i64 [[TMP2]]
42   %ret = call i64 @llabs(i64 %x)
43   ret i64 %ret
46 ; We have a canonical form of abs to make CSE easier.
48 define i8 @abs_canonical_1(i8 %x) {
49 ; CHECK-LABEL: @abs_canonical_1(
50 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
51 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[X]]
52 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]]
53 ; CHECK-NEXT:    ret i8 [[ABS]]
55   %cmp = icmp sgt i8 %x, 0
56   %neg = sub i8 0, %x
57   %abs = select i1 %cmp, i8 %x, i8 %neg
58   ret i8 %abs
61 ; Vectors should work too.
63 define <2 x i8> @abs_canonical_2(<2 x i8> %x) {
64 ; CHECK-LABEL: @abs_canonical_2(
65 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
66 ; CHECK-NEXT:    [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
67 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[NEG]], <2 x i8> [[X]]
68 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
70   %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
71   %neg = sub <2 x i8> zeroinitializer, %x
72   %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg
73   ret <2 x i8> %abs
76 ; Even if a constant has undef elements.
78 define <2 x i8> @abs_canonical_2_vec_undef_elts(<2 x i8> %x) {
79 ; CHECK-LABEL: @abs_canonical_2_vec_undef_elts(
80 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
81 ; CHECK-NEXT:    [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
82 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[NEG]], <2 x i8> [[X]]
83 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
85   %cmp = icmp sgt <2 x i8> %x, <i8 undef, i8 -1>
86   %neg = sub <2 x i8> zeroinitializer, %x
87   %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg
88   ret <2 x i8> %abs
91 ; NSW should not change.
93 define i8 @abs_canonical_3(i8 %x) {
94 ; CHECK-LABEL: @abs_canonical_3(
95 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
96 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i8 0, [[X]]
97 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]]
98 ; CHECK-NEXT:    ret i8 [[ABS]]
100   %cmp = icmp slt i8 %x, 0
101   %neg = sub nsw i8 0, %x
102   %abs = select i1 %cmp, i8 %neg, i8 %x
103   ret i8 %abs
106 define i8 @abs_canonical_4(i8 %x) {
107 ; CHECK-LABEL: @abs_canonical_4(
108 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
109 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[X]]
110 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]]
111 ; CHECK-NEXT:    ret i8 [[ABS]]
113   %cmp = icmp slt i8 %x, 1
114   %neg = sub i8 0, %x
115   %abs = select i1 %cmp, i8 %neg, i8 %x
116   ret i8 %abs
119 define i32 @abs_canonical_5(i8 %x) {
120 ; CHECK-LABEL: @abs_canonical_5(
121 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
122 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[X]] to i32
123 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i32 0, [[CONV]]
124 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[CONV]]
125 ; CHECK-NEXT:    ret i32 [[ABS]]
127   %cmp = icmp sgt i8 %x, 0
128   %conv = sext i8 %x to i32
129   %neg = sub i32 0, %conv
130   %abs = select i1 %cmp, i32 %conv, i32 %neg
131   ret i32 %abs
134 define i32 @abs_canonical_6(i32 %a, i32 %b) {
135 ; CHECK-LABEL: @abs_canonical_6(
136 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
137 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
138 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
139 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
140 ; CHECK-NEXT:    ret i32 [[ABS]]
142   %tmp1 = sub i32 %a, %b
143   %cmp = icmp sgt i32 %tmp1, -1
144   %tmp2 = sub i32 %b, %a
145   %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
146   ret i32 %abs
149 define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
150 ; CHECK-LABEL: @abs_canonical_7(
151 ; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
152 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer
153 ; CHECK-NEXT:    [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
154 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]]
155 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
158   %tmp1 = sub <2 x i8> %a, %b
159   %cmp = icmp sgt <2 x i8> %tmp1, <i8 -1, i8 -1>
160   %tmp2 = sub <2 x i8> %b, %a
161   %abs = select <2 x i1> %cmp, <2 x i8> %tmp1, <2 x i8> %tmp2
162   ret <2 x i8> %abs
165 define i32 @abs_canonical_8(i32 %a) {
166 ; CHECK-LABEL: @abs_canonical_8(
167 ; CHECK-NEXT:    [[TMP:%.*]] = sub i32 0, [[A:%.*]]
168 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
169 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]]
170 ; CHECK-NEXT:    ret i32 [[ABS]]
172   %tmp = sub i32 0, %a
173   %cmp = icmp slt i32 %tmp, 0
174   %abs = select i1 %cmp, i32 %a, i32 %tmp
175   ret i32 %abs
178 define i32 @abs_canonical_9(i32 %a, i32 %b) {
179 ; CHECK-LABEL: @abs_canonical_9(
180 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
181 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
182 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[B]], [[A]]
183 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]]
184 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[ABS]], [[TMP2]]
185 ; CHECK-NEXT:    ret i32 [[ADD]]
187   %tmp1 = sub i32 %a, %b
188   %cmp = icmp sgt i32 %tmp1, -1
189   %tmp2 = sub i32 %b, %a
190   %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
191   %add = add i32 %abs, %tmp2 ; increase use count for %tmp2.
192   ret i32 %add
195 define i32 @abs_canonical_10(i32 %a, i32 %b) {
196 ; CHECK-LABEL: @abs_canonical_10(
197 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
198 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
199 ; CHECK-NEXT:    [[NEGTMP:%.*]] = sub i32 0, [[TMP1]]
200 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGTMP]], i32 [[TMP1]]
201 ; CHECK-NEXT:    ret i32 [[ABS]]
203   %tmp2 = sub i32 %b, %a
204   %tmp1 = sub i32 %a, %b
205   %cmp = icmp sgt i32 %tmp1, -1
206   %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
207   ret i32 %abs
210 ; We have a canonical form of nabs to make CSE easier.
212 define i8 @nabs_canonical_1(i8 %x) {
213 ; CHECK-LABEL: @nabs_canonical_1(
214 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
215 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[X]]
216 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
217 ; CHECK-NEXT:    ret i8 [[ABS]]
219   %cmp = icmp sgt i8 %x, 0
220   %neg = sub i8 0, %x
221   %abs = select i1 %cmp, i8 %neg, i8 %x
222   ret i8 %abs
225 ; Vectors should work too.
227 define <2 x i8> @nabs_canonical_2(<2 x i8> %x) {
228 ; CHECK-LABEL: @nabs_canonical_2(
229 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
230 ; CHECK-NEXT:    [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
231 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]]
232 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
234   %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
235   %neg = sub <2 x i8> zeroinitializer, %x
236   %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
237   ret <2 x i8> %abs
240 ; Even if a constant has undef elements.
242 define <2 x i8> @nabs_canonical_2_vec_undef_elts(<2 x i8> %x) {
243 ; CHECK-LABEL: @nabs_canonical_2_vec_undef_elts(
244 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
245 ; CHECK-NEXT:    [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
246 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]]
247 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
249   %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 undef>
250   %neg = sub <2 x i8> zeroinitializer, %x
251   %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
252   ret <2 x i8> %abs
255 ; NSW should not change.
257 define i8 @nabs_canonical_3(i8 %x) {
258 ; CHECK-LABEL: @nabs_canonical_3(
259 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
260 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i8 0, [[X]]
261 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
262 ; CHECK-NEXT:    ret i8 [[ABS]]
264   %cmp = icmp slt i8 %x, 0
265   %neg = sub nsw i8 0, %x
266   %abs = select i1 %cmp, i8 %x, i8 %neg
267   ret i8 %abs
270 define i8 @nabs_canonical_4(i8 %x) {
271 ; CHECK-LABEL: @nabs_canonical_4(
272 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
273 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[X]]
274 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
275 ; CHECK-NEXT:    ret i8 [[ABS]]
277   %cmp = icmp slt i8 %x, 1
278   %neg = sub i8 0, %x
279   %abs = select i1 %cmp, i8 %x, i8 %neg
280   ret i8 %abs
283 define i32 @nabs_canonical_5(i8 %x) {
284 ; CHECK-LABEL: @nabs_canonical_5(
285 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
286 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[X]] to i32
287 ; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i32 0, [[CONV]]
288 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[CONV]], i32 [[NEG]]
289 ; CHECK-NEXT:    ret i32 [[ABS]]
291   %cmp = icmp sgt i8 %x, 0
292   %conv = sext i8 %x to i32
293   %neg = sub i32 0, %conv
294   %abs = select i1 %cmp, i32 %neg, i32 %conv
295   ret i32 %abs
298 define i32 @nabs_canonical_6(i32 %a, i32 %b) {
299 ; CHECK-LABEL: @nabs_canonical_6(
300 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
301 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
302 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
303 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]]
304 ; CHECK-NEXT:    ret i32 [[ABS]]
306   %tmp1 = sub i32 %a, %b
307   %cmp = icmp sgt i32 %tmp1, -1
308   %tmp2 = sub i32 %b, %a
309   %abs = select i1 %cmp, i32 %tmp2, i32 %tmp1
310   ret i32 %abs
313 define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
314 ; CHECK-LABEL: @nabs_canonical_7(
315 ; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
316 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer
317 ; CHECK-NEXT:    [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
318 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]]
319 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
321   %tmp1 = sub <2 x i8> %a, %b
322   %cmp = icmp sgt <2 x i8> %tmp1, <i8 -1, i8 -1>
323   %tmp2 = sub <2 x i8> %b, %a
324   %abs = select <2 x i1> %cmp, <2 x i8> %tmp2, <2 x i8> %tmp1
325   ret <2 x i8> %abs
328 define i32 @nabs_canonical_8(i32 %a) {
329 ; CHECK-LABEL: @nabs_canonical_8(
330 ; CHECK-NEXT:    [[TMP:%.*]] = sub i32 0, [[A:%.*]]
331 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
332 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]]
333 ; CHECK-NEXT:    ret i32 [[ABS]]
335   %tmp = sub i32 0, %a
336   %cmp = icmp slt i32 %tmp, 0
337   %abs = select i1 %cmp, i32 %tmp, i32 %a
338   ret i32 %abs
341 define i32 @nabs_canonical_9(i32 %a, i32 %b) {
342 ; CHECK-LABEL: @nabs_canonical_9(
343 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
344 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
345 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[B]], [[A]]
346 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
347 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP2]], [[ABS]]
348 ; CHECK-NEXT:    ret i32 [[ADD]]
350   %tmp1 = sub i32 %a, %b
351   %cmp = icmp sgt i32 %tmp1, -1
352   %tmp2 = sub i32 %b, %a
353   %abs = select i1 %cmp, i32 %tmp2, i32 %tmp1
354   %add = add i32 %tmp2, %abs ; increase use count for %tmp2
355   ret i32 %add
358 define i32 @nabs_canonical_10(i32 %a, i32 %b) {
359 ; CHECK-LABEL: @nabs_canonical_10(
360 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
361 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
362 ; CHECK-NEXT:    [[NEGTMP:%.*]] = sub i32 0, [[TMP1]]
363 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[NEGTMP]]
364 ; CHECK-NEXT:    ret i32 [[ABS]]
366   %tmp2 = sub i32 %b, %a
367   %tmp1 = sub i32 %a, %b
368   %cmp = icmp slt i32 %tmp1, 1
369   %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
370   ret i32 %abs
373 ; The following 5 tests use a shift+add+xor to implement abs():
374 ; B = ashr i8 A, 7  -- smear the sign bit.
375 ; xor (add A, B), B -- add -1 and flip bits if negative
377 define i8 @shifty_abs_commute0(i8 %x) {
378 ; CHECK-LABEL: @shifty_abs_commute0(
379 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
380 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i8 0, [[X]]
381 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
382 ; CHECK-NEXT:    ret i8 [[ABS]]
384   %signbit = ashr i8 %x, 7
385   %add = add i8 %signbit, %x
386   %abs = xor i8 %add, %signbit
387   ret i8 %abs
390 define i8 @shifty_abs_commute0_nsw(i8 %x) {
391 ; CHECK-LABEL: @shifty_abs_commute0_nsw(
392 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
393 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i8 0, [[X]]
394 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
395 ; CHECK-NEXT:    ret i8 [[ABS]]
397   %signbit = ashr i8 %x, 7
398   %add = add nsw i8 %signbit, %x
399   %abs = xor i8 %add, %signbit
400   ret i8 %abs
403 ; The nuw flag creates a contradiction. If the shift produces all 1s, the only
404 ; way for the add to not wrap is for %x to be 0, but then the shift couldn't
405 ; have produced all 1s. We partially optimize this.
406 define i8 @shifty_abs_commute0_nuw(i8 %x) {
407 ; CHECK-LABEL: @shifty_abs_commute0_nuw(
408 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 0
409 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 0
410 ; CHECK-NEXT:    ret i8 [[ABS]]
412   %signbit = ashr i8 %x, 7
413   %add = add nuw i8 %signbit, %x
414   %abs = xor i8 %add, %signbit
415   ret i8 %abs
418 define <2 x i8> @shifty_abs_commute1(<2 x i8> %x) {
419 ; CHECK-LABEL: @shifty_abs_commute1(
420 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
421 ; CHECK-NEXT:    [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
422 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[X]]
423 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
425   %signbit = ashr <2 x i8> %x, <i8 7, i8 7>
426   %add = add <2 x i8> %signbit, %x
427   %abs = xor <2 x i8> %signbit, %add
428   ret <2 x i8> %abs
431 define <2 x i8> @shifty_abs_commute2(<2 x i8> %x) {
432 ; CHECK-LABEL: @shifty_abs_commute2(
433 ; CHECK-NEXT:    [[Y:%.*]] = mul <2 x i8> [[X:%.*]], <i8 3, i8 3>
434 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <2 x i8> [[Y]], zeroinitializer
435 ; CHECK-NEXT:    [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[Y]]
436 ; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[Y]]
437 ; CHECK-NEXT:    ret <2 x i8> [[ABS]]
439   %y = mul <2 x i8> %x, <i8 3, i8 3>   ; extra op to thwart complexity-based canonicalization
440   %signbit = ashr <2 x i8> %y, <i8 7, i8 7>
441   %add = add <2 x i8> %y, %signbit
442   %abs = xor <2 x i8> %signbit, %add
443   ret <2 x i8> %abs
446 define i8 @shifty_abs_commute3(i8 %x) {
447 ; CHECK-LABEL: @shifty_abs_commute3(
448 ; CHECK-NEXT:    [[Y:%.*]] = mul i8 [[X:%.*]], 3
449 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[Y]], 0
450 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i8 0, [[Y]]
451 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[Y]]
452 ; CHECK-NEXT:    ret i8 [[ABS]]
454   %y = mul i8 %x, 3                    ; extra op to thwart complexity-based canonicalization
455   %signbit = ashr i8 %y, 7
456   %add = add i8 %y, %signbit
457   %abs = xor i8 %add, %signbit
458   ret i8 %abs
461 ; Negative test - don't transform if it would increase instruction count.
463 declare void @extra_use(i8)
465 define i8 @shifty_abs_too_many_uses(i8 %x) {
466 ; CHECK-LABEL: @shifty_abs_too_many_uses(
467 ; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i8 [[X:%.*]], 7
468 ; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[SIGNBIT]], [[X]]
469 ; CHECK-NEXT:    [[ABS:%.*]] = xor i8 [[ADD]], [[SIGNBIT]]
470 ; CHECK-NEXT:    call void @extra_use(i8 [[SIGNBIT]])
471 ; CHECK-NEXT:    ret i8 [[ABS]]
473   %signbit = ashr i8 %x, 7
474   %add = add i8 %x, %signbit
475   %abs = xor i8 %add, %signbit
476   call void @extra_use(i8 %signbit)
477   ret i8 %abs
480 ; There's another way to make abs() using shift, xor, and subtract.
481 ; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036
483 define i8 @shifty_sub(i8 %x) {
484 ; CHECK-LABEL: @shifty_sub(
485 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
486 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i8 0, [[X]]
487 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
488 ; CHECK-NEXT:    ret i8 [[R]]
490   %sh = ashr i8 %x, 7
491   %xor = xor i8 %x, %sh
492   %r = sub i8 %xor, %sh
493   ret i8 %r
496 define i8 @shifty_sub_nsw_commute(i8 %x) {
497 ; CHECK-LABEL: @shifty_sub_nsw_commute(
498 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
499 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i8 0, [[X]]
500 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
501 ; CHECK-NEXT:    ret i8 [[R]]
503   %sh = ashr i8 %x, 7
504   %xor = xor i8 %sh, %x
505   %r = sub nsw i8 %xor, %sh
506   ret i8 %r
509 define <4 x i32> @shifty_sub_nuw_vec_commute(<4 x i32> %x) {
510 ; CHECK-LABEL: @shifty_sub_nuw_vec_commute(
511 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i32> [[X:%.*]], zeroinitializer
512 ; CHECK-NEXT:    [[R:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[X]], <4 x i32> zeroinitializer
513 ; CHECK-NEXT:    ret <4 x i32> [[R]]
515   %sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
516   %xor = xor <4 x i32> %sh, %x
517   %r = sub nuw <4 x i32> %xor, %sh
518   ret <4 x i32> %r
521 define i12 @shifty_sub_nsw_nuw(i12 %x) {
522 ; CHECK-LABEL: @shifty_sub_nsw_nuw(
523 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i12 [[X:%.*]], 0
524 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i12 [[X]], i12 0
525 ; CHECK-NEXT:    ret i12 [[R]]
527   %sh = ashr i12 %x, 11
528   %xor = xor i12 %x, %sh
529   %r = sub nsw nuw i12 %xor, %sh
530   ret i12 %r
533 define i8 @negate_abs(i8 %x) {
534 ; CHECK-LABEL: @negate_abs(
535 ; CHECK-NEXT:    [[N:%.*]] = sub i8 0, [[X:%.*]]
536 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X]], 0
537 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[N]]
538 ; CHECK-NEXT:    ret i8 [[S]]
540   %n = sub i8 0, %x
541   %c = icmp slt i8 %x, 0
542   %s = select i1 %c, i8 %n, i8 %x
543   %r = sub i8 0, %s
544   ret i8 %r
547 define <2 x i8> @negate_nabs(<2 x i8> %x) {
548 ; CHECK-LABEL: @negate_nabs(
549 ; CHECK-NEXT:    [[N:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]]
550 ; CHECK-NEXT:    [[C:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
551 ; CHECK-NEXT:    [[S:%.*]] = select <2 x i1> [[C]], <2 x i8> [[N]], <2 x i8> [[X]]
552 ; CHECK-NEXT:    ret <2 x i8> [[S]]
554   %n = sub <2 x i8> zeroinitializer, %x
555   %c = icmp slt <2 x i8> %x, zeroinitializer
556   %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n
557   %r = sub <2 x i8> zeroinitializer, %s
558   ret <2 x i8> %r
561 define i1 @abs_must_be_positive(i32 %x) {
562 ; CHECK-LABEL: @abs_must_be_positive(
563 ; CHECK-NEXT:    ret i1 true
565   %negx = sub nsw i32 0, %x
566   %c = icmp sge i32 %x, 0
567   %sel = select i1 %c, i32 %x, i32 %negx
568   %c2 = icmp sge i32 %sel, 0
569   ret i1 %c2