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"
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)
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)
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)
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
57 %abs = select i1 %cmp, i8 %x, i8 %neg
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
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
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
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
115 %abs = select i1 %cmp, i8 %neg, i8 %x
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
134 ; We have a canonical form of nabs to make CSE easier.
136 define i8 @nabs_canonical_1(i8 %x) {
137 ; CHECK-LABEL: @nabs_canonical_1(
138 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
139 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]]
140 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
141 ; CHECK-NEXT: ret i8 [[ABS]]
143 %cmp = icmp sgt i8 %x, 0
145 %abs = select i1 %cmp, i8 %neg, i8 %x
149 ; Vectors should work too.
151 define <2 x i8> @nabs_canonical_2(<2 x i8> %x) {
152 ; CHECK-LABEL: @nabs_canonical_2(
153 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
154 ; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
155 ; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]]
156 ; CHECK-NEXT: ret <2 x i8> [[ABS]]
158 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
159 %neg = sub <2 x i8> zeroinitializer, %x
160 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
164 ; Even if a constant has undef elements.
166 define <2 x i8> @nabs_canonical_2_vec_undef_elts(<2 x i8> %x) {
167 ; CHECK-LABEL: @nabs_canonical_2_vec_undef_elts(
168 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
169 ; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
170 ; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]]
171 ; CHECK-NEXT: ret <2 x i8> [[ABS]]
173 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 undef>
174 %neg = sub <2 x i8> zeroinitializer, %x
175 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x
179 ; NSW should not change.
181 define i8 @nabs_canonical_3(i8 %x) {
182 ; CHECK-LABEL: @nabs_canonical_3(
183 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
184 ; CHECK-NEXT: [[NEG:%.*]] = sub nsw i8 0, [[X]]
185 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
186 ; CHECK-NEXT: ret i8 [[ABS]]
188 %cmp = icmp slt i8 %x, 0
189 %neg = sub nsw i8 0, %x
190 %abs = select i1 %cmp, i8 %x, i8 %neg
194 define i8 @nabs_canonical_4(i8 %x) {
195 ; CHECK-LABEL: @nabs_canonical_4(
196 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
197 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]]
198 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]]
199 ; CHECK-NEXT: ret i8 [[ABS]]
201 %cmp = icmp slt i8 %x, 1
203 %abs = select i1 %cmp, i8 %x, i8 %neg
207 define i32 @nabs_canonical_5(i8 %x) {
208 ; CHECK-LABEL: @nabs_canonical_5(
209 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
210 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X]] to i32
211 ; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[CONV]]
212 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[CONV]], i32 [[NEG]]
213 ; CHECK-NEXT: ret i32 [[ABS]]
215 %cmp = icmp sgt i8 %x, 0
216 %conv = sext i8 %x to i32
217 %neg = sub i32 0, %conv
218 %abs = select i1 %cmp, i32 %neg, i32 %conv
222 ; The following 5 tests use a shift+add+xor to implement abs():
223 ; B = ashr i8 A, 7 -- smear the sign bit.
224 ; xor (add A, B), B -- add -1 and flip bits if negative
226 define i8 @shifty_abs_commute0(i8 %x) {
227 ; CHECK-LABEL: @shifty_abs_commute0(
228 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
229 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[X]]
230 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
231 ; CHECK-NEXT: ret i8 [[ABS]]
233 %signbit = ashr i8 %x, 7
234 %add = add i8 %signbit, %x
235 %abs = xor i8 %add, %signbit
239 define i8 @shifty_abs_commute0_nsw(i8 %x) {
240 ; CHECK-LABEL: @shifty_abs_commute0_nsw(
241 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
242 ; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[X]]
243 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
244 ; CHECK-NEXT: ret i8 [[ABS]]
246 %signbit = ashr i8 %x, 7
247 %add = add nsw i8 %signbit, %x
248 %abs = xor i8 %add, %signbit
252 ; The nuw flag creates a contradiction. If the shift produces all 1s, the only
253 ; way for the add to not wrap is for %x to be 0, but then the shift couldn't
254 ; have produced all 1s. We partially optimize this.
255 define i8 @shifty_abs_commute0_nuw(i8 %x) {
256 ; CHECK-LABEL: @shifty_abs_commute0_nuw(
257 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 0
258 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 0
259 ; CHECK-NEXT: ret i8 [[ABS]]
261 %signbit = ashr i8 %x, 7
262 %add = add nuw i8 %signbit, %x
263 %abs = xor i8 %add, %signbit
267 define <2 x i8> @shifty_abs_commute1(<2 x i8> %x) {
268 ; CHECK-LABEL: @shifty_abs_commute1(
269 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
270 ; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[X]]
271 ; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[X]]
272 ; CHECK-NEXT: ret <2 x i8> [[ABS]]
274 %signbit = ashr <2 x i8> %x, <i8 7, i8 7>
275 %add = add <2 x i8> %signbit, %x
276 %abs = xor <2 x i8> %signbit, %add
280 define <2 x i8> @shifty_abs_commute2(<2 x i8> %x) {
281 ; CHECK-LABEL: @shifty_abs_commute2(
282 ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[X:%.*]], <i8 3, i8 3>
283 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[Y]], zeroinitializer
284 ; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[Y]]
285 ; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[Y]]
286 ; CHECK-NEXT: ret <2 x i8> [[ABS]]
288 %y = mul <2 x i8> %x, <i8 3, i8 3> ; extra op to thwart complexity-based canonicalization
289 %signbit = ashr <2 x i8> %y, <i8 7, i8 7>
290 %add = add <2 x i8> %y, %signbit
291 %abs = xor <2 x i8> %signbit, %add
295 define i8 @shifty_abs_commute3(i8 %x) {
296 ; CHECK-LABEL: @shifty_abs_commute3(
297 ; CHECK-NEXT: [[Y:%.*]] = mul i8 [[X:%.*]], 3
298 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y]], 0
299 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[Y]]
300 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[Y]]
301 ; CHECK-NEXT: ret i8 [[ABS]]
303 %y = mul i8 %x, 3 ; extra op to thwart complexity-based canonicalization
304 %signbit = ashr i8 %y, 7
305 %add = add i8 %y, %signbit
306 %abs = xor i8 %add, %signbit
310 ; Negative test - don't transform if it would increase instruction count.
312 declare void @extra_use(i8)
314 define i8 @shifty_abs_too_many_uses(i8 %x) {
315 ; CHECK-LABEL: @shifty_abs_too_many_uses(
316 ; CHECK-NEXT: [[SIGNBIT:%.*]] = ashr i8 [[X:%.*]], 7
317 ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SIGNBIT]], [[X]]
318 ; CHECK-NEXT: [[ABS:%.*]] = xor i8 [[ADD]], [[SIGNBIT]]
319 ; CHECK-NEXT: call void @extra_use(i8 [[SIGNBIT]])
320 ; CHECK-NEXT: ret i8 [[ABS]]
322 %signbit = ashr i8 %x, 7
323 %add = add i8 %x, %signbit
324 %abs = xor i8 %add, %signbit
325 call void @extra_use(i8 %signbit)
329 ; There's another way to make abs() using shift, xor, and subtract.
330 ; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036
332 define i8 @shifty_sub(i8 %x) {
333 ; CHECK-LABEL: @shifty_sub(
334 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
335 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[X]]
336 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
337 ; CHECK-NEXT: ret i8 [[R]]
340 %xor = xor i8 %x, %sh
341 %r = sub i8 %xor, %sh
345 define i8 @shifty_sub_nsw_commute(i8 %x) {
346 ; CHECK-LABEL: @shifty_sub_nsw_commute(
347 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0
348 ; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[X]]
349 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]]
350 ; CHECK-NEXT: ret i8 [[R]]
353 %xor = xor i8 %sh, %x
354 %r = sub nsw i8 %xor, %sh
358 define <4 x i32> @shifty_sub_nuw_vec_commute(<4 x i32> %x) {
359 ; CHECK-LABEL: @shifty_sub_nuw_vec_commute(
360 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i32> [[X:%.*]], zeroinitializer
361 ; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[X]], <4 x i32> zeroinitializer
362 ; CHECK-NEXT: ret <4 x i32> [[R]]
364 %sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
365 %xor = xor <4 x i32> %sh, %x
366 %r = sub nuw <4 x i32> %xor, %sh
370 define i12 @shifty_sub_nsw_nuw(i12 %x) {
371 ; CHECK-LABEL: @shifty_sub_nsw_nuw(
372 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i12 [[X:%.*]], 0
373 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i12 [[X]], i12 0
374 ; CHECK-NEXT: ret i12 [[R]]
376 %sh = ashr i12 %x, 11
377 %xor = xor i12 %x, %sh
378 %r = sub nsw nuw i12 %xor, %sh
382 define i8 @negate_abs(i8 %x) {
383 ; CHECK-LABEL: @negate_abs(
384 ; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X:%.*]]
385 ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0
386 ; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[N]]
387 ; CHECK-NEXT: ret i8 [[S]]
390 %c = icmp slt i8 %x, 0
391 %s = select i1 %c, i8 %n, i8 %x
396 define <2 x i8> @negate_nabs(<2 x i8> %x) {
397 ; CHECK-LABEL: @negate_nabs(
398 ; CHECK-NEXT: [[N:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]]
399 ; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
400 ; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[C]], <2 x i8> [[N]], <2 x i8> [[X]]
401 ; CHECK-NEXT: ret <2 x i8> [[S]]
403 %n = sub <2 x i8> zeroinitializer, %x
404 %c = icmp slt <2 x i8> %x, zeroinitializer
405 %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n
406 %r = sub <2 x i8> zeroinitializer, %s
410 define i1 @abs_must_be_positive(i32 %x) {
411 ; CHECK-LABEL: @abs_must_be_positive(
412 ; CHECK-NEXT: ret i1 true
414 %negx = sub nsw i32 0, %x
415 %c = icmp sge i32 %x, 0
416 %sel = select i1 %c, i32 %x, i32 %negx
417 %c2 = icmp sge i32 %sel, 0