[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
blob2826d2d33c18508872410af5a76a6492ae502015
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=38123
6 ; Pattern:
7 ;   x & ~(-1 << y) != x
8 ; Should be transformed into:
9 ;   x u> ~(-1 << y)
10 ; That is then later transformed into:
11 ;   (x >> y) != 0
13 ; ============================================================================ ;
14 ; Basic positive tests
15 ; ============================================================================ ;
17 define i1 @p0(i8 %x, i8 %y) {
18 ; CHECK-LABEL: @p0(
19 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]]
20 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
21 ; CHECK-NEXT:    ret i1 [[TMP1]]
23   %t0 = shl i8 -1, %y
24   %t1 = xor i8 %t0, -1
25   %t2 = and i8 %t1, %x
26   %ret = icmp ne i8 %t2, %x
27   ret i1 %ret
30 ; ============================================================================ ;
31 ; Vector tests
32 ; ============================================================================ ;
34 define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
35 ; CHECK-LABEL: @p1_vec(
36 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <2 x i8> [[X:%.*]], [[Y:%.*]]
37 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i8> [[X_HIGHBITS]], zeroinitializer
38 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
40   %t0 = shl <2 x i8> <i8 -1, i8 -1>, %y
41   %t1 = xor <2 x i8> %t0, <i8 -1, i8 -1>
42   %t2 = and <2 x i8> %t1, %x
43   %ret = icmp ne <2 x i8> %t2, %x
44   ret <2 x i1> %ret
47 define <3 x i1> @p2_vec_undef0(<3 x i8> %x, <3 x i8> %y) {
48 ; CHECK-LABEL: @p2_vec_undef0(
49 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y:%.*]]
50 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
51 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
53   %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %y
54   %t1 = xor <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
55   %t2 = and <3 x i8> %t1, %x
56   %ret = icmp ne <3 x i8> %t2, %x
57   ret <3 x i1> %ret
60 define <3 x i1> @p3_vec_undef0(<3 x i8> %x, <3 x i8> %y) {
61 ; CHECK-LABEL: @p3_vec_undef0(
62 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y:%.*]]
63 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
64 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
66   %t0 = shl <3 x i8> <i8 -1, i8 -1, i8 -1>, %y
67   %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
68   %t2 = and <3 x i8> %t1, %x
69   %ret = icmp ne <3 x i8> %t2, %x
70   ret <3 x i1> %ret
73 define <3 x i1> @p4_vec_undef2(<3 x i8> %x, <3 x i8> %y) {
74 ; CHECK-LABEL: @p4_vec_undef2(
75 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y:%.*]]
76 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
77 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
79   %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %y
80   %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
81   %t2 = and <3 x i8> %t1, %x
82   %ret = icmp ne <3 x i8> %t2, %x
83   ret <3 x i1> %ret
86 ; ============================================================================ ;
87 ; Commutativity tests.
88 ; ============================================================================ ;
90 declare i8 @gen8()
92 define i1 @c0(i8 %y) {
93 ; CHECK-LABEL: @c0(
94 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
95 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y:%.*]]
96 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
97 ; CHECK-NEXT:    ret i1 [[TMP1]]
99   %t0 = shl i8 -1, %y
100   %t1 = xor i8 %t0, -1
101   %x = call i8 @gen8()
102   %t2 = and i8 %x, %t1 ; swapped order
103   %ret = icmp ne i8 %t2, %x
104   ret i1 %ret
107 define i1 @c1(i8 %y) {
108 ; CHECK-LABEL: @c1(
109 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
110 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y:%.*]]
111 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
112 ; CHECK-NEXT:    ret i1 [[TMP1]]
114   %t0 = shl i8 -1, %y
115   %t1 = xor i8 %t0, -1
116   %x = call i8 @gen8()
117   %t2 = and i8 %t1, %x
118   %ret = icmp ne i8 %x, %t2 ; swapped order
119   ret i1 %ret
122 define i1 @c2(i8 %y) {
123 ; CHECK-LABEL: @c2(
124 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
125 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y:%.*]]
126 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
127 ; CHECK-NEXT:    ret i1 [[TMP1]]
129   %t0 = shl i8 -1, %y
130   %t1 = xor i8 %t0, -1
131   %x = call i8 @gen8()
132   %t2 = and i8 %x, %t1 ; swapped order
133   %ret = icmp ne i8 %x, %t2 ; swapped order
134   ret i1 %ret
137 ; ============================================================================ ;
138 ; One-use tests. We don't care about multi-uses here.
139 ; ============================================================================ ;
141 declare void @use8(i8)
143 define i1 @oneuse0(i8 %x, i8 %y) {
144 ; CHECK-LABEL: @oneuse0(
145 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
146 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
147 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
148 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
149 ; CHECK-NEXT:    ret i1 [[TMP1]]
151   %t0 = shl i8 -1, %y
152   call void @use8(i8 %t0)
153   %t1 = xor i8 %t0, -1
154   %t2 = and i8 %t1, %x
155   %ret = icmp ne i8 %t2, %x
156   ret i1 %ret
159 define i1 @oneuse1(i8 %x, i8 %y) {
160 ; CHECK-LABEL: @oneuse1(
161 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
162 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
163 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
164 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
165 ; CHECK-NEXT:    ret i1 [[TMP1]]
167   %t0 = shl i8 -1, %y
168   %t1 = xor i8 %t0, -1
169   call void @use8(i8 %t1)
170   %t2 = and i8 %t1, %x
171   %ret = icmp ne i8 %t2, %x
172   ret i1 %ret
175 define i1 @oneuse2(i8 %x, i8 %y) {
176 ; CHECK-LABEL: @oneuse2(
177 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
178 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
179 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
180 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
181 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[T1]], [[X]]
182 ; CHECK-NEXT:    ret i1 [[TMP1]]
184   %t0 = shl i8 -1, %y
185   %t1 = xor i8 %t0, -1
186   %t2 = and i8 %t1, %x
187   call void @use8(i8 %t2)
188   %ret = icmp ne i8 %t2, %x
189   ret i1 %ret
192 define i1 @oneuse3(i8 %x, i8 %y) {
193 ; CHECK-LABEL: @oneuse3(
194 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
195 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
196 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
197 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
198 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
199 ; CHECK-NEXT:    ret i1 [[TMP1]]
201   %t0 = shl i8 -1, %y
202   call void @use8(i8 %t0)
203   %t1 = xor i8 %t0, -1
204   call void @use8(i8 %t1)
205   %t2 = and i8 %t1, %x
206   %ret = icmp ne i8 %t2, %x
207   ret i1 %ret
210 define i1 @oneuse4(i8 %x, i8 %y) {
211 ; CHECK-LABEL: @oneuse4(
212 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
213 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
214 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
215 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
216 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
217 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[T1]], [[X]]
218 ; CHECK-NEXT:    ret i1 [[TMP1]]
220   %t0 = shl i8 -1, %y
221   call void @use8(i8 %t0)
222   %t1 = xor i8 %t0, -1
223   %t2 = and i8 %t1, %x
224   call void @use8(i8 %t2)
225   %ret = icmp ne i8 %t2, %x
226   ret i1 %ret
229 define i1 @oneuse5(i8 %x, i8 %y) {
230 ; CHECK-LABEL: @oneuse5(
231 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
232 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
233 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
234 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
235 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
236 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
237 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[T1]], [[X]]
238 ; CHECK-NEXT:    ret i1 [[TMP1]]
240   %t0 = shl i8 -1, %y
241   call void @use8(i8 %t0)
242   %t1 = xor i8 %t0, -1
243   call void @use8(i8 %t1)
244   %t2 = and i8 %t1, %x
245   call void @use8(i8 %t2)
246   %ret = icmp ne i8 %t2, %x
247   ret i1 %ret
250 ; ============================================================================ ;
251 ; Negative tests
252 ; ============================================================================ ;
254 define i1 @n0(i8 %x, i8 %y, i8 %notx) {
255 ; CHECK-LABEL: @n0(
256 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
257 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
258 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
259 ; CHECK-NEXT:    [[RET:%.*]] = icmp ne i8 [[T2]], [[NOTX:%.*]]
260 ; CHECK-NEXT:    ret i1 [[RET]]
262   %t0 = shl i8 -1, %y
263   %t1 = xor i8 %t0, -1
264   %t2 = and i8 %t1, %x
265   %ret = icmp ne i8 %t2, %notx ; not %x
266   ret i1 %ret
269 define i1 @n1(i8 %x, i8 %y) {
270 ; CHECK-LABEL: @n1(
271 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
272 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
273 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
274 ; CHECK-NEXT:    [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
275 ; CHECK-NEXT:    ret i1 [[RET]]
277   %t0 = shl i8 1, %y ; not -1
278   %t1 = xor i8 %t0, -1
279   %t2 = and i8 %t1, %x
280   %ret = icmp ne i8 %t2, %x
281   ret i1 %ret
284 define i1 @n2(i8 %x, i8 %y) {
285 ; CHECK-LABEL: @n2(
286 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
287 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], 1
288 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
289 ; CHECK-NEXT:    [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
290 ; CHECK-NEXT:    ret i1 [[RET]]
292   %t0 = shl i8 -1, %y
293   %t1 = xor i8 %t0, 1 ; not -1
294   %t2 = and i8 %t1, %x
295   %ret = icmp ne i8 %t2, %x
296   ret i1 %ret