[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
blobfcbe5a615c3bdd4c094c5677c46dd1d6d055e72b
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:    // kill: def $w1 killed $w1 def $x1
19 ; CHECK-NEXT:    lsl w8, w0, w1
20 ; CHECK-NEXT:    tst w8, #0x80
21 ; CHECK-NEXT:    cset w0, eq
22 ; CHECK-NEXT:    ret
23   %t0 = lshr i8 128, %y
24   %t1 = and i8 %t0, %x
25   %res = icmp eq i8 %t1, 0
26   ret i1 %res
29 define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
30 ; CHECK-LABEL: scalar_i8_lowestbit_eq:
31 ; CHECK:       // %bb.0:
32 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
33 ; CHECK-NEXT:    lsl w8, w0, w1
34 ; CHECK-NEXT:    tst w8, #0x1
35 ; CHECK-NEXT:    cset w0, eq
36 ; CHECK-NEXT:    ret
37   %t0 = lshr i8 1, %y
38   %t1 = and i8 %t0, %x
39   %res = icmp eq i8 %t1, 0
40   ret i1 %res
43 define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
44 ; CHECK-LABEL: scalar_i8_bitsinmiddle_eq:
45 ; CHECK:       // %bb.0:
46 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
47 ; CHECK-NEXT:    lsl w8, w0, w1
48 ; CHECK-NEXT:    tst w8, #0x18
49 ; CHECK-NEXT:    cset w0, eq
50 ; CHECK-NEXT:    ret
51   %t0 = lshr i8 24, %y
52   %t1 = and i8 %t0, %x
53   %res = icmp eq i8 %t1, 0
54   ret i1 %res
57 ; i16 scalar
59 define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
60 ; CHECK-LABEL: scalar_i16_signbit_eq:
61 ; CHECK:       // %bb.0:
62 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
63 ; CHECK-NEXT:    lsl w8, w0, w1
64 ; CHECK-NEXT:    tst w8, #0x8000
65 ; CHECK-NEXT:    cset w0, eq
66 ; CHECK-NEXT:    ret
67   %t0 = lshr i16 32768, %y
68   %t1 = and i16 %t0, %x
69   %res = icmp eq i16 %t1, 0
70   ret i1 %res
73 define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
74 ; CHECK-LABEL: scalar_i16_lowestbit_eq:
75 ; CHECK:       // %bb.0:
76 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
77 ; CHECK-NEXT:    lsl w8, w0, w1
78 ; CHECK-NEXT:    tst w8, #0x1
79 ; CHECK-NEXT:    cset w0, eq
80 ; CHECK-NEXT:    ret
81   %t0 = lshr i16 1, %y
82   %t1 = and i16 %t0, %x
83   %res = icmp eq i16 %t1, 0
84   ret i1 %res
87 define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
88 ; CHECK-LABEL: scalar_i16_bitsinmiddle_eq:
89 ; CHECK:       // %bb.0:
90 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
91 ; CHECK-NEXT:    lsl w8, w0, w1
92 ; CHECK-NEXT:    tst w8, #0xff0
93 ; CHECK-NEXT:    cset w0, eq
94 ; CHECK-NEXT:    ret
95   %t0 = lshr i16 4080, %y
96   %t1 = and i16 %t0, %x
97   %res = icmp eq i16 %t1, 0
98   ret i1 %res
101 ; i32 scalar
103 define i1 @scalar_i32_signbit_eq(i32 %x, i32 %y) nounwind {
104 ; CHECK-LABEL: scalar_i32_signbit_eq:
105 ; CHECK:       // %bb.0:
106 ; CHECK-NEXT:    lsl w8, w0, w1
107 ; CHECK-NEXT:    tst w8, #0x80000000
108 ; CHECK-NEXT:    cset w0, eq
109 ; CHECK-NEXT:    ret
110   %t0 = lshr i32 2147483648, %y
111   %t1 = and i32 %t0, %x
112   %res = icmp eq i32 %t1, 0
113   ret i1 %res
116 define i1 @scalar_i32_lowestbit_eq(i32 %x, i32 %y) nounwind {
117 ; CHECK-LABEL: scalar_i32_lowestbit_eq:
118 ; CHECK:       // %bb.0:
119 ; CHECK-NEXT:    lsl w8, w0, w1
120 ; CHECK-NEXT:    tst w8, #0x1
121 ; CHECK-NEXT:    cset w0, eq
122 ; CHECK-NEXT:    ret
123   %t0 = lshr i32 1, %y
124   %t1 = and i32 %t0, %x
125   %res = icmp eq i32 %t1, 0
126   ret i1 %res
129 define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
130 ; CHECK-LABEL: scalar_i32_bitsinmiddle_eq:
131 ; CHECK:       // %bb.0:
132 ; CHECK-NEXT:    lsl w8, w0, w1
133 ; CHECK-NEXT:    tst w8, #0xffff00
134 ; CHECK-NEXT:    cset w0, eq
135 ; CHECK-NEXT:    ret
136   %t0 = lshr i32 16776960, %y
137   %t1 = and i32 %t0, %x
138   %res = icmp eq i32 %t1, 0
139   ret i1 %res
142 ; i64 scalar
144 define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
145 ; CHECK-LABEL: scalar_i64_signbit_eq:
146 ; CHECK:       // %bb.0:
147 ; CHECK-NEXT:    lsl x8, x0, x1
148 ; CHECK-NEXT:    tst x8, #0x8000000000000000
149 ; CHECK-NEXT:    cset w0, eq
150 ; CHECK-NEXT:    ret
151   %t0 = lshr i64 9223372036854775808, %y
152   %t1 = and i64 %t0, %x
153   %res = icmp eq i64 %t1, 0
154   ret i1 %res
157 define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
158 ; CHECK-LABEL: scalar_i64_lowestbit_eq:
159 ; CHECK:       // %bb.0:
160 ; CHECK-NEXT:    lsl x8, x0, x1
161 ; CHECK-NEXT:    tst x8, #0x1
162 ; CHECK-NEXT:    cset w0, eq
163 ; CHECK-NEXT:    ret
164   %t0 = lshr i64 1, %y
165   %t1 = and i64 %t0, %x
166   %res = icmp eq i64 %t1, 0
167   ret i1 %res
170 define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
171 ; CHECK-LABEL: scalar_i64_bitsinmiddle_eq:
172 ; CHECK:       // %bb.0:
173 ; CHECK-NEXT:    lsl x8, x0, x1
174 ; CHECK-NEXT:    tst x8, #0xffffffff0000
175 ; CHECK-NEXT:    cset w0, eq
176 ; CHECK-NEXT:    ret
177   %t0 = lshr i64 281474976645120, %y
178   %t1 = and i64 %t0, %x
179   %res = icmp eq i64 %t1, 0
180   ret i1 %res
183 ;------------------------------------------------------------------------------;
184 ; A few trivial vector tests
185 ;------------------------------------------------------------------------------;
187 define <4 x i1> @vec_4xi32_splat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
188 ; CHECK-LABEL: vec_4xi32_splat_eq:
189 ; CHECK:       // %bb.0:
190 ; CHECK-NEXT:    movi v2.4s, #1
191 ; CHECK-NEXT:    ushl v0.4s, v0.4s, v1.4s
192 ; CHECK-NEXT:    and v0.16b, v0.16b, v2.16b
193 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
194 ; CHECK-NEXT:    xtn v0.4h, v0.4s
195 ; CHECK-NEXT:    ret
196   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 1, i32 1>, %y
197   %t1 = and <4 x i32> %t0, %x
198   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
199   ret <4 x i1> %res
202 define <4 x i1> @vec_4xi32_nonsplat_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
203 ; CHECK-LABEL: vec_4xi32_nonsplat_eq:
204 ; CHECK:       // %bb.0:
205 ; CHECK-NEXT:    adrp x8, .LCPI13_0
206 ; CHECK-NEXT:    ldr q2, [x8, :lo12:.LCPI13_0]
207 ; CHECK-NEXT:    neg v1.4s, v1.4s
208 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
209 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
210 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
211 ; CHECK-NEXT:    xtn v0.4h, v0.4s
212 ; CHECK-NEXT:    ret
213   %t0 = lshr <4 x i32> <i32 0, i32 1, i32 16776960, i32 2147483648>, %y
214   %t1 = and <4 x i32> %t0, %x
215   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
216   ret <4 x i1> %res
219 define <4 x i1> @vec_4xi32_nonsplat_undef0_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
220 ; CHECK-LABEL: vec_4xi32_nonsplat_undef0_eq:
221 ; CHECK:       // %bb.0:
222 ; CHECK-NEXT:    movi v2.4s, #1
223 ; CHECK-NEXT:    ushl v0.4s, v0.4s, v1.4s
224 ; CHECK-NEXT:    and v0.16b, v0.16b, v2.16b
225 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
226 ; CHECK-NEXT:    xtn v0.4h, v0.4s
227 ; CHECK-NEXT:    ret
228   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 undef, i32 1>, %y
229   %t1 = and <4 x i32> %t0, %x
230   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
231   ret <4 x i1> %res
233 define <4 x i1> @vec_4xi32_nonsplat_undef1_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
234 ; CHECK-LABEL: vec_4xi32_nonsplat_undef1_eq:
235 ; CHECK:       // %bb.0:
236 ; CHECK-NEXT:    neg v1.4s, v1.4s
237 ; CHECK-NEXT:    movi v2.4s, #1
238 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
239 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
240 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
241 ; CHECK-NEXT:    xtn v0.4h, v0.4s
242 ; CHECK-NEXT:    ret
243   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 1, i32 1>, %y
244   %t1 = and <4 x i32> %t0, %x
245   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0>
246   ret <4 x i1> %res
248 define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwind {
249 ; CHECK-LABEL: vec_4xi32_nonsplat_undef2_eq:
250 ; CHECK:       // %bb.0:
251 ; CHECK-NEXT:    neg v1.4s, v1.4s
252 ; CHECK-NEXT:    movi v2.4s, #1
253 ; CHECK-NEXT:    ushl v1.4s, v2.4s, v1.4s
254 ; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
255 ; CHECK-NEXT:    cmeq v0.4s, v0.4s, #0
256 ; CHECK-NEXT:    xtn v0.4h, v0.4s
257 ; CHECK-NEXT:    ret
258   %t0 = lshr <4 x i32> <i32 1, i32 1, i32 undef, i32 1>, %y
259   %t1 = and <4 x i32> %t0, %x
260   %res = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0>
261   ret <4 x i1> %res
264 ;------------------------------------------------------------------------------;
265 ; A special tests
266 ;------------------------------------------------------------------------------;
268 define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
269 ; CHECK-LABEL: scalar_i8_signbit_ne:
270 ; CHECK:       // %bb.0:
271 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
272 ; CHECK-NEXT:    lsl w8, w0, w1
273 ; CHECK-NEXT:    ubfx w0, w8, #7, #1
274 ; CHECK-NEXT:    ret
275   %t0 = lshr i8 128, %y
276   %t1 = and i8 %t0, %x
277   %res = icmp ne i8 %t1, 0 ;  we are perfectly happy with 'ne' predicate
278   ret i1 %res
281 ;------------------------------------------------------------------------------;
282 ; What if X is a constant too?
283 ;------------------------------------------------------------------------------;
285 define i1 @scalar_i32_x_is_const_eq(i32 %y) nounwind {
286 ; CHECK-LABEL: scalar_i32_x_is_const_eq:
287 ; CHECK:       // %bb.0:
288 ; CHECK-NEXT:    mov w8, #43605
289 ; CHECK-NEXT:    movk w8, #43605, lsl #16
290 ; CHECK-NEXT:    lsr w8, w8, w0
291 ; CHECK-NEXT:    tst w8, #0x1
292 ; CHECK-NEXT:    cset w0, eq
293 ; CHECK-NEXT:    ret
294   %t0 = lshr i32 2857740885, %y
295   %t1 = and i32 %t0, 1
296   %res = icmp eq i32 %t1, 0
297   ret i1 %res
299 define i1 @scalar_i32_x_is_const2_eq(i32 %y) nounwind {
300 ; CHECK-LABEL: scalar_i32_x_is_const2_eq:
301 ; CHECK:       // %bb.0:
302 ; CHECK-NEXT:    mov w8, #1
303 ; CHECK-NEXT:    mov w9, #43605
304 ; CHECK-NEXT:    lsr w8, w8, w0
305 ; CHECK-NEXT:    movk w9, #43605, lsl #16
306 ; CHECK-NEXT:    tst w8, w9
307 ; CHECK-NEXT:    cset w0, eq
308 ; CHECK-NEXT:    ret
309   %t0 = lshr i32 1, %y
310   %t1 = and i32 %t0, 2857740885
311   %res = icmp eq i32 %t1, 0
312   ret i1 %res
315 ;------------------------------------------------------------------------------;
316 ; A few negative tests
317 ;------------------------------------------------------------------------------;
319 define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
320 ; CHECK-LABEL: negative_scalar_i8_bitsinmiddle_slt:
321 ; CHECK:       // %bb.0:
322 ; CHECK-NEXT:    mov w8, #24
323 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
324 ; CHECK-NEXT:    lsr w8, w8, w1
325 ; CHECK-NEXT:    and w8, w8, w0
326 ; CHECK-NEXT:    sxtb w8, w8
327 ; CHECK-NEXT:    cmp w8, #0 // =0
328 ; CHECK-NEXT:    cset w0, lt
329 ; CHECK-NEXT:    ret
330   %t0 = lshr i8 24, %y
331   %t1 = and i8 %t0, %x
332   %res = icmp slt i8 %t1, 0
333   ret i1 %res
336 define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
337 ; CHECK-LABEL: scalar_i8_signbit_eq_with_nonzero:
338 ; CHECK:       // %bb.0:
339 ; CHECK-NEXT:    mov w8, #128
340 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
341 ; CHECK-NEXT:    lsr w8, w8, w1
342 ; CHECK-NEXT:    and w8, w8, w0
343 ; CHECK-NEXT:    and w8, w8, #0xff
344 ; CHECK-NEXT:    cmp w8, #1 // =1
345 ; CHECK-NEXT:    cset w0, eq
346 ; CHECK-NEXT:    ret
347   %t0 = lshr i8 128, %y
348   %t1 = and i8 %t0, %x
349   %res = icmp eq i8 %t1, 1 ; should be comparing with 0
350   ret i1 %res