[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / ashr-or-mul-abs.ll
blobab390a209340dfec00a387cfe123e2d0d0acd04a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; ((ashr X, 31) | 1 ) * X --> abs(X)
5 ; X * ((ashr X, 31) | 1 ) --> abs(X)
7 define i32 @ashr_or_mul_to_abs(i32 %X) {
8 ; CHECK-LABEL: @ashr_or_mul_to_abs(
9 ; CHECK-NEXT:    [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
10 ; CHECK-NEXT:    ret i32 [[I2]]
12   %i = ashr i32 %X, 31
13   %i1 = or i32 %i, 1
14   %i2 = mul nsw i32 %i1, %X
15   ret i32 %i2
18 define i32 @ashr_or_mul_to_abs2(i32 %X) {
19 ; CHECK-LABEL: @ashr_or_mul_to_abs2(
20 ; CHECK-NEXT:    [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
21 ; CHECK-NEXT:    ret i32 [[I2]]
23   %i = ashr i32 %X, 31
24   %i1 = or i32 %i, 1
25   %i2 = mul i32 %i1, %X
26   ret i32 %i2
29 define i32 @ashr_or_mul_to_abs3(i32 %PX) {
30 ; CHECK-LABEL: @ashr_or_mul_to_abs3(
31 ; CHECK-NEXT:    [[X:%.*]] = sdiv i32 42, [[PX:%.*]]
32 ; CHECK-NEXT:    [[I2:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false)
33 ; CHECK-NEXT:    ret i32 [[I2]]
35   %X = sdiv i32 42, %PX ; thwart complexity-based canonicalization
36   %i = ashr i32 %X, 31
37   %i1 = or i32 %i, 1
38   %i2 = mul i32 %X, %i1
39   ret i32 %i2
43 define <4 x i32> @ashr_or_mul_to_abs_vec(<4 x i32> %X) {
44 ; CHECK-LABEL: @ashr_or_mul_to_abs_vec(
45 ; CHECK-NEXT:    [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 false)
46 ; CHECK-NEXT:    ret <4 x i32> [[I2]]
48   %i = ashr <4 x i32> %X, <i32 31, i32 31, i32 31, i32 31>
49   %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 1>
50   %i2 = mul <4 x i32> %i1, %X
51   ret <4 x i32> %i2
54 define <4 x i32> @ashr_or_mul_to_abs_vec2(<4 x i32> %X) {
55 ; CHECK-LABEL: @ashr_or_mul_to_abs_vec2(
56 ; CHECK-NEXT:    [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 true)
57 ; CHECK-NEXT:    ret <4 x i32> [[I2]]
59   %i = ashr <4 x i32> %X, <i32 31, i32 31, i32 31, i32 31>
60   %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 1>
61   %i2 = mul nsw <4 x i32> %i1, %X
62   ret <4 x i32> %i2
65 define <4 x i32> @ashr_or_mul_to_abs_vec3_undef(<4 x i32> %X) {
66 ; CHECK-LABEL: @ashr_or_mul_to_abs_vec3_undef(
67 ; CHECK-NEXT:    [[I2:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 false)
68 ; CHECK-NEXT:    ret <4 x i32> [[I2]]
70   %i = ashr <4 x i32> %X, <i32 31, i32 undef, i32 31, i32 31>
71   %i1 = or <4 x i32> %i, <i32 1, i32 1, i32 1, i32 undef>
72   %i2 = mul <4 x i32> %i1, %X
73   ret <4 x i32> %i2
76 ; Negative tests
78 define i32 @ashr_or_mul_to_abs_neg(i32 %X) {
79 ; CHECK-LABEL: @ashr_or_mul_to_abs_neg(
80 ; CHECK-NEXT:    [[I:%.*]] = ashr i32 [[X:%.*]], 30
81 ; CHECK-NEXT:    [[I1:%.*]] = or i32 [[I]], 1
82 ; CHECK-NEXT:    [[I2:%.*]] = mul nsw i32 [[I1]], [[X]]
83 ; CHECK-NEXT:    ret i32 [[I2]]
85   %i = ashr i32 %X, 30
86   %i1 = or i32 %i, 1
87   %i2 = mul nsw i32 %i1, %X
88   ret i32 %i2
91 define i32 @ashr_or_mul_to_abs_neg2(i32 %X) {
92 ; CHECK-LABEL: @ashr_or_mul_to_abs_neg2(
93 ; CHECK-NEXT:    [[I:%.*]] = ashr i32 [[X:%.*]], 31
94 ; CHECK-NEXT:    [[I1:%.*]] = or i32 [[I]], 2
95 ; CHECK-NEXT:    [[I2:%.*]] = mul nsw i32 [[I1]], [[X]]
96 ; CHECK-NEXT:    ret i32 [[I2]]
98   %i = ashr i32 %X, 31
99   %i1 = or i32 %i, 2
100   %i2 = mul nsw i32 %i1, %X
101   ret i32 %i2
104 define i32 @ashr_or_mul_to_abs_neg3(i32 %X, i32 %Y) {
105 ; CHECK-LABEL: @ashr_or_mul_to_abs_neg3(
106 ; CHECK-NEXT:    [[I:%.*]] = ashr i32 [[X:%.*]], 31
107 ; CHECK-NEXT:    [[I1:%.*]] = or i32 [[I]], 1
108 ; CHECK-NEXT:    [[I2:%.*]] = mul nsw i32 [[I1]], [[Y:%.*]]
109 ; CHECK-NEXT:    ret i32 [[I2]]
111   %i = ashr i32 %X, 31
112   %i1 = or i32 %i, 1
113   %i2 = mul nsw i32 %i1, %Y
114   ret i32 %i2