1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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:    [[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]]
19;
20  %ret = call i32 @abs(i32 %x)
21  ret i32 %ret
22}
23
24define 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]]
30;
31  %ret = call i64 @labs(i64 %x)
32  ret i64 %ret
33}
34
35define 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]]
41;
42  %ret = call i64 @llabs(i64 %x)
43  ret i64 %ret
44}
45
46; We have a canonical form of abs to make CSE easier.
47
48define 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]]
54;
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
59}
60
61; Vectors should work too.
62
63define <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]]
69;
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
74}
75
76; Even if a constant has undef elements.
77
78define <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]]
84;
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
89}
90
91; NSW should not change.
92
93define 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]]
99;
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
104}
105
106define 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]]
112;
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
117}
118
119define 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]]
126;
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
132}
133
134define 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]]
141;
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
147}
148
149define <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]]
156;
157
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
163}
164
165define 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]]
171;
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
176}
177
178define 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]]
186;
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
193}
194
195define 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]]
202;
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
208}
209
210; We have a canonical form of nabs to make CSE easier.
211
212define 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]]
218;
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
223}
224
225; Vectors should work too.
226
227define <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]]
233;
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
238}
239
240; Even if a constant has undef elements.
241
242define <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]]
248;
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
253}
254
255; NSW should not change.
256
257define 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]]
263;
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
268}
269
270define 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]]
276;
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
281}
282
283define 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]]
290;
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
296}
297
298define 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]]
305;
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
311}
312
313define <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]]
320;
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
326}
327
328define 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]]
334;
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
339}
340
341define 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]]
349;
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
356}
357
358define 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]]
365;
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
371}
372
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
376
377define 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]]
383;
384  %signbit = ashr i8 %x, 7
385  %add = add i8 %signbit, %x
386  %abs = xor i8 %add, %signbit
387  ret i8 %abs
388}
389
390define 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]]
396;
397  %signbit = ashr i8 %x, 7
398  %add = add nsw i8 %signbit, %x
399  %abs = xor i8 %add, %signbit
400  ret i8 %abs
401}
402
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.
406define 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]]
411;
412  %signbit = ashr i8 %x, 7
413  %add = add nuw i8 %signbit, %x
414  %abs = xor i8 %add, %signbit
415  ret i8 %abs
416}
417
418define <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]]
424;
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
429}
430
431define <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]]
438;
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
444}
445
446define 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]]
453;
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
459}
460
461; Negative test - don't transform if it would increase instruction count.
462
463declare void @extra_use(i8)
464
465define 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]]
472;
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
478}
479
480; There's another way to make abs() using shift, xor, and subtract.
481; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036
482
483define 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]]
489;
490  %sh = ashr i8 %x, 7
491  %xor = xor i8 %x, %sh
492  %r = sub i8 %xor, %sh
493  ret i8 %r
494}
495
496define 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]]
502;
503  %sh = ashr i8 %x, 7
504  %xor = xor i8 %sh, %x
505  %r = sub nsw i8 %xor, %sh
506  ret i8 %r
507}
508
509define <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]]
514;
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
519}
520
521define 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]]
526;
527  %sh = ashr i12 %x, 11
528  %xor = xor i12 %x, %sh
529  %r = sub nsw nuw i12 %xor, %sh
530  ret i12 %r
531}
532
533define 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]]
539;
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
545}
546
547define <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]]
553;
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
559}
560
561define i1 @abs_must_be_positive(i32 %x) {
562; CHECK-LABEL: @abs_must_be_positive(
563; CHECK-NEXT:    ret i1 true
564;
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
570}
571
572