[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
blob2de7e432ac2b84fdccb9569e64f3313c036b3670
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=38708
6 ; Pattern:
7 ;   ((1 << bits)+(-1)) u< val
8 ; Should be transformed into:
9 ;   (val l>> bits) != 0
11 ; NOTE: the innermost shl is not one-use. Else canonicalization happens.
13 declare void @use8(i8)
14 declare void @use2i8(<2 x i8>)
15 declare void @use3i8(<3 x i8>)
17 ; ============================================================================ ;
18 ; Basic positive tests
19 ; ============================================================================ ;
21 define i1 @p0(i8 %val, i8 %bits) {
22 ; CHECK-LABEL: @p0(
23 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
24 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
25 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS]]
26 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
27 ; CHECK-NEXT:    ret i1 [[R]]
29   %t0 = shl i8 1, %bits
30   call void @use8(i8 %t0)
31   %t1 = add i8 %t0, -1
32   %r = icmp ult i8 %t1, %val
33   ret i1 %r
36 ; ============================================================================ ;
37 ; Vector tests
38 ; ============================================================================ ;
40 define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
41 ; CHECK-LABEL: @p1_vec(
42 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
43 ; CHECK-NEXT:    call void @use2i8(<2 x i8> [[T0]])
44 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS]]
45 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
46 ; CHECK-NEXT:    ret <2 x i1> [[R]]
48   %t0 = shl <2 x i8> <i8 1, i8 1>, %bits
49   call void @use2i8(<2 x i8> %t0)
50   %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
51   %r = icmp ult <2 x i8> %t1, %val
52   ret <2 x i1> %r
55 define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) {
56 ; CHECK-LABEL: @p2_vec_undef0(
57 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
58 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
59 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
60 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
61 ; CHECK-NEXT:    ret <3 x i1> [[R]]
63   %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
64   call void @use3i8(<3 x i8> %t0)
65   %t1 = add <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
66   %r = icmp ult <3 x i8> %t1, %val
67   ret <3 x i1> %r
70 define <3 x i1> @p2_vec_undef1(<3 x i8> %val, <3 x i8> %bits) {
71 ; CHECK-LABEL: @p2_vec_undef1(
72 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 1, i8 1>, [[BITS:%.*]]
73 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
74 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
75 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
76 ; CHECK-NEXT:    ret <3 x i1> [[R]]
78   %t0 = shl <3 x i8> <i8 1, i8 1, i8 1>, %bits
79   call void @use3i8(<3 x i8> %t0)
80   %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
81   %r = icmp ult <3 x i8> %t1, %val
82   ret <3 x i1> %r
85 define <3 x i1> @p2_vec_undef2(<3 x i8> %val, <3 x i8> %bits) {
86 ; CHECK-LABEL: @p2_vec_undef2(
87 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
88 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
89 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
90 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
91 ; CHECK-NEXT:    ret <3 x i1> [[R]]
93   %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
94   call void @use3i8(<3 x i8> %t0)
95   %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
96   %r = icmp ult <3 x i8> %t1, %val
97   ret <3 x i1> %r
100 ; ============================================================================ ;
101 ; Commutativity tests.
102 ; ============================================================================ ;
104 declare i8 @gen8()
106 define i1 @c0(i8 %bits) {
107 ; CHECK-LABEL: @c0(
108 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
109 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
110 ; CHECK-NEXT:    [[VAL:%.*]] = call i8 @gen8()
111 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS]]
112 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
113 ; CHECK-NEXT:    ret i1 [[R]]
115   %t0 = shl i8 1, %bits
116   call void @use8(i8 %t0)
117   %t1 = add i8 %t0, -1
118   %val = call i8 @gen8()
119   %r = icmp ugt i8 %val, %t1 ; swapped order and predicate
120   ret i1 %r
123 ; What if we have the same pattern on both sides?
124 define i1 @both(i8 %bits0, i8 %bits1) {
125 ; CHECK-LABEL: @both(
126 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS0:%.*]]
127 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
128 ; CHECK-NEXT:    [[T2:%.*]] = shl i8 1, [[BITS1:%.*]]
129 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
130 ; CHECK-NEXT:    [[T3:%.*]] = add i8 [[T2]], -1
131 ; CHECK-NEXT:    [[T3_HIGHBITS:%.*]] = lshr i8 [[T3]], [[BITS0]]
132 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[T3_HIGHBITS]], 0
133 ; CHECK-NEXT:    ret i1 [[R]]
135   %t0 = shl i8 1, %bits0
136   call void @use8(i8 %t0)
137   %t1 = add i8 %t0, -1
138   %t2 = shl i8 1, %bits1
139   call void @use8(i8 %t2)
140   %t3 = add i8 %t2, -1
141   %r = icmp ult i8 %t1, %t3
142   ret i1 %r
145 ; ============================================================================ ;
146 ; One-use tests.
147 ; ============================================================================ ;
149 define i1 @oneuse(i8 %val, i8 %bits) {
150 ; CHECK-LABEL: @oneuse(
151 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
152 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
153 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
154 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
155 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
156 ; CHECK-NEXT:    ret i1 [[R]]
158   %t0 = shl i8 1, %bits
159   call void @use8(i8 %t0) ; this is needed anyway
160   %t1 = add i8 %t0, -1
161   call void @use8(i8 %t1)
162   %r = icmp ult i8 %t1, %val
163   ret i1 %r
166 ; ============================================================================ ;
167 ; Negative tests
168 ; ============================================================================ ;
170 define i1 @n0(i8 %val, i8 %bits) {
171 ; CHECK-LABEL: @n0(
172 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
173 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
174 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
175 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
176 ; CHECK-NEXT:    ret i1 [[R]]
178   %t0 = shl i8 -1, %bits ; constant is not 1
179   call void @use8(i8 %t0)
180   %t1 = add i8 %t0, -1
181   %r = icmp ult i8 %t1, %val
182   ret i1 %r
185 define i1 @n1(i8 %val, i8 %bits) {
186 ; CHECK-LABEL: @n1(
187 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
188 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
189 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], 1
190 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
191 ; CHECK-NEXT:    ret i1 [[R]]
193   %t0 = shl i8 1, %bits
194   call void @use8(i8 %t0)
195   %t1 = add i8 %t0, 1 ; constant is not -1
196   %r = icmp ult i8 %t1, %val
197   ret i1 %r
200 define <2 x i1> @n2_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
201 ; CHECK-LABEL: @n2_vec_nonsplat(
202 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 1, i8 -1>, [[BITS:%.*]]
203 ; CHECK-NEXT:    call void @use2i8(<2 x i8> [[T0]])
204 ; CHECK-NEXT:    [[T1:%.*]] = add <2 x i8> [[T0]], <i8 -1, i8 -1>
205 ; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
206 ; CHECK-NEXT:    ret <2 x i1> [[R]]
208   %t0 = shl <2 x i8> <i8 1, i8 -1>, %bits ; again, wrong constant
209   call void @use2i8(<2 x i8> %t0)
210   %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
211   %r = icmp ult <2 x i8> %t1, %val
212   ret <2 x i1> %r
215 define <2 x i1> @n3_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
216 ; CHECK-LABEL: @n3_vec_nonsplat(
217 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
218 ; CHECK-NEXT:    call void @use2i8(<2 x i8> [[T0]])
219 ; CHECK-NEXT:    [[T1:%.*]] = add <2 x i8> [[T0]], <i8 -1, i8 1>
220 ; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
221 ; CHECK-NEXT:    ret <2 x i1> [[R]]
223   %t0 = shl <2 x i8> <i8 1, i8 1>, %bits
224   call void @use2i8(<2 x i8> %t0)
225   %t1 = add <2 x i8> %t0, <i8 -1, i8 1> ; again, wrong constant
226   %r = icmp ult <2 x i8> %t1, %val
227   ret <2 x i1> %r
230 define i1 @n3(i8 %val, i8 %bits) {
231 ; CHECK-LABEL: @n3(
232 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
233 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
234 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
235 ; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[T1]], [[VAL:%.*]]
236 ; CHECK-NEXT:    ret i1 [[R]]
238   %t0 = shl i8 1, %bits
239   call void @use8(i8 %t0)
240   %t1 = add i8 %t0, -1
241   %r = icmp ule i8 %t1, %val ; wrong predicate
242   ret i1 %r
245 define i1 @n4(i8 %bits) {
246 ; CHECK-LABEL: @n4(
247 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
248 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
249 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
250 ; CHECK-NEXT:    [[VAL:%.*]] = call i8 @gen8()
251 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[VAL]], [[T1]]
252 ; CHECK-NEXT:    ret i1 [[R]]
254   %t0 = shl i8 1, %bits
255   call void @use8(i8 %t0)
256   %t1 = add i8 %t0, -1
257   %val = call i8 @gen8()
258   %r = icmp uge i8 %val, %t1 ; swapped order and [wrong] predicate
259   ret i1 %r