[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / extract-lowbits.ll
blob4b8f3e86b5fefe63877d9ed56018fde662f31d38
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
4 ; *Please* keep in sync with test/CodeGen/X86/extract-lowbits.ll
6 ; https://bugs.llvm.org/show_bug.cgi?id=36419
7 ; https://bugs.llvm.org/show_bug.cgi?id=37603
8 ; https://bugs.llvm.org/show_bug.cgi?id=37610
10 ; Patterns:
11 ;   a) x &  (1 << nbits) - 1
12 ;   b) x & ~(-1 << nbits)
13 ;   c) x &  (-1 >> (32 - y))
14 ;   d) x << (32 - y) >> (32 - y)
15 ; are equivalent.
17 ; ---------------------------------------------------------------------------- ;
18 ; Pattern a. 32-bit
19 ; ---------------------------------------------------------------------------- ;
21 define i32 @bzhi32_a0(i32 %val, i32 %numlowbits) nounwind {
22 ; CHECK-LABEL: bzhi32_a0:
23 ; CHECK:       // %bb.0:
24 ; CHECK-NEXT:    mov w8, #1 // =0x1
25 ; CHECK-NEXT:    lsl w8, w8, w1
26 ; CHECK-NEXT:    sub w8, w8, #1
27 ; CHECK-NEXT:    and w0, w8, w0
28 ; CHECK-NEXT:    ret
29   %onebit = shl i32 1, %numlowbits
30   %mask = add nsw i32 %onebit, -1
31   %masked = and i32 %mask, %val
32   ret i32 %masked
35 define i32 @bzhi32_a1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind {
36 ; CHECK-LABEL: bzhi32_a1_indexzext:
37 ; CHECK:       // %bb.0:
38 ; CHECK-NEXT:    mov w8, #1 // =0x1
39 ; CHECK-NEXT:    lsl w8, w8, w1
40 ; CHECK-NEXT:    sub w8, w8, #1
41 ; CHECK-NEXT:    and w0, w8, w0
42 ; CHECK-NEXT:    ret
43   %conv = zext i8 %numlowbits to i32
44   %onebit = shl i32 1, %conv
45   %mask = add nsw i32 %onebit, -1
46   %masked = and i32 %mask, %val
47   ret i32 %masked
50 define i32 @bzhi32_a2_load(ptr %w, i32 %numlowbits) nounwind {
51 ; CHECK-LABEL: bzhi32_a2_load:
52 ; CHECK:       // %bb.0:
53 ; CHECK-NEXT:    mov w8, #1 // =0x1
54 ; CHECK-NEXT:    ldr w9, [x0]
55 ; CHECK-NEXT:    lsl w8, w8, w1
56 ; CHECK-NEXT:    sub w8, w8, #1
57 ; CHECK-NEXT:    and w0, w8, w9
58 ; CHECK-NEXT:    ret
59   %val = load i32, ptr %w
60   %onebit = shl i32 1, %numlowbits
61   %mask = add nsw i32 %onebit, -1
62   %masked = and i32 %mask, %val
63   ret i32 %masked
66 define i32 @bzhi32_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind {
67 ; CHECK-LABEL: bzhi32_a3_load_indexzext:
68 ; CHECK:       // %bb.0:
69 ; CHECK-NEXT:    mov w8, #1 // =0x1
70 ; CHECK-NEXT:    ldr w9, [x0]
71 ; CHECK-NEXT:    lsl w8, w8, w1
72 ; CHECK-NEXT:    sub w8, w8, #1
73 ; CHECK-NEXT:    and w0, w8, w9
74 ; CHECK-NEXT:    ret
75   %val = load i32, ptr %w
76   %conv = zext i8 %numlowbits to i32
77   %onebit = shl i32 1, %conv
78   %mask = add nsw i32 %onebit, -1
79   %masked = and i32 %mask, %val
80   ret i32 %masked
83 define i32 @bzhi32_a4_commutative(i32 %val, i32 %numlowbits) nounwind {
84 ; CHECK-LABEL: bzhi32_a4_commutative:
85 ; CHECK:       // %bb.0:
86 ; CHECK-NEXT:    mov w8, #1 // =0x1
87 ; CHECK-NEXT:    lsl w8, w8, w1
88 ; CHECK-NEXT:    sub w8, w8, #1
89 ; CHECK-NEXT:    and w0, w0, w8
90 ; CHECK-NEXT:    ret
91   %onebit = shl i32 1, %numlowbits
92   %mask = add nsw i32 %onebit, -1
93   %masked = and i32 %val, %mask ; swapped order
94   ret i32 %masked
97 ; 64-bit
99 define i64 @bzhi64_a0(i64 %val, i64 %numlowbits) nounwind {
100 ; CHECK-LABEL: bzhi64_a0:
101 ; CHECK:       // %bb.0:
102 ; CHECK-NEXT:    mov w8, #1 // =0x1
103 ; CHECK-NEXT:    lsl x8, x8, x1
104 ; CHECK-NEXT:    sub x8, x8, #1
105 ; CHECK-NEXT:    and x0, x8, x0
106 ; CHECK-NEXT:    ret
107   %onebit = shl i64 1, %numlowbits
108   %mask = add nsw i64 %onebit, -1
109   %masked = and i64 %mask, %val
110   ret i64 %masked
113 ; Check that we don't throw away the vreg_width-1 mask if not using shifts
114 define i64 @bzhi64_a0_masked(i64 %val, i64 %numlowbits) nounwind {
115 ; CHECK-LABEL: bzhi64_a0_masked:
116 ; CHECK:       // %bb.0:
117 ; CHECK-NEXT:    mov w8, #1 // =0x1
118 ; CHECK-NEXT:    lsl x8, x8, x1
119 ; CHECK-NEXT:    sub x8, x8, #1
120 ; CHECK-NEXT:    and x0, x8, x0
121 ; CHECK-NEXT:    ret
122   %numlowbits.masked = and i64 %numlowbits, 63
123   %onebit = shl i64 1, %numlowbits.masked
124   %mask = add nsw i64 %onebit, -1
125   %masked = and i64 %mask, %val
126   ret i64 %masked
129 define i64 @bzhi64_a1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind {
130 ; CHECK-LABEL: bzhi64_a1_indexzext:
131 ; CHECK:       // %bb.0:
132 ; CHECK-NEXT:    mov w8, #1 // =0x1
133 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
134 ; CHECK-NEXT:    lsl x8, x8, x1
135 ; CHECK-NEXT:    sub x8, x8, #1
136 ; CHECK-NEXT:    and x0, x8, x0
137 ; CHECK-NEXT:    ret
138   %conv = zext i8 %numlowbits to i64
139   %onebit = shl i64 1, %conv
140   %mask = add nsw i64 %onebit, -1
141   %masked = and i64 %mask, %val
142   ret i64 %masked
145 define i64 @bzhi64_a2_load(ptr %w, i64 %numlowbits) nounwind {
146 ; CHECK-LABEL: bzhi64_a2_load:
147 ; CHECK:       // %bb.0:
148 ; CHECK-NEXT:    mov w8, #1 // =0x1
149 ; CHECK-NEXT:    ldr x9, [x0]
150 ; CHECK-NEXT:    lsl x8, x8, x1
151 ; CHECK-NEXT:    sub x8, x8, #1
152 ; CHECK-NEXT:    and x0, x8, x9
153 ; CHECK-NEXT:    ret
154   %val = load i64, ptr %w
155   %onebit = shl i64 1, %numlowbits
156   %mask = add nsw i64 %onebit, -1
157   %masked = and i64 %mask, %val
158   ret i64 %masked
161 define i64 @bzhi64_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind {
162 ; CHECK-LABEL: bzhi64_a3_load_indexzext:
163 ; CHECK:       // %bb.0:
164 ; CHECK-NEXT:    mov w8, #1 // =0x1
165 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
166 ; CHECK-NEXT:    ldr x9, [x0]
167 ; CHECK-NEXT:    lsl x8, x8, x1
168 ; CHECK-NEXT:    sub x8, x8, #1
169 ; CHECK-NEXT:    and x0, x8, x9
170 ; CHECK-NEXT:    ret
171   %val = load i64, ptr %w
172   %conv = zext i8 %numlowbits to i64
173   %onebit = shl i64 1, %conv
174   %mask = add nsw i64 %onebit, -1
175   %masked = and i64 %mask, %val
176   ret i64 %masked
179 define i64 @bzhi64_a4_commutative(i64 %val, i64 %numlowbits) nounwind {
180 ; CHECK-LABEL: bzhi64_a4_commutative:
181 ; CHECK:       // %bb.0:
182 ; CHECK-NEXT:    mov w8, #1 // =0x1
183 ; CHECK-NEXT:    lsl x8, x8, x1
184 ; CHECK-NEXT:    sub x8, x8, #1
185 ; CHECK-NEXT:    and x0, x0, x8
186 ; CHECK-NEXT:    ret
187   %onebit = shl i64 1, %numlowbits
188   %mask = add nsw i64 %onebit, -1
189   %masked = and i64 %val, %mask ; swapped order
190   ret i64 %masked
193 ; ---------------------------------------------------------------------------- ;
194 ; Pattern b. 32-bit
195 ; ---------------------------------------------------------------------------- ;
197 define i32 @bzhi32_b0(i32 %val, i32 %numlowbits) nounwind {
198 ; CHECK-LABEL: bzhi32_b0:
199 ; CHECK:       // %bb.0:
200 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
201 ; CHECK-NEXT:    lsl w8, w8, w1
202 ; CHECK-NEXT:    bic w0, w0, w8
203 ; CHECK-NEXT:    ret
204   %notmask = shl i32 -1, %numlowbits
205   %mask = xor i32 %notmask, -1
206   %masked = and i32 %mask, %val
207   ret i32 %masked
210 define i32 @bzhi32_b1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind {
211 ; CHECK-LABEL: bzhi32_b1_indexzext:
212 ; CHECK:       // %bb.0:
213 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
214 ; CHECK-NEXT:    lsl w8, w8, w1
215 ; CHECK-NEXT:    bic w0, w0, w8
216 ; CHECK-NEXT:    ret
217   %conv = zext i8 %numlowbits to i32
218   %notmask = shl i32 -1, %conv
219   %mask = xor i32 %notmask, -1
220   %masked = and i32 %mask, %val
221   ret i32 %masked
224 define i32 @bzhi32_b2_load(ptr %w, i32 %numlowbits) nounwind {
225 ; CHECK-LABEL: bzhi32_b2_load:
226 ; CHECK:       // %bb.0:
227 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
228 ; CHECK-NEXT:    ldr w9, [x0]
229 ; CHECK-NEXT:    lsl w8, w8, w1
230 ; CHECK-NEXT:    bic w0, w9, w8
231 ; CHECK-NEXT:    ret
232   %val = load i32, ptr %w
233   %notmask = shl i32 -1, %numlowbits
234   %mask = xor i32 %notmask, -1
235   %masked = and i32 %mask, %val
236   ret i32 %masked
239 define i32 @bzhi32_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind {
240 ; CHECK-LABEL: bzhi32_b3_load_indexzext:
241 ; CHECK:       // %bb.0:
242 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
243 ; CHECK-NEXT:    ldr w9, [x0]
244 ; CHECK-NEXT:    lsl w8, w8, w1
245 ; CHECK-NEXT:    bic w0, w9, w8
246 ; CHECK-NEXT:    ret
247   %val = load i32, ptr %w
248   %conv = zext i8 %numlowbits to i32
249   %notmask = shl i32 -1, %conv
250   %mask = xor i32 %notmask, -1
251   %masked = and i32 %mask, %val
252   ret i32 %masked
255 define i32 @bzhi32_b4_commutative(i32 %val, i32 %numlowbits) nounwind {
256 ; CHECK-LABEL: bzhi32_b4_commutative:
257 ; CHECK:       // %bb.0:
258 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
259 ; CHECK-NEXT:    lsl w8, w8, w1
260 ; CHECK-NEXT:    bic w0, w0, w8
261 ; CHECK-NEXT:    ret
262   %notmask = shl i32 -1, %numlowbits
263   %mask = xor i32 %notmask, -1
264   %masked = and i32 %val, %mask ; swapped order
265   ret i32 %masked
268 ; 64-bit
270 define i64 @bzhi64_b0(i64 %val, i64 %numlowbits) nounwind {
271 ; CHECK-LABEL: bzhi64_b0:
272 ; CHECK:       // %bb.0:
273 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
274 ; CHECK-NEXT:    lsl x8, x8, x1
275 ; CHECK-NEXT:    bic x0, x0, x8
276 ; CHECK-NEXT:    ret
277   %notmask = shl i64 -1, %numlowbits
278   %mask = xor i64 %notmask, -1
279   %masked = and i64 %mask, %val
280   ret i64 %masked
283 define i64 @bzhi64_b1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind {
284 ; CHECK-LABEL: bzhi64_b1_indexzext:
285 ; CHECK:       // %bb.0:
286 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
287 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
288 ; CHECK-NEXT:    lsl x8, x8, x1
289 ; CHECK-NEXT:    bic x0, x0, x8
290 ; CHECK-NEXT:    ret
291   %conv = zext i8 %numlowbits to i64
292   %notmask = shl i64 -1, %conv
293   %mask = xor i64 %notmask, -1
294   %masked = and i64 %mask, %val
295   ret i64 %masked
298 define i64 @bzhi64_b2_load(ptr %w, i64 %numlowbits) nounwind {
299 ; CHECK-LABEL: bzhi64_b2_load:
300 ; CHECK:       // %bb.0:
301 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
302 ; CHECK-NEXT:    ldr x9, [x0]
303 ; CHECK-NEXT:    lsl x8, x8, x1
304 ; CHECK-NEXT:    bic x0, x9, x8
305 ; CHECK-NEXT:    ret
306   %val = load i64, ptr %w
307   %notmask = shl i64 -1, %numlowbits
308   %mask = xor i64 %notmask, -1
309   %masked = and i64 %mask, %val
310   ret i64 %masked
313 define i64 @bzhi64_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind {
314 ; CHECK-LABEL: bzhi64_b3_load_indexzext:
315 ; CHECK:       // %bb.0:
316 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
317 ; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
318 ; CHECK-NEXT:    ldr x9, [x0]
319 ; CHECK-NEXT:    lsl x8, x8, x1
320 ; CHECK-NEXT:    bic x0, x9, x8
321 ; CHECK-NEXT:    ret
322   %val = load i64, ptr %w
323   %conv = zext i8 %numlowbits to i64
324   %notmask = shl i64 -1, %conv
325   %mask = xor i64 %notmask, -1
326   %masked = and i64 %mask, %val
327   ret i64 %masked
330 define i64 @bzhi64_b4_commutative(i64 %val, i64 %numlowbits) nounwind {
331 ; CHECK-LABEL: bzhi64_b4_commutative:
332 ; CHECK:       // %bb.0:
333 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
334 ; CHECK-NEXT:    lsl x8, x8, x1
335 ; CHECK-NEXT:    bic x0, x0, x8
336 ; CHECK-NEXT:    ret
337   %notmask = shl i64 -1, %numlowbits
338   %mask = xor i64 %notmask, -1
339   %masked = and i64 %val, %mask ; swapped order
340   ret i64 %masked
343 ; ---------------------------------------------------------------------------- ;
344 ; Pattern c. 32-bit
345 ; ---------------------------------------------------------------------------- ;
347 define i32 @bzhi32_c0(i32 %val, i32 %numlowbits) nounwind {
348 ; CHECK-LABEL: bzhi32_c0:
349 ; CHECK:       // %bb.0:
350 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
351 ; CHECK-NEXT:    neg w9, w1
352 ; CHECK-NEXT:    lsr w8, w8, w9
353 ; CHECK-NEXT:    and w0, w8, w0
354 ; CHECK-NEXT:    ret
355   %numhighbits = sub i32 32, %numlowbits
356   %mask = lshr i32 -1, %numhighbits
357   %masked = and i32 %mask, %val
358   ret i32 %masked
361 define i32 @bzhi32_c1_indexzext(i32 %val, i8 %numlowbits) nounwind {
362 ; CHECK-LABEL: bzhi32_c1_indexzext:
363 ; CHECK:       // %bb.0:
364 ; CHECK-NEXT:    mov w8, #32 // =0x20
365 ; CHECK-NEXT:    mov w9, #-1 // =0xffffffff
366 ; CHECK-NEXT:    sub w8, w8, w1
367 ; CHECK-NEXT:    lsr w8, w9, w8
368 ; CHECK-NEXT:    and w0, w8, w0
369 ; CHECK-NEXT:    ret
370   %numhighbits = sub i8 32, %numlowbits
371   %sh_prom = zext i8 %numhighbits to i32
372   %mask = lshr i32 -1, %sh_prom
373   %masked = and i32 %mask, %val
374   ret i32 %masked
377 define i32 @bzhi32_c2_load(ptr %w, i32 %numlowbits) nounwind {
378 ; CHECK-LABEL: bzhi32_c2_load:
379 ; CHECK:       // %bb.0:
380 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
381 ; CHECK-NEXT:    neg w9, w1
382 ; CHECK-NEXT:    ldr w10, [x0]
383 ; CHECK-NEXT:    lsr w8, w8, w9
384 ; CHECK-NEXT:    and w0, w8, w10
385 ; CHECK-NEXT:    ret
386   %val = load i32, ptr %w
387   %numhighbits = sub i32 32, %numlowbits
388   %mask = lshr i32 -1, %numhighbits
389   %masked = and i32 %mask, %val
390   ret i32 %masked
393 define i32 @bzhi32_c3_load_indexzext(ptr %w, i8 %numlowbits) nounwind {
394 ; CHECK-LABEL: bzhi32_c3_load_indexzext:
395 ; CHECK:       // %bb.0:
396 ; CHECK-NEXT:    mov w8, #32 // =0x20
397 ; CHECK-NEXT:    mov w9, #-1 // =0xffffffff
398 ; CHECK-NEXT:    ldr w10, [x0]
399 ; CHECK-NEXT:    sub w8, w8, w1
400 ; CHECK-NEXT:    lsr w8, w9, w8
401 ; CHECK-NEXT:    and w0, w8, w10
402 ; CHECK-NEXT:    ret
403   %val = load i32, ptr %w
404   %numhighbits = sub i8 32, %numlowbits
405   %sh_prom = zext i8 %numhighbits to i32
406   %mask = lshr i32 -1, %sh_prom
407   %masked = and i32 %mask, %val
408   ret i32 %masked
411 define i32 @bzhi32_c4_commutative(i32 %val, i32 %numlowbits) nounwind {
412 ; CHECK-LABEL: bzhi32_c4_commutative:
413 ; CHECK:       // %bb.0:
414 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
415 ; CHECK-NEXT:    neg w9, w1
416 ; CHECK-NEXT:    lsr w8, w8, w9
417 ; CHECK-NEXT:    and w0, w0, w8
418 ; CHECK-NEXT:    ret
419   %numhighbits = sub i32 32, %numlowbits
420   %mask = lshr i32 -1, %numhighbits
421   %masked = and i32 %val, %mask ; swapped order
422   ret i32 %masked
425 ; 64-bit
427 define i64 @bzhi64_c0(i64 %val, i64 %numlowbits) nounwind {
428 ; CHECK-LABEL: bzhi64_c0:
429 ; CHECK:       // %bb.0:
430 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
431 ; CHECK-NEXT:    neg x9, x1
432 ; CHECK-NEXT:    lsr x8, x8, x9
433 ; CHECK-NEXT:    and x0, x8, x0
434 ; CHECK-NEXT:    ret
435   %numhighbits = sub i64 64, %numlowbits
436   %mask = lshr i64 -1, %numhighbits
437   %masked = and i64 %mask, %val
438   ret i64 %masked
441 define i64 @bzhi64_c1_indexzext(i64 %val, i8 %numlowbits) nounwind {
442 ; CHECK-LABEL: bzhi64_c1_indexzext:
443 ; CHECK:       // %bb.0:
444 ; CHECK-NEXT:    mov w8, #64 // =0x40
445 ; CHECK-NEXT:    mov x9, #-1 // =0xffffffffffffffff
446 ; CHECK-NEXT:    sub w8, w8, w1
447 ; CHECK-NEXT:    lsr x8, x9, x8
448 ; CHECK-NEXT:    and x0, x8, x0
449 ; CHECK-NEXT:    ret
450   %numhighbits = sub i8 64, %numlowbits
451   %sh_prom = zext i8 %numhighbits to i64
452   %mask = lshr i64 -1, %sh_prom
453   %masked = and i64 %mask, %val
454   ret i64 %masked
457 define i64 @bzhi64_c2_load(ptr %w, i64 %numlowbits) nounwind {
458 ; CHECK-LABEL: bzhi64_c2_load:
459 ; CHECK:       // %bb.0:
460 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
461 ; CHECK-NEXT:    neg x9, x1
462 ; CHECK-NEXT:    ldr x10, [x0]
463 ; CHECK-NEXT:    lsr x8, x8, x9
464 ; CHECK-NEXT:    and x0, x8, x10
465 ; CHECK-NEXT:    ret
466   %val = load i64, ptr %w
467   %numhighbits = sub i64 64, %numlowbits
468   %mask = lshr i64 -1, %numhighbits
469   %masked = and i64 %mask, %val
470   ret i64 %masked
473 define i64 @bzhi64_c3_load_indexzext(ptr %w, i8 %numlowbits) nounwind {
474 ; CHECK-LABEL: bzhi64_c3_load_indexzext:
475 ; CHECK:       // %bb.0:
476 ; CHECK-NEXT:    mov w8, #64 // =0x40
477 ; CHECK-NEXT:    mov x9, #-1 // =0xffffffffffffffff
478 ; CHECK-NEXT:    ldr x10, [x0]
479 ; CHECK-NEXT:    sub w8, w8, w1
480 ; CHECK-NEXT:    lsr x8, x9, x8
481 ; CHECK-NEXT:    and x0, x8, x10
482 ; CHECK-NEXT:    ret
483   %val = load i64, ptr %w
484   %numhighbits = sub i8 64, %numlowbits
485   %sh_prom = zext i8 %numhighbits to i64
486   %mask = lshr i64 -1, %sh_prom
487   %masked = and i64 %mask, %val
488   ret i64 %masked
491 define i64 @bzhi64_c4_commutative(i64 %val, i64 %numlowbits) nounwind {
492 ; CHECK-LABEL: bzhi64_c4_commutative:
493 ; CHECK:       // %bb.0:
494 ; CHECK-NEXT:    mov x8, #-1 // =0xffffffffffffffff
495 ; CHECK-NEXT:    neg x9, x1
496 ; CHECK-NEXT:    lsr x8, x8, x9
497 ; CHECK-NEXT:    and x0, x0, x8
498 ; CHECK-NEXT:    ret
499   %numhighbits = sub i64 64, %numlowbits
500   %mask = lshr i64 -1, %numhighbits
501   %masked = and i64 %val, %mask ; swapped order
502   ret i64 %masked
505 ; ---------------------------------------------------------------------------- ;
506 ; Pattern d. 32-bit.
507 ; ---------------------------------------------------------------------------- ;
509 define i32 @bzhi32_d0(i32 %val, i32 %numlowbits) nounwind {
510 ; CHECK-LABEL: bzhi32_d0:
511 ; CHECK:       // %bb.0:
512 ; CHECK-NEXT:    neg w8, w1
513 ; CHECK-NEXT:    lsl w9, w0, w8
514 ; CHECK-NEXT:    lsr w0, w9, w8
515 ; CHECK-NEXT:    ret
516   %numhighbits = sub i32 32, %numlowbits
517   %highbitscleared = shl i32 %val, %numhighbits
518   %masked = lshr i32 %highbitscleared, %numhighbits
519   ret i32 %masked
522 define i32 @bzhi32_d1_indexzext(i32 %val, i8 %numlowbits) nounwind {
523 ; CHECK-LABEL: bzhi32_d1_indexzext:
524 ; CHECK:       // %bb.0:
525 ; CHECK-NEXT:    mov w8, #32 // =0x20
526 ; CHECK-NEXT:    sub w8, w8, w1
527 ; CHECK-NEXT:    lsl w9, w0, w8
528 ; CHECK-NEXT:    lsr w0, w9, w8
529 ; CHECK-NEXT:    ret
530   %numhighbits = sub i8 32, %numlowbits
531   %sh_prom = zext i8 %numhighbits to i32
532   %highbitscleared = shl i32 %val, %sh_prom
533   %masked = lshr i32 %highbitscleared, %sh_prom
534   ret i32 %masked
537 define i32 @bzhi32_d2_load(ptr %w, i32 %numlowbits) nounwind {
538 ; CHECK-LABEL: bzhi32_d2_load:
539 ; CHECK:       // %bb.0:
540 ; CHECK-NEXT:    ldr w8, [x0]
541 ; CHECK-NEXT:    neg w9, w1
542 ; CHECK-NEXT:    lsl w8, w8, w9
543 ; CHECK-NEXT:    lsr w0, w8, w9
544 ; CHECK-NEXT:    ret
545   %val = load i32, ptr %w
546   %numhighbits = sub i32 32, %numlowbits
547   %highbitscleared = shl i32 %val, %numhighbits
548   %masked = lshr i32 %highbitscleared, %numhighbits
549   ret i32 %masked
552 define i32 @bzhi32_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind {
553 ; CHECK-LABEL: bzhi32_d3_load_indexzext:
554 ; CHECK:       // %bb.0:
555 ; CHECK-NEXT:    mov w8, #32 // =0x20
556 ; CHECK-NEXT:    ldr w9, [x0]
557 ; CHECK-NEXT:    sub w8, w8, w1
558 ; CHECK-NEXT:    lsl w9, w9, w8
559 ; CHECK-NEXT:    lsr w0, w9, w8
560 ; CHECK-NEXT:    ret
561   %val = load i32, ptr %w
562   %numhighbits = sub i8 32, %numlowbits
563   %sh_prom = zext i8 %numhighbits to i32
564   %highbitscleared = shl i32 %val, %sh_prom
565   %masked = lshr i32 %highbitscleared, %sh_prom
566   ret i32 %masked
569 ; 64-bit.
571 define i64 @bzhi64_d0(i64 %val, i64 %numlowbits) nounwind {
572 ; CHECK-LABEL: bzhi64_d0:
573 ; CHECK:       // %bb.0:
574 ; CHECK-NEXT:    neg x8, x1
575 ; CHECK-NEXT:    lsl x9, x0, x8
576 ; CHECK-NEXT:    lsr x0, x9, x8
577 ; CHECK-NEXT:    ret
578   %numhighbits = sub i64 64, %numlowbits
579   %highbitscleared = shl i64 %val, %numhighbits
580   %masked = lshr i64 %highbitscleared, %numhighbits
581   ret i64 %masked
584 define i64 @bzhi64_d1_indexzext(i64 %val, i8 %numlowbits) nounwind {
585 ; CHECK-LABEL: bzhi64_d1_indexzext:
586 ; CHECK:       // %bb.0:
587 ; CHECK-NEXT:    mov w8, #64 // =0x40
588 ; CHECK-NEXT:    sub w8, w8, w1
589 ; CHECK-NEXT:    lsl x9, x0, x8
590 ; CHECK-NEXT:    lsr x0, x9, x8
591 ; CHECK-NEXT:    ret
592   %numhighbits = sub i8 64, %numlowbits
593   %sh_prom = zext i8 %numhighbits to i64
594   %highbitscleared = shl i64 %val, %sh_prom
595   %masked = lshr i64 %highbitscleared, %sh_prom
596   ret i64 %masked
599 define i64 @bzhi64_d2_load(ptr %w, i64 %numlowbits) nounwind {
600 ; CHECK-LABEL: bzhi64_d2_load:
601 ; CHECK:       // %bb.0:
602 ; CHECK-NEXT:    ldr x8, [x0]
603 ; CHECK-NEXT:    neg x9, x1
604 ; CHECK-NEXT:    lsl x8, x8, x9
605 ; CHECK-NEXT:    lsr x0, x8, x9
606 ; CHECK-NEXT:    ret
607   %val = load i64, ptr %w
608   %numhighbits = sub i64 64, %numlowbits
609   %highbitscleared = shl i64 %val, %numhighbits
610   %masked = lshr i64 %highbitscleared, %numhighbits
611   ret i64 %masked
614 define i64 @bzhi64_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind {
615 ; CHECK-LABEL: bzhi64_d3_load_indexzext:
616 ; CHECK:       // %bb.0:
617 ; CHECK-NEXT:    mov w8, #64 // =0x40
618 ; CHECK-NEXT:    ldr x9, [x0]
619 ; CHECK-NEXT:    sub w8, w8, w1
620 ; CHECK-NEXT:    lsl x9, x9, x8
621 ; CHECK-NEXT:    lsr x0, x9, x8
622 ; CHECK-NEXT:    ret
623   %val = load i64, ptr %w
624   %numhighbits = sub i8 64, %numlowbits
625   %sh_prom = zext i8 %numhighbits to i64
626   %highbitscleared = shl i64 %val, %sh_prom
627   %masked = lshr i64 %highbitscleared, %sh_prom
628   ret i64 %masked
631 ; ---------------------------------------------------------------------------- ;
632 ; Constant mask
633 ; ---------------------------------------------------------------------------- ;
635 ; 32-bit
637 define i32 @bzhi32_constant_mask32(i32 %val) nounwind {
638 ; CHECK-LABEL: bzhi32_constant_mask32:
639 ; CHECK:       // %bb.0:
640 ; CHECK-NEXT:    and w0, w0, #0x7fffffff
641 ; CHECK-NEXT:    ret
642   %masked = and i32 %val, 2147483647
643   ret i32 %masked
646 define i32 @bzhi32_constant_mask32_load(ptr %val) nounwind {
647 ; CHECK-LABEL: bzhi32_constant_mask32_load:
648 ; CHECK:       // %bb.0:
649 ; CHECK-NEXT:    ldr w8, [x0]
650 ; CHECK-NEXT:    and w0, w8, #0x7fffffff
651 ; CHECK-NEXT:    ret
652   %val1 = load i32, ptr %val
653   %masked = and i32 %val1, 2147483647
654   ret i32 %masked
657 define i32 @bzhi32_constant_mask16(i32 %val) nounwind {
658 ; CHECK-LABEL: bzhi32_constant_mask16:
659 ; CHECK:       // %bb.0:
660 ; CHECK-NEXT:    and w0, w0, #0x7fff
661 ; CHECK-NEXT:    ret
662   %masked = and i32 %val, 32767
663   ret i32 %masked
666 define i32 @bzhi32_constant_mask16_load(ptr %val) nounwind {
667 ; CHECK-LABEL: bzhi32_constant_mask16_load:
668 ; CHECK:       // %bb.0:
669 ; CHECK-NEXT:    ldr w8, [x0]
670 ; CHECK-NEXT:    and w0, w8, #0x7fff
671 ; CHECK-NEXT:    ret
672   %val1 = load i32, ptr %val
673   %masked = and i32 %val1, 32767
674   ret i32 %masked
677 define i32 @bzhi32_constant_mask8(i32 %val) nounwind {
678 ; CHECK-LABEL: bzhi32_constant_mask8:
679 ; CHECK:       // %bb.0:
680 ; CHECK-NEXT:    and w0, w0, #0x7f
681 ; CHECK-NEXT:    ret
682   %masked = and i32 %val, 127
683   ret i32 %masked
686 define i32 @bzhi32_constant_mask8_load(ptr %val) nounwind {
687 ; CHECK-LABEL: bzhi32_constant_mask8_load:
688 ; CHECK:       // %bb.0:
689 ; CHECK-NEXT:    ldr w8, [x0]
690 ; CHECK-NEXT:    and w0, w8, #0x7f
691 ; CHECK-NEXT:    ret
692   %val1 = load i32, ptr %val
693   %masked = and i32 %val1, 127
694   ret i32 %masked
697 ; 64-bit
699 define i64 @bzhi64_constant_mask64(i64 %val) nounwind {
700 ; CHECK-LABEL: bzhi64_constant_mask64:
701 ; CHECK:       // %bb.0:
702 ; CHECK-NEXT:    and x0, x0, #0x3fffffffffffffff
703 ; CHECK-NEXT:    ret
704   %masked = and i64 %val, 4611686018427387903
705   ret i64 %masked
708 define i64 @bzhi64_constant_mask64_load(ptr %val) nounwind {
709 ; CHECK-LABEL: bzhi64_constant_mask64_load:
710 ; CHECK:       // %bb.0:
711 ; CHECK-NEXT:    ldr x8, [x0]
712 ; CHECK-NEXT:    and x0, x8, #0x3fffffffffffffff
713 ; CHECK-NEXT:    ret
714   %val1 = load i64, ptr %val
715   %masked = and i64 %val1, 4611686018427387903
716   ret i64 %masked
719 define i64 @bzhi64_constant_mask32(i64 %val) nounwind {
720 ; CHECK-LABEL: bzhi64_constant_mask32:
721 ; CHECK:       // %bb.0:
722 ; CHECK-NEXT:    and x0, x0, #0x7fffffff
723 ; CHECK-NEXT:    ret
724   %masked = and i64 %val, 2147483647
725   ret i64 %masked
728 define i64 @bzhi64_constant_mask32_load(ptr %val) nounwind {
729 ; CHECK-LABEL: bzhi64_constant_mask32_load:
730 ; CHECK:       // %bb.0:
731 ; CHECK-NEXT:    ldr x8, [x0]
732 ; CHECK-NEXT:    and x0, x8, #0x7fffffff
733 ; CHECK-NEXT:    ret
734   %val1 = load i64, ptr %val
735   %masked = and i64 %val1, 2147483647
736   ret i64 %masked
739 define i64 @bzhi64_constant_mask16(i64 %val) nounwind {
740 ; CHECK-LABEL: bzhi64_constant_mask16:
741 ; CHECK:       // %bb.0:
742 ; CHECK-NEXT:    and x0, x0, #0x7fff
743 ; CHECK-NEXT:    ret
744   %masked = and i64 %val, 32767
745   ret i64 %masked
748 define i64 @bzhi64_constant_mask16_load(ptr %val) nounwind {
749 ; CHECK-LABEL: bzhi64_constant_mask16_load:
750 ; CHECK:       // %bb.0:
751 ; CHECK-NEXT:    ldr x8, [x0]
752 ; CHECK-NEXT:    and x0, x8, #0x7fff
753 ; CHECK-NEXT:    ret
754   %val1 = load i64, ptr %val
755   %masked = and i64 %val1, 32767
756   ret i64 %masked
759 define i64 @bzhi64_constant_mask8(i64 %val) nounwind {
760 ; CHECK-LABEL: bzhi64_constant_mask8:
761 ; CHECK:       // %bb.0:
762 ; CHECK-NEXT:    and x0, x0, #0x7f
763 ; CHECK-NEXT:    ret
764   %masked = and i64 %val, 127
765   ret i64 %masked
768 define i64 @bzhi64_constant_mask8_load(ptr %val) nounwind {
769 ; CHECK-LABEL: bzhi64_constant_mask8_load:
770 ; CHECK:       // %bb.0:
771 ; CHECK-NEXT:    ldr x8, [x0]
772 ; CHECK-NEXT:    and x0, x8, #0x7f
773 ; CHECK-NEXT:    ret
774   %val1 = load i64, ptr %val
775   %masked = and i64 %val1, 127
776   ret i64 %masked