xref: /llvm-project/llvm/test/CodeGen/AArch64/extract-lowbits.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
3
4; *Please* keep in sync with test/CodeGen/X86/extract-lowbits.ll
5
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
9
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.
16
17; ---------------------------------------------------------------------------- ;
18; Pattern a. 32-bit
19; ---------------------------------------------------------------------------- ;
20
21define 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
33}
34
35define 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
48}
49
50define 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
64}
65
66define 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
81}
82
83define 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
95}
96
97; 64-bit
98
99define 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
111}
112
113; Check that we don't throw away the vreg_width-1 mask if not using shifts
114define 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
127}
128
129define 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
143}
144
145define 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
159}
160
161define 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
177}
178
179define 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
191}
192
193; ---------------------------------------------------------------------------- ;
194; Pattern b. 32-bit
195; ---------------------------------------------------------------------------- ;
196
197define 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
208}
209
210define 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
222}
223
224define 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
237}
238
239define 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
253}
254
255define 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
266}
267
268; 64-bit
269
270define 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
281}
282
283define 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
296}
297
298define 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
311}
312
313define 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
328}
329
330define 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
341}
342
343; ---------------------------------------------------------------------------- ;
344; Pattern c. 32-bit
345; ---------------------------------------------------------------------------- ;
346
347define 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
359}
360
361define 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
375}
376
377define 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
391}
392
393define 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
409}
410
411define 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
423}
424
425; 64-bit
426
427define 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
439}
440
441define 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
455}
456
457define 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
471}
472
473define 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
489}
490
491define 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
503}
504
505; ---------------------------------------------------------------------------- ;
506; Pattern d. 32-bit.
507; ---------------------------------------------------------------------------- ;
508
509define 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
520}
521
522define 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
535}
536
537define 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
550}
551
552define 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
567}
568
569; 64-bit.
570
571define 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
582}
583
584define 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
597}
598
599define 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
612}
613
614define 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
629}
630
631; ---------------------------------------------------------------------------- ;
632; Constant mask
633; ---------------------------------------------------------------------------- ;
634
635; 32-bit
636
637define 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
644}
645
646define 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
655}
656
657define 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
664}
665
666define 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
675}
676
677define 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
684}
685
686define 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
695}
696
697; 64-bit
698
699define 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
706}
707
708define 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
717}
718
719define 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
726}
727
728define 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
737}
738
739define 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
746}
747
748define 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
757}
758
759define 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
766}
767
768define 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
777}
778