[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / AArch64 / hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
blob433904a6fedbc3cb4796ed7cfd69c14625e71ebd
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s --check-prefixes=CHECK,AARCH64
4 ; We are looking for the following pattern here:
5 ;   (X & (C l>> Y)) ==/!= 0
6 ; It may be optimal to hoist the constant:
7 ;   ((X << Y) & C) ==/!= 0
9 ;------------------------------------------------------------------------------;
10 ; A few scalar test
11 ;------------------------------------------------------------------------------;
13 ; i8 scalar
15 define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
16 ; CHECK-LABEL: scalar_i8_signbit_eq:
17 ; CHECK:       // %bb.0:
18 ; CHECK-NEXT:    mov w8, #128
19 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
20 ; CHECK-NEXT:    lsr w8, w8, w1
21 ; CHECK-NEXT:    and w8, w8, w0
22 ; CHECK-NEXT:    tst w8, #0xff
23 ; CHECK-NEXT:    cset w0, eq
24 ; CHECK-NEXT:    ret
25   %t0 = lshr i8 128, %y
26   %t1 = and i8 %t0, %x
27   %res = icmp eq i8 %t1, 0
28   ret i1 %res
31 define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
32 ; CHECK-LABEL: scalar_i8_lowestbit_eq:
33 ; CHECK:       // %bb.0:
34 ; CHECK-NEXT:    mov w8, #1
35 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
36 ; CHECK-NEXT:    lsr w8, w8, w1
37 ; CHECK-NEXT:    and w8, w8, w0
38 ; CHECK-NEXT:    tst w8, #0xff
39 ; CHECK-NEXT:    cset w0, eq
40 ; CHECK-NEXT:    ret
41   %t0 = lshr i8 1, %y
42   %t1 = and i8 %t0, %x
43   %res = icmp eq i8 %t1, 0
44   ret i1 %res
47 define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
48 ; CHECK-LABEL: scalar_i8_bitsinmiddle_eq:
49 ; CHECK:       // %bb.0:
50 ; CHECK-NEXT:    mov w8, #24
51 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
52 ; CHECK-NEXT:    lsr w8, w8, w1
53 ; CHECK-NEXT:    and w8, w8, w0
54 ; CHECK-NEXT:    tst w8, #0xff
55 ; CHECK-NEXT:    cset w0, eq
56 ; CHECK-NEXT:    ret
57   %t0 = lshr i8 24, %y
58   %t1 = and i8 %t0, %x
59   %res = icmp eq i8 %t1, 0
60   ret i1 %res
63 ; i16 scalar
65 define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
66 ; CHECK-LABEL: scalar_i16_signbit_eq:
67 ; CHECK:       // %bb.0:
68 ; CHECK-NEXT:    mov w8, #32768
69 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
70 ; CHECK-NEXT:    lsr w8, w8, w1
71 ; CHECK-NEXT:    and w8, w8, w0
72 ; CHECK-NEXT:    tst w8, #0xffff
73 ; CHECK-NEXT:    cset w0, eq
74 ; CHECK-NEXT:    ret
75   %t0 = lshr i16 32768, %y
76   %t1 = and i16 %t0, %x
77   %res = icmp eq i16 %t1, 0
78   ret i1 %res
81 define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
82 ; CHECK-LABEL: scalar_i16_lowestbit_eq:
83 ; CHECK:       // %bb.0:
84 ; CHECK-NEXT:    mov w8, #1
85 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
86 ; CHECK-NEXT:    lsr w8, w8, w1
87 ; CHECK-NEXT:    and w8, w8, w0
88 ; CHECK-NEXT:    tst w8, #0xffff
89 ; CHECK-NEXT:    cset w0, eq
90 ; CHECK-NEXT:    ret
91   %t0 = lshr i16 1, %y
92   %t1 = and i16 %t0, %x
93   %res = icmp eq i16 %t1, 0
94   ret i1 %res
97 define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
98 ; CHECK-LABEL: scalar_i16_bitsinmiddle_eq:
99 ; CHECK:       // %bb.0:
100 ; CHECK-NEXT:    mov w8, #4080
101 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
102 ; CHECK-NEXT:    lsr w8, w8, w1
103 ; CHECK-NEXT:    and w8, w8, w0
104 ; CHECK-NEXT:    tst w8, #0xffff
105 ; CHECK-NEXT:    cset w0, eq
106 ; CHECK-NEXT:    ret
107   %t0 = lshr i16 4080, %y
108   %t1 = and i16 %t0, %x
109   %res = icmp eq i16 %t1, 0
110   ret i1 %res
113 ; i32 scalar
115 define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
116 ; CHECK-LABEL: scalar_i32_signbit_eq:
117 ; CHECK:       // %bb.0:
118 ; CHECK-NEXT:    mov w8, #-2147483648
119 ; CHECK-NEXT:    lsr w8, w8, w1
120 ; CHECK-NEXT:    tst w8, w0
121 ; CHECK-NEXT:    cset w0, eq
122 ; CHECK-NEXT:    ret
123   %t0 = lshr i32 2147483648, %y
124   %t1 = and i32 %t0, %x
125   %res = icmp eq i32 %t1, 0
126   ret i1 %res
129 define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
130 ; CHECK-LABEL: scalar_i32_lowestbit_eq:
131 ; CHECK:       // %bb.0:
132 ; CHECK-NEXT:    mov w8, #1
133 ; CHECK-NEXT:    lsr w8, w8, w1
134 ; CHECK-NEXT:    tst w8, w0
135 ; CHECK-NEXT:    cset w0, eq
136 ; CHECK-NEXT:    ret
137   %t0 = lshr i32 1, %y
138   %t1 = and i32 %t0, %x
139   %res = icmp eq i32 %t1, 0
140   ret i1 %res
143 define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
144 ; CHECK-LABEL: scalar_i32_bitsinmiddle_eq:
145 ; CHECK:       // %bb.0:
146 ; CHECK-NEXT:    mov w8, #16776960
147 ; CHECK-NEXT:    lsr w8, w8, w1
148 ; CHECK-NEXT:    tst w8, w0
149 ; CHECK-NEXT:    cset w0, eq
150 ; CHECK-NEXT:    ret
151   %t0 = lshr i32 16776960, %y
152   %t1 = and i32 %t0, %x
153   %res = icmp eq i32 %t1, 0
154   ret i1 %res
157 ; i64 scalar
159 define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
160 ; CHECK-LABEL: scalar_i64_signbit_eq:
161 ; CHECK:       // %bb.0:
162 ; CHECK-NEXT:    mov x8, #-9223372036854775808
163 ; CHECK-NEXT:    lsr x8, x8, x1
164 ; CHECK-NEXT:    tst x8, x0
165 ; CHECK-NEXT:    cset w0, eq
166 ; CHECK-NEXT:    ret
167   %t0 = lshr i64 9223372036854775808, %y
168   %t1 = and i64 %t0, %x
169   %res = icmp eq i64 %t1, 0
170   ret i1 %res
173 define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
174 ; CHECK-LABEL: scalar_i64_lowestbit_eq:
175 ; CHECK:       // %bb.0:
176 ; CHECK-NEXT:    mov w8, #1
177 ; CHECK-NEXT:    lsr x8, x8, x1
178 ; CHECK-NEXT:    tst x8, x0
179 ; CHECK-NEXT:    cset w0, eq
180 ; CHECK-NEXT:    ret
181   %t0 = lshr i64 1, %y
182   %t1 = and i64 %t0, %x
183   %res = icmp eq i64 %t1, 0
184   ret i1 %res
187 define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
188 ; CHECK-LABEL: scalar_i64_bitsinmiddle_eq:
189 ; CHECK:       // %bb.0:
190 ; CHECK-NEXT:    mov x8, #281474976645120
191 ; CHECK-NEXT:    lsr x8, x8, x1
192 ; CHECK-NEXT:    tst x8, x0
193 ; CHECK-NEXT:    cset w0, eq
194 ; CHECK-NEXT:    ret
195   %t0 = lshr i64 281474976645120, %y
196   %t1 = and i64 %t0, %x
197   %res = icmp eq i64 %t1, 0
198   ret i1 %res
201 ;------------------------------------------------------------------------------;
202 ; A few trivial vector tests
203 ;------------------------------------------------------------------------------;
205 define <4 x i1> @vec_4xi32_splat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
206 ; CHECK-LABEL: vec_4xi32_splat_eq:
207 ; CHECK:       // %bb.0:
208 ; CHECK-NEXT:    neg v1.4s, v1.4s
209 ; CHECK-NEXT:    movi v2.4s, #1
210 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
211 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
212 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
213 ; CHECK-NEXT:    xtn v0.4h, v0.4s
214 ; CHECK-NEXT:    ret
215   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 1, i32 1>, %y
216   %t1 = and <4 x i32> %t0, %x
217   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
218   ret <4 x i1> %res
221 define <4 x i1> @vec_4xi32_nonsplat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
222 ; CHECK-LABEL: vec_4xi32_nonsplat_eq:
223 ; CHECK:       // %bb.0:
224 ; CHECK-NEXT:    adrp x8, .LCPI13_0
225 ; CHECK-NEXT:    ldr q2, [x8, :lo12:.LCPI13_0]
226 ; CHECK-NEXT:    neg v1.4s, v1.4s
227 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
228 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
229 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
230 ; CHECK-NEXT:    xtn v0.4h, v0.4s
231 ; CHECK-NEXT:    ret
232   %t0 = lshr <4 x i32> <i32 0, i32 1, i32 16776960, i32 2147483648>, %y
233   %t1 = and <4 x i32> %t0, %x
234   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
235   ret <4 x i1> %res
238 define <4 x i1> @vec_4xi32_nonsplat_undef0_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
239 ; CHECK-LABEL: vec_4xi32_nonsplat_undef0_eq:
240 ; CHECK:       // %bb.0:
241 ; CHECK-NEXT:    neg v1.4s, v1.4s
242 ; CHECK-NEXT:    movi v2.4s, #1
243 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
244 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
245 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
246 ; CHECK-NEXT:    xtn v0.4h, v0.4s
247 ; CHECK-NEXT:    ret
248   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 undef, i32 1>, %y
249   %t1 = and <4 x i32> %t0, %x
250   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
251   ret <4 x i1> %res
253 define <4 x i1> @vec_4xi32_nonsplat_undef1_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
254 ; CHECK-LABEL: vec_4xi32_nonsplat_undef1_eq:
255 ; CHECK:       // %bb.0:
256 ; CHECK-NEXT:    neg v1.4s, v1.4s
257 ; CHECK-NEXT:    movi v2.4s, #1
258 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
259 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
260 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
261 ; CHECK-NEXT:    xtn v0.4h, v0.4s
262 ; CHECK-NEXT:    ret
263   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 1, i32 1>, %y
264   %t1 = and <4 x i32> %t0, %x
265   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0>
266   ret <4 x i1> %res
268 define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
269 ; CHECK-LABEL: vec_4xi32_nonsplat_undef2_eq:
270 ; CHECK:       // %bb.0:
271 ; CHECK-NEXT:    neg v1.4s, v1.4s
272 ; CHECK-NEXT:    movi v2.4s, #1
273 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
274 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
275 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
276 ; CHECK-NEXT:    xtn v0.4h, v0.4s
277 ; CHECK-NEXT:    ret
278   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 undef, i32 1>, %y
279   %t1 = and <4 x i32> %t0, %x
280   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0>
281   ret <4 x i1> %res
284 ;------------------------------------------------------------------------------;
285 ; A special tests
286 ;------------------------------------------------------------------------------;
288 define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
289 ; CHECK-LABEL: scalar_i8_signbit_ne:
290 ; CHECK:       // %bb.0:
291 ; CHECK-NEXT:    mov w8, #128
292 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
293 ; CHECK-NEXT:    lsr w8, w8, w1
294 ; CHECK-NEXT:    and w8, w8, w0
295 ; CHECK-NEXT:    tst w8, #0xff
296 ; CHECK-NEXT:    cset w0, ne
297 ; CHECK-NEXT:    ret
298   %t0 = lshr i8 128, %y
299   %t1 = and i8 %t0, %x
300   %res = icmp ne i8 %t1, 0 ;  we are perfectly happy with 'ne' predicate
301   ret i1 %res
304 ;------------------------------------------------------------------------------;
305 ; What if X is a constant too?
306 ;------------------------------------------------------------------------------;
308 define i1 @scalar_i32_x_is_const_eq(i32 %y) nounwind {
309 ; CHECK-LABEL: scalar_i32_x_is_const_eq:
310 ; CHECK:       // %bb.0:
311 ; CHECK-NEXT:    mov w8, #43605
312 ; CHECK-NEXT:    movk w8, #43605, lsl #16
313 ; CHECK-NEXT:    lsr w8, w8, w0
314 ; CHECK-NEXT:    tst w8, #0x1
315 ; CHECK-NEXT:    cset w0, eq
316 ; CHECK-NEXT:    ret
317   %t0 = lshr i32 2857740885, %y
318   %t1 = and i32 %t0, 1
319   %res = icmp eq i32 %t1, 0
320   ret i1 %res
322 define i1 @scalar_i32_x_is_const2_eq(i32 %y) nounwind {
323 ; CHECK-LABEL: scalar_i32_x_is_const2_eq:
324 ; CHECK:       // %bb.0:
325 ; CHECK-NEXT:    mov w8, #1
326 ; CHECK-NEXT:    mov w9, #43605
327 ; CHECK-NEXT:    lsr w8, w8, w0
328 ; CHECK-NEXT:    movk w9, #43605, lsl #16
329 ; CHECK-NEXT:    tst w8, w9
330 ; CHECK-NEXT:    cset w0, eq
331 ; CHECK-NEXT:    ret
332   %t0 = lshr i32 1, %y
333   %t1 = and i32 %t0, 2857740885
334   %res = icmp eq i32 %t1, 0
335   ret i1 %res
338 ;------------------------------------------------------------------------------;
339 ; A few negative tests
340 ;------------------------------------------------------------------------------;
342 define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
343 ; CHECK-LABEL: negative_scalar_i8_bitsinmiddle_slt:
344 ; CHECK:       // %bb.0:
345 ; CHECK-NEXT:    mov w8, #24
346 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
347 ; CHECK-NEXT:    lsr w8, w8, w1
348 ; CHECK-NEXT:    and w8, w8, w0
349 ; CHECK-NEXT:    sxtb w8, w8
350 ; CHECK-NEXT:    cmp w8, #0 // =0
351 ; CHECK-NEXT:    cset w0, lt
352 ; CHECK-NEXT:    ret
353   %t0 = lshr i8 24, %y
354   %t1 = and i8 %t0, %x
355   %res = icmp slt i8 %t1, 0
356   ret i1 %res
359 define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
360 ; CHECK-LABEL: scalar_i8_signbit_eq_with_nonzero:
361 ; CHECK:       // %bb.0:
362 ; CHECK-NEXT:    mov w8, #128
363 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
364 ; CHECK-NEXT:    lsr w8, w8, w1
365 ; CHECK-NEXT:    and w8, w8, w0
366 ; CHECK-NEXT:    and w8, w8, #0xff
367 ; CHECK-NEXT:    cmp w8, #1 // =1
368 ; CHECK-NEXT:    cset w0, eq
369 ; CHECK-NEXT:    ret
370   %t0 = lshr i8 128, %y
371   %t1 = and i8 %t0, %x
372   %res = icmp eq i8 %t1, 1 ; should be comparing with 0
373   ret i1 %res