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-bits.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 >> start) &  (1 << nbits) - 1
12;   b) (x >> start) & ~(-1 << nbits)
13;   c) (x >> start) &  (-1 >> (32 - y))
14;   d) (x >> start) << (32 - y) >> (32 - y)
15; are equivalent.
16
17; ---------------------------------------------------------------------------- ;
18; Pattern a. 32-bit
19; ---------------------------------------------------------------------------- ;
20
21define i32 @bextr32_a0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
22; CHECK-LABEL: bextr32_a0:
23; CHECK:       // %bb.0:
24; CHECK-NEXT:    orr w9, wzr, #0x1
25; CHECK-NEXT:    lsl w9, w9, w2
26; CHECK-NEXT:    lsr w8, w0, w1
27; CHECK-NEXT:    sub w9, w9, #1 // =1
28; CHECK-NEXT:    and w0, w9, w8
29; CHECK-NEXT:    ret
30  %shifted = lshr i32 %val, %numskipbits
31  %onebit = shl i32 1, %numlowbits
32  %mask = add nsw i32 %onebit, -1
33  %masked = and i32 %mask, %shifted
34  ret i32 %masked
35}
36
37define i32 @bextr32_a1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
38; CHECK-LABEL: bextr32_a1_indexzext:
39; CHECK:       // %bb.0:
40; CHECK-NEXT:    orr w9, wzr, #0x1
41; CHECK-NEXT:    lsl w9, w9, w2
42; CHECK-NEXT:    lsr w8, w0, w1
43; CHECK-NEXT:    sub w9, w9, #1 // =1
44; CHECK-NEXT:    and w0, w9, w8
45; CHECK-NEXT:    ret
46  %skip = zext i8 %numskipbits to i32
47  %shifted = lshr i32 %val, %skip
48  %conv = zext i8 %numlowbits to i32
49  %onebit = shl i32 1, %conv
50  %mask = add nsw i32 %onebit, -1
51  %masked = and i32 %mask, %shifted
52  ret i32 %masked
53}
54
55define i32 @bextr32_a2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind {
56; CHECK-LABEL: bextr32_a2_load:
57; CHECK:       // %bb.0:
58; CHECK-NEXT:    ldr w8, [x0]
59; CHECK-NEXT:    orr w9, wzr, #0x1
60; CHECK-NEXT:    lsl w9, w9, w2
61; CHECK-NEXT:    sub w9, w9, #1 // =1
62; CHECK-NEXT:    lsr w8, w8, w1
63; CHECK-NEXT:    and w0, w9, w8
64; CHECK-NEXT:    ret
65  %val = load i32, i32* %w
66  %shifted = lshr i32 %val, %numskipbits
67  %onebit = shl i32 1, %numlowbits
68  %mask = add nsw i32 %onebit, -1
69  %masked = and i32 %mask, %shifted
70  ret i32 %masked
71}
72
73define i32 @bextr32_a3_load_indexzext(i32* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
74; CHECK-LABEL: bextr32_a3_load_indexzext:
75; CHECK:       // %bb.0:
76; CHECK-NEXT:    ldr w8, [x0]
77; CHECK-NEXT:    orr w9, wzr, #0x1
78; CHECK-NEXT:    lsl w9, w9, w2
79; CHECK-NEXT:    sub w9, w9, #1 // =1
80; CHECK-NEXT:    lsr w8, w8, w1
81; CHECK-NEXT:    and w0, w9, w8
82; CHECK-NEXT:    ret
83  %val = load i32, i32* %w
84  %skip = zext i8 %numskipbits to i32
85  %shifted = lshr i32 %val, %skip
86  %conv = zext i8 %numlowbits to i32
87  %onebit = shl i32 1, %conv
88  %mask = add nsw i32 %onebit, -1
89  %masked = and i32 %mask, %shifted
90  ret i32 %masked
91}
92
93define i32 @bextr32_a4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
94; CHECK-LABEL: bextr32_a4_commutative:
95; CHECK:       // %bb.0:
96; CHECK-NEXT:    orr w9, wzr, #0x1
97; CHECK-NEXT:    lsl w9, w9, w2
98; CHECK-NEXT:    lsr w8, w0, w1
99; CHECK-NEXT:    sub w9, w9, #1 // =1
100; CHECK-NEXT:    and w0, w8, w9
101; CHECK-NEXT:    ret
102  %shifted = lshr i32 %val, %numskipbits
103  %onebit = shl i32 1, %numlowbits
104  %mask = add nsw i32 %onebit, -1
105  %masked = and i32 %shifted, %mask ; swapped order
106  ret i32 %masked
107}
108
109; 64-bit
110
111define i64 @bextr64_a0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
112; CHECK-LABEL: bextr64_a0:
113; CHECK:       // %bb.0:
114; CHECK-NEXT:    orr w9, wzr, #0x1
115; CHECK-NEXT:    lsl x9, x9, x2
116; CHECK-NEXT:    lsr x8, x0, x1
117; CHECK-NEXT:    sub x9, x9, #1 // =1
118; CHECK-NEXT:    and x0, x9, x8
119; CHECK-NEXT:    ret
120  %shifted = lshr i64 %val, %numskipbits
121  %onebit = shl i64 1, %numlowbits
122  %mask = add nsw i64 %onebit, -1
123  %masked = and i64 %mask, %shifted
124  ret i64 %masked
125}
126
127define i64 @bextr64_a1_indexzext(i64 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
128; CHECK-LABEL: bextr64_a1_indexzext:
129; CHECK:       // %bb.0:
130; CHECK-NEXT:    orr w9, wzr, #0x1
131; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
132; CHECK-NEXT:    lsl x9, x9, x2
133; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
134; CHECK-NEXT:    lsr x8, x0, x1
135; CHECK-NEXT:    sub x9, x9, #1 // =1
136; CHECK-NEXT:    and x0, x9, x8
137; CHECK-NEXT:    ret
138  %skip = zext i8 %numskipbits to i64
139  %shifted = lshr i64 %val, %skip
140  %conv = zext i8 %numlowbits to i64
141  %onebit = shl i64 1, %conv
142  %mask = add nsw i64 %onebit, -1
143  %masked = and i64 %mask, %shifted
144  ret i64 %masked
145}
146
147define i64 @bextr64_a2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind {
148; CHECK-LABEL: bextr64_a2_load:
149; CHECK:       // %bb.0:
150; CHECK-NEXT:    ldr x8, [x0]
151; CHECK-NEXT:    orr w9, wzr, #0x1
152; CHECK-NEXT:    lsl x9, x9, x2
153; CHECK-NEXT:    sub x9, x9, #1 // =1
154; CHECK-NEXT:    lsr x8, x8, x1
155; CHECK-NEXT:    and x0, x9, x8
156; CHECK-NEXT:    ret
157  %val = load i64, i64* %w
158  %shifted = lshr i64 %val, %numskipbits
159  %onebit = shl i64 1, %numlowbits
160  %mask = add nsw i64 %onebit, -1
161  %masked = and i64 %mask, %shifted
162  ret i64 %masked
163}
164
165define i64 @bextr64_a3_load_indexzext(i64* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
166; CHECK-LABEL: bextr64_a3_load_indexzext:
167; CHECK:       // %bb.0:
168; CHECK-NEXT:    ldr x8, [x0]
169; CHECK-NEXT:    orr w9, wzr, #0x1
170; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
171; CHECK-NEXT:    lsl x9, x9, x2
172; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
173; CHECK-NEXT:    sub x9, x9, #1 // =1
174; CHECK-NEXT:    lsr x8, x8, x1
175; CHECK-NEXT:    and x0, x9, x8
176; CHECK-NEXT:    ret
177  %val = load i64, i64* %w
178  %skip = zext i8 %numskipbits to i64
179  %shifted = lshr i64 %val, %skip
180  %conv = zext i8 %numlowbits to i64
181  %onebit = shl i64 1, %conv
182  %mask = add nsw i64 %onebit, -1
183  %masked = and i64 %mask, %shifted
184  ret i64 %masked
185}
186
187define i64 @bextr64_a4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
188; CHECK-LABEL: bextr64_a4_commutative:
189; CHECK:       // %bb.0:
190; CHECK-NEXT:    orr w9, wzr, #0x1
191; CHECK-NEXT:    lsl x9, x9, x2
192; CHECK-NEXT:    lsr x8, x0, x1
193; CHECK-NEXT:    sub x9, x9, #1 // =1
194; CHECK-NEXT:    and x0, x8, x9
195; CHECK-NEXT:    ret
196  %shifted = lshr i64 %val, %numskipbits
197  %onebit = shl i64 1, %numlowbits
198  %mask = add nsw i64 %onebit, -1
199  %masked = and i64 %shifted, %mask ; swapped order
200  ret i64 %masked
201}
202
203; ---------------------------------------------------------------------------- ;
204; Pattern b. 32-bit
205; ---------------------------------------------------------------------------- ;
206
207define i32 @bextr32_b0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
208; CHECK-LABEL: bextr32_b0:
209; CHECK:       // %bb.0:
210; CHECK-NEXT:    mov w9, #-1
211; CHECK-NEXT:    lsr w8, w0, w1
212; CHECK-NEXT:    lsl w9, w9, w2
213; CHECK-NEXT:    bic w0, w8, w9
214; CHECK-NEXT:    ret
215  %shifted = lshr i32 %val, %numskipbits
216  %notmask = shl i32 -1, %numlowbits
217  %mask = xor i32 %notmask, -1
218  %masked = and i32 %mask, %shifted
219  ret i32 %masked
220}
221
222define i32 @bextr32_b1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
223; CHECK-LABEL: bextr32_b1_indexzext:
224; CHECK:       // %bb.0:
225; CHECK-NEXT:    mov w9, #-1
226; CHECK-NEXT:    lsr w8, w0, w1
227; CHECK-NEXT:    lsl w9, w9, w2
228; CHECK-NEXT:    bic w0, w8, w9
229; CHECK-NEXT:    ret
230  %skip = zext i8 %numskipbits to i32
231  %shifted = lshr i32 %val, %skip
232  %conv = zext i8 %numlowbits to i32
233  %notmask = shl i32 -1, %conv
234  %mask = xor i32 %notmask, -1
235  %masked = and i32 %mask, %shifted
236  ret i32 %masked
237}
238
239define i32 @bextr32_b2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind {
240; CHECK-LABEL: bextr32_b2_load:
241; CHECK:       // %bb.0:
242; CHECK-NEXT:    ldr w8, [x0]
243; CHECK-NEXT:    mov w9, #-1
244; CHECK-NEXT:    lsl w9, w9, w2
245; CHECK-NEXT:    lsr w8, w8, w1
246; CHECK-NEXT:    bic w0, w8, w9
247; CHECK-NEXT:    ret
248  %val = load i32, i32* %w
249  %shifted = lshr i32 %val, %numskipbits
250  %notmask = shl i32 -1, %numlowbits
251  %mask = xor i32 %notmask, -1
252  %masked = and i32 %mask, %shifted
253  ret i32 %masked
254}
255
256define i32 @bextr32_b3_load_indexzext(i32* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
257; CHECK-LABEL: bextr32_b3_load_indexzext:
258; CHECK:       // %bb.0:
259; CHECK-NEXT:    ldr w8, [x0]
260; CHECK-NEXT:    mov w9, #-1
261; CHECK-NEXT:    lsl w9, w9, w2
262; CHECK-NEXT:    lsr w8, w8, w1
263; CHECK-NEXT:    bic w0, w8, w9
264; CHECK-NEXT:    ret
265  %val = load i32, i32* %w
266  %skip = zext i8 %numskipbits to i32
267  %shifted = lshr i32 %val, %skip
268  %conv = zext i8 %numlowbits to i32
269  %notmask = shl i32 -1, %conv
270  %mask = xor i32 %notmask, -1
271  %masked = and i32 %mask, %shifted
272  ret i32 %masked
273}
274
275define i32 @bextr32_b4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
276; CHECK-LABEL: bextr32_b4_commutative:
277; CHECK:       // %bb.0:
278; CHECK-NEXT:    mov w9, #-1
279; CHECK-NEXT:    lsr w8, w0, w1
280; CHECK-NEXT:    lsl w9, w9, w2
281; CHECK-NEXT:    bic w0, w8, w9
282; CHECK-NEXT:    ret
283  %shifted = lshr i32 %val, %numskipbits
284  %notmask = shl i32 -1, %numlowbits
285  %mask = xor i32 %notmask, -1
286  %masked = and i32 %shifted, %mask ; swapped order
287  ret i32 %masked
288}
289
290; 64-bit
291
292define i64 @bextr64_b0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
293; CHECK-LABEL: bextr64_b0:
294; CHECK:       // %bb.0:
295; CHECK-NEXT:    mov x9, #-1
296; CHECK-NEXT:    lsr x8, x0, x1
297; CHECK-NEXT:    lsl x9, x9, x2
298; CHECK-NEXT:    bic x0, x8, x9
299; CHECK-NEXT:    ret
300  %shifted = lshr i64 %val, %numskipbits
301  %notmask = shl i64 -1, %numlowbits
302  %mask = xor i64 %notmask, -1
303  %masked = and i64 %mask, %shifted
304  ret i64 %masked
305}
306
307define i64 @bextr64_b1_indexzext(i64 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
308; CHECK-LABEL: bextr64_b1_indexzext:
309; CHECK:       // %bb.0:
310; CHECK-NEXT:    mov x9, #-1
311; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
312; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
313; CHECK-NEXT:    lsr x8, x0, x1
314; CHECK-NEXT:    lsl x9, x9, x2
315; CHECK-NEXT:    bic x0, x8, x9
316; CHECK-NEXT:    ret
317  %skip = zext i8 %numskipbits to i64
318  %shifted = lshr i64 %val, %skip
319  %conv = zext i8 %numlowbits to i64
320  %notmask = shl i64 -1, %conv
321  %mask = xor i64 %notmask, -1
322  %masked = and i64 %mask, %shifted
323  ret i64 %masked
324}
325
326define i64 @bextr64_b2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind {
327; CHECK-LABEL: bextr64_b2_load:
328; CHECK:       // %bb.0:
329; CHECK-NEXT:    ldr x8, [x0]
330; CHECK-NEXT:    mov x9, #-1
331; CHECK-NEXT:    lsl x9, x9, x2
332; CHECK-NEXT:    lsr x8, x8, x1
333; CHECK-NEXT:    bic x0, x8, x9
334; CHECK-NEXT:    ret
335  %val = load i64, i64* %w
336  %shifted = lshr i64 %val, %numskipbits
337  %notmask = shl i64 -1, %numlowbits
338  %mask = xor i64 %notmask, -1
339  %masked = and i64 %mask, %shifted
340  ret i64 %masked
341}
342
343define i64 @bextr64_b3_load_indexzext(i64* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind {
344; CHECK-LABEL: bextr64_b3_load_indexzext:
345; CHECK:       // %bb.0:
346; CHECK-NEXT:    ldr x8, [x0]
347; CHECK-NEXT:    mov x9, #-1
348; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
349; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
350; CHECK-NEXT:    lsl x9, x9, x2
351; CHECK-NEXT:    lsr x8, x8, x1
352; CHECK-NEXT:    bic x0, x8, x9
353; CHECK-NEXT:    ret
354  %val = load i64, i64* %w
355  %skip = zext i8 %numskipbits to i64
356  %shifted = lshr i64 %val, %skip
357  %conv = zext i8 %numlowbits to i64
358  %notmask = shl i64 -1, %conv
359  %mask = xor i64 %notmask, -1
360  %masked = and i64 %mask, %shifted
361  ret i64 %masked
362}
363
364define i64 @bextr64_b4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
365; CHECK-LABEL: bextr64_b4_commutative:
366; CHECK:       // %bb.0:
367; CHECK-NEXT:    mov x9, #-1
368; CHECK-NEXT:    lsr x8, x0, x1
369; CHECK-NEXT:    lsl x9, x9, x2
370; CHECK-NEXT:    bic x0, x8, x9
371; CHECK-NEXT:    ret
372  %shifted = lshr i64 %val, %numskipbits
373  %notmask = shl i64 -1, %numlowbits
374  %mask = xor i64 %notmask, -1
375  %masked = and i64 %shifted, %mask ; swapped order
376  ret i64 %masked
377}
378
379; ---------------------------------------------------------------------------- ;
380; Pattern c. 32-bit
381; ---------------------------------------------------------------------------- ;
382
383define i32 @bextr32_c0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
384; CHECK-LABEL: bextr32_c0:
385; CHECK:       // %bb.0:
386; CHECK-NEXT:    neg w9, w2
387; CHECK-NEXT:    mov w10, #-1
388; CHECK-NEXT:    lsr w8, w0, w1
389; CHECK-NEXT:    lsr w9, w10, w9
390; CHECK-NEXT:    and w0, w9, w8
391; CHECK-NEXT:    ret
392  %shifted = lshr i32 %val, %numskipbits
393  %numhighbits = sub i32 32, %numlowbits
394  %mask = lshr i32 -1, %numhighbits
395  %masked = and i32 %mask, %shifted
396  ret i32 %masked
397}
398
399define i32 @bextr32_c1_indexzext(i32 %val, i8 %numskipbits, i8 %numlowbits) nounwind {
400; CHECK-LABEL: bextr32_c1_indexzext:
401; CHECK:       // %bb.0:
402; CHECK-NEXT:    orr w9, wzr, #0x20
403; CHECK-NEXT:    sub w9, w9, w2
404; CHECK-NEXT:    mov w10, #-1
405; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
406; CHECK-NEXT:    lsr w8, w0, w1
407; CHECK-NEXT:    lsr w9, w10, w9
408; CHECK-NEXT:    and w0, w9, w8
409; CHECK-NEXT:    ret
410  %skip = zext i8 %numskipbits to i32
411  %shifted = lshr i32 %val, %skip
412  %numhighbits = sub i8 32, %numlowbits
413  %sh_prom = zext i8 %numhighbits to i32
414  %mask = lshr i32 -1, %sh_prom
415  %masked = and i32 %mask, %shifted
416  ret i32 %masked
417}
418
419define i32 @bextr32_c2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind {
420; CHECK-LABEL: bextr32_c2_load:
421; CHECK:       // %bb.0:
422; CHECK-NEXT:    ldr w8, [x0]
423; CHECK-NEXT:    neg w9, w2
424; CHECK-NEXT:    mov w10, #-1
425; CHECK-NEXT:    lsr w9, w10, w9
426; CHECK-NEXT:    lsr w8, w8, w1
427; CHECK-NEXT:    and w0, w9, w8
428; CHECK-NEXT:    ret
429  %val = load i32, i32* %w
430  %shifted = lshr i32 %val, %numskipbits
431  %numhighbits = sub i32 32, %numlowbits
432  %mask = lshr i32 -1, %numhighbits
433  %masked = and i32 %mask, %shifted
434  ret i32 %masked
435}
436
437define i32 @bextr32_c3_load_indexzext(i32* %w, i8 %numskipbits, i8 %numlowbits) nounwind {
438; CHECK-LABEL: bextr32_c3_load_indexzext:
439; CHECK:       // %bb.0:
440; CHECK-NEXT:    ldr w8, [x0]
441; CHECK-NEXT:    orr w9, wzr, #0x20
442; CHECK-NEXT:    mov w10, #-1
443; CHECK-NEXT:    sub w9, w9, w2
444; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
445; CHECK-NEXT:    lsr w8, w8, w1
446; CHECK-NEXT:    lsr w9, w10, w9
447; CHECK-NEXT:    and w0, w9, w8
448; CHECK-NEXT:    ret
449  %val = load i32, i32* %w
450  %skip = zext i8 %numskipbits to i32
451  %shifted = lshr i32 %val, %skip
452  %numhighbits = sub i8 32, %numlowbits
453  %sh_prom = zext i8 %numhighbits to i32
454  %mask = lshr i32 -1, %sh_prom
455  %masked = and i32 %mask, %shifted
456  ret i32 %masked
457}
458
459define i32 @bextr32_c4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
460; CHECK-LABEL: bextr32_c4_commutative:
461; CHECK:       // %bb.0:
462; CHECK-NEXT:    neg w9, w2
463; CHECK-NEXT:    mov w10, #-1
464; CHECK-NEXT:    lsr w8, w0, w1
465; CHECK-NEXT:    lsr w9, w10, w9
466; CHECK-NEXT:    and w0, w8, w9
467; CHECK-NEXT:    ret
468  %shifted = lshr i32 %val, %numskipbits
469  %numhighbits = sub i32 32, %numlowbits
470  %mask = lshr i32 -1, %numhighbits
471  %masked = and i32 %shifted, %mask ; swapped order
472  ret i32 %masked
473}
474
475; 64-bit
476
477define i64 @bextr64_c0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
478; CHECK-LABEL: bextr64_c0:
479; CHECK:       // %bb.0:
480; CHECK-NEXT:    neg x9, x2
481; CHECK-NEXT:    mov x10, #-1
482; CHECK-NEXT:    lsr x8, x0, x1
483; CHECK-NEXT:    lsr x9, x10, x9
484; CHECK-NEXT:    and x0, x9, x8
485; CHECK-NEXT:    ret
486  %shifted = lshr i64 %val, %numskipbits
487  %numhighbits = sub i64 64, %numlowbits
488  %mask = lshr i64 -1, %numhighbits
489  %masked = and i64 %mask, %shifted
490  ret i64 %masked
491}
492
493define i64 @bextr64_c1_indexzext(i64 %val, i8 %numskipbits, i8 %numlowbits) nounwind {
494; CHECK-LABEL: bextr64_c1_indexzext:
495; CHECK:       // %bb.0:
496; CHECK-NEXT:    orr w9, wzr, #0x40
497; CHECK-NEXT:    sub w9, w9, w2
498; CHECK-NEXT:    mov x10, #-1
499; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
500; CHECK-NEXT:    lsr x8, x0, x1
501; CHECK-NEXT:    lsr x9, x10, x9
502; CHECK-NEXT:    and x0, x9, x8
503; CHECK-NEXT:    ret
504  %skip = zext i8 %numskipbits to i64
505  %shifted = lshr i64 %val, %skip
506  %numhighbits = sub i8 64, %numlowbits
507  %sh_prom = zext i8 %numhighbits to i64
508  %mask = lshr i64 -1, %sh_prom
509  %masked = and i64 %mask, %shifted
510  ret i64 %masked
511}
512
513define i64 @bextr64_c2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind {
514; CHECK-LABEL: bextr64_c2_load:
515; CHECK:       // %bb.0:
516; CHECK-NEXT:    ldr x8, [x0]
517; CHECK-NEXT:    neg x9, x2
518; CHECK-NEXT:    mov x10, #-1
519; CHECK-NEXT:    lsr x9, x10, x9
520; CHECK-NEXT:    lsr x8, x8, x1
521; CHECK-NEXT:    and x0, x9, x8
522; CHECK-NEXT:    ret
523  %val = load i64, i64* %w
524  %shifted = lshr i64 %val, %numskipbits
525  %numhighbits = sub i64 64, %numlowbits
526  %mask = lshr i64 -1, %numhighbits
527  %masked = and i64 %mask, %shifted
528  ret i64 %masked
529}
530
531define i64 @bextr64_c3_load_indexzext(i64* %w, i8 %numskipbits, i8 %numlowbits) nounwind {
532; CHECK-LABEL: bextr64_c3_load_indexzext:
533; CHECK:       // %bb.0:
534; CHECK-NEXT:    ldr x8, [x0]
535; CHECK-NEXT:    orr w9, wzr, #0x40
536; CHECK-NEXT:    mov x10, #-1
537; CHECK-NEXT:    sub w9, w9, w2
538; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
539; CHECK-NEXT:    lsr x8, x8, x1
540; CHECK-NEXT:    lsr x9, x10, x9
541; CHECK-NEXT:    and x0, x9, x8
542; CHECK-NEXT:    ret
543  %val = load i64, i64* %w
544  %skip = zext i8 %numskipbits to i64
545  %shifted = lshr i64 %val, %skip
546  %numhighbits = sub i8 64, %numlowbits
547  %sh_prom = zext i8 %numhighbits to i64
548  %mask = lshr i64 -1, %sh_prom
549  %masked = and i64 %mask, %shifted
550  ret i64 %masked
551}
552
553define i64 @bextr64_c4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
554; CHECK-LABEL: bextr64_c4_commutative:
555; CHECK:       // %bb.0:
556; CHECK-NEXT:    neg x9, x2
557; CHECK-NEXT:    mov x10, #-1
558; CHECK-NEXT:    lsr x8, x0, x1
559; CHECK-NEXT:    lsr x9, x10, x9
560; CHECK-NEXT:    and x0, x8, x9
561; CHECK-NEXT:    ret
562  %shifted = lshr i64 %val, %numskipbits
563  %numhighbits = sub i64 64, %numlowbits
564  %mask = lshr i64 -1, %numhighbits
565  %masked = and i64 %shifted, %mask ; swapped order
566  ret i64 %masked
567}
568
569; ---------------------------------------------------------------------------- ;
570; Pattern d. 32-bit.
571; ---------------------------------------------------------------------------- ;
572
573define i32 @bextr32_d0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
574; CHECK-LABEL: bextr32_d0:
575; CHECK:       // %bb.0:
576; CHECK-NEXT:    lsr w8, w0, w1
577; CHECK-NEXT:    neg w9, w2
578; CHECK-NEXT:    lsl w8, w8, w9
579; CHECK-NEXT:    lsr w0, w8, w9
580; CHECK-NEXT:    ret
581  %shifted = lshr i32 %val, %numskipbits
582  %numhighbits = sub i32 32, %numlowbits
583  %highbitscleared = shl i32 %shifted, %numhighbits
584  %masked = lshr i32 %highbitscleared, %numhighbits
585  ret i32 %masked
586}
587
588define i32 @bextr32_d1_indexzext(i32 %val, i8 %numskipbits, i8 %numlowbits) nounwind {
589; CHECK-LABEL: bextr32_d1_indexzext:
590; CHECK:       // %bb.0:
591; CHECK-NEXT:    orr w9, wzr, #0x20
592; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
593; CHECK-NEXT:    lsr w8, w0, w1
594; CHECK-NEXT:    sub w9, w9, w2
595; CHECK-NEXT:    lsl w8, w8, w9
596; CHECK-NEXT:    lsr w0, w8, w9
597; CHECK-NEXT:    ret
598  %skip = zext i8 %numskipbits to i32
599  %shifted = lshr i32 %val, %skip
600  %numhighbits = sub i8 32, %numlowbits
601  %sh_prom = zext i8 %numhighbits to i32
602  %highbitscleared = shl i32 %shifted, %sh_prom
603  %masked = lshr i32 %highbitscleared, %sh_prom
604  ret i32 %masked
605}
606
607define i32 @bextr32_d2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind {
608; CHECK-LABEL: bextr32_d2_load:
609; CHECK:       // %bb.0:
610; CHECK-NEXT:    ldr w8, [x0]
611; CHECK-NEXT:    neg w9, w2
612; CHECK-NEXT:    lsr w8, w8, w1
613; CHECK-NEXT:    lsl w8, w8, w9
614; CHECK-NEXT:    lsr w0, w8, w9
615; CHECK-NEXT:    ret
616  %val = load i32, i32* %w
617  %shifted = lshr i32 %val, %numskipbits
618  %numhighbits = sub i32 32, %numlowbits
619  %highbitscleared = shl i32 %shifted, %numhighbits
620  %masked = lshr i32 %highbitscleared, %numhighbits
621  ret i32 %masked
622}
623
624define i32 @bextr32_d3_load_indexzext(i32* %w, i8 %numskipbits, i8 %numlowbits) nounwind {
625; CHECK-LABEL: bextr32_d3_load_indexzext:
626; CHECK:       // %bb.0:
627; CHECK-NEXT:    ldr w8, [x0]
628; CHECK-NEXT:    orr w9, wzr, #0x20
629; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
630; CHECK-NEXT:    sub w9, w9, w2
631; CHECK-NEXT:    lsr w8, w8, w1
632; CHECK-NEXT:    lsl w8, w8, w9
633; CHECK-NEXT:    lsr w0, w8, w9
634; CHECK-NEXT:    ret
635  %val = load i32, i32* %w
636  %skip = zext i8 %numskipbits to i32
637  %shifted = lshr i32 %val, %skip
638  %numhighbits = sub i8 32, %numlowbits
639  %sh_prom = zext i8 %numhighbits to i32
640  %highbitscleared = shl i32 %shifted, %sh_prom
641  %masked = lshr i32 %highbitscleared, %sh_prom
642  ret i32 %masked
643}
644
645; 64-bit.
646
647define i64 @bextr64_d0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind {
648; CHECK-LABEL: bextr64_d0:
649; CHECK:       // %bb.0:
650; CHECK-NEXT:    lsr x8, x0, x1
651; CHECK-NEXT:    neg x9, x2
652; CHECK-NEXT:    lsl x8, x8, x9
653; CHECK-NEXT:    lsr x0, x8, x9
654; CHECK-NEXT:    ret
655  %shifted = lshr i64 %val, %numskipbits
656  %numhighbits = sub i64 64, %numlowbits
657  %highbitscleared = shl i64 %shifted, %numhighbits
658  %masked = lshr i64 %highbitscleared, %numhighbits
659  ret i64 %masked
660}
661
662define i64 @bextr64_d1_indexzext(i64 %val, i8 %numskipbits, i8 %numlowbits) nounwind {
663; CHECK-LABEL: bextr64_d1_indexzext:
664; CHECK:       // %bb.0:
665; CHECK-NEXT:    orr w9, wzr, #0x40
666; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
667; CHECK-NEXT:    lsr x8, x0, x1
668; CHECK-NEXT:    sub w9, w9, w2
669; CHECK-NEXT:    lsl x8, x8, x9
670; CHECK-NEXT:    lsr x0, x8, x9
671; CHECK-NEXT:    ret
672  %skip = zext i8 %numskipbits to i64
673  %shifted = lshr i64 %val, %skip
674  %numhighbits = sub i8 64, %numlowbits
675  %sh_prom = zext i8 %numhighbits to i64
676  %highbitscleared = shl i64 %shifted, %sh_prom
677  %masked = lshr i64 %highbitscleared, %sh_prom
678  ret i64 %masked
679}
680
681define i64 @bextr64_d2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind {
682; CHECK-LABEL: bextr64_d2_load:
683; CHECK:       // %bb.0:
684; CHECK-NEXT:    ldr x8, [x0]
685; CHECK-NEXT:    neg x9, x2
686; CHECK-NEXT:    lsr x8, x8, x1
687; CHECK-NEXT:    lsl x8, x8, x9
688; CHECK-NEXT:    lsr x0, x8, x9
689; CHECK-NEXT:    ret
690  %val = load i64, i64* %w
691  %shifted = lshr i64 %val, %numskipbits
692  %numhighbits = sub i64 64, %numlowbits
693  %highbitscleared = shl i64 %shifted, %numhighbits
694  %masked = lshr i64 %highbitscleared, %numhighbits
695  ret i64 %masked
696}
697
698define i64 @bextr64_d3_load_indexzext(i64* %w, i8 %numskipbits, i8 %numlowbits) nounwind {
699; CHECK-LABEL: bextr64_d3_load_indexzext:
700; CHECK:       // %bb.0:
701; CHECK-NEXT:    ldr x8, [x0]
702; CHECK-NEXT:    orr w9, wzr, #0x40
703; CHECK-NEXT:    // kill: def $w1 killed $w1 def $x1
704; CHECK-NEXT:    sub w9, w9, w2
705; CHECK-NEXT:    lsr x8, x8, x1
706; CHECK-NEXT:    lsl x8, x8, x9
707; CHECK-NEXT:    lsr x0, x8, x9
708; CHECK-NEXT:    ret
709  %val = load i64, i64* %w
710  %skip = zext i8 %numskipbits to i64
711  %shifted = lshr i64 %val, %skip
712  %numhighbits = sub i8 64, %numlowbits
713  %sh_prom = zext i8 %numhighbits to i64
714  %highbitscleared = shl i64 %shifted, %sh_prom
715  %masked = lshr i64 %highbitscleared, %sh_prom
716  ret i64 %masked
717}
718
719; ---------------------------------------------------------------------------- ;
720; Constant
721; ---------------------------------------------------------------------------- ;
722
723; https://bugs.llvm.org/show_bug.cgi?id=38938
724define void @pr38938(i32* %a0, i64* %a1) {
725; CHECK-LABEL: pr38938:
726; CHECK:       // %bb.0:
727; CHECK-NEXT:    ldr x8, [x1]
728; CHECK-NEXT:    ubfx x8, x8, #21, #10
729; CHECK-NEXT:    lsl x8, x8, #2
730; CHECK-NEXT:    ldr w9, [x0, x8]
731; CHECK-NEXT:    add w9, w9, #1 // =1
732; CHECK-NEXT:    str w9, [x0, x8]
733; CHECK-NEXT:    ret
734  %tmp = load i64, i64* %a1, align 8
735  %tmp1 = lshr i64 %tmp, 21
736  %tmp2 = and i64 %tmp1, 1023
737  %tmp3 = getelementptr inbounds i32, i32* %a0, i64 %tmp2
738  %tmp4 = load i32, i32* %tmp3, align 4
739  %tmp5 = add nsw i32 %tmp4, 1
740  store i32 %tmp5, i32* %tmp3, align 4
741  ret void
742}
743
744; The most canonical variant
745define i32 @c0_i32(i32 %arg) {
746; CHECK-LABEL: c0_i32:
747; CHECK:       // %bb.0:
748; CHECK-NEXT:    ubfx w0, w0, #19, #10
749; CHECK-NEXT:    ret
750  %tmp0 = lshr i32 %arg, 19
751  %tmp1 = and i32 %tmp0, 1023
752  ret i32 %tmp1
753}
754
755; Should be still fine, but the mask is shifted
756define i32 @c1_i32(i32 %arg) {
757; CHECK-LABEL: c1_i32:
758; CHECK:       // %bb.0:
759; CHECK-NEXT:    lsr w8, w0, #19
760; CHECK-NEXT:    and w0, w8, #0xffc
761; CHECK-NEXT:    ret
762  %tmp0 = lshr i32 %arg, 19
763  %tmp1 = and i32 %tmp0, 4092
764  ret i32 %tmp1
765}
766
767; Should be still fine, but the result is shifted left afterwards
768define i32 @c2_i32(i32 %arg) {
769; CHECK-LABEL: c2_i32:
770; CHECK:       // %bb.0:
771; CHECK-NEXT:    ubfx w8, w0, #19, #10
772; CHECK-NEXT:    lsl w0, w8, #2
773; CHECK-NEXT:    ret
774  %tmp0 = lshr i32 %arg, 19
775  %tmp1 = and i32 %tmp0, 1023
776  %tmp2 = shl i32 %tmp1, 2
777  ret i32 %tmp2
778}
779
780; The mask covers newly shifted-in bit
781define i32 @c4_i32_bad(i32 %arg) {
782; CHECK-LABEL: c4_i32_bad:
783; CHECK:       // %bb.0:
784; CHECK-NEXT:    lsr w8, w0, #19
785; CHECK-NEXT:    and w0, w8, #0x1ffe
786; CHECK-NEXT:    ret
787  %tmp0 = lshr i32 %arg, 19
788  %tmp1 = and i32 %tmp0, 16382
789  ret i32 %tmp1
790}
791
792; i64
793
794; The most canonical variant
795define i64 @c0_i64(i64 %arg) {
796; CHECK-LABEL: c0_i64:
797; CHECK:       // %bb.0:
798; CHECK-NEXT:    ubfx x0, x0, #51, #10
799; CHECK-NEXT:    ret
800  %tmp0 = lshr i64 %arg, 51
801  %tmp1 = and i64 %tmp0, 1023
802  ret i64 %tmp1
803}
804
805; Should be still fine, but the mask is shifted
806define i64 @c1_i64(i64 %arg) {
807; CHECK-LABEL: c1_i64:
808; CHECK:       // %bb.0:
809; CHECK-NEXT:    lsr x8, x0, #51
810; CHECK-NEXT:    and x0, x8, #0xffc
811; CHECK-NEXT:    ret
812  %tmp0 = lshr i64 %arg, 51
813  %tmp1 = and i64 %tmp0, 4092
814  ret i64 %tmp1
815}
816
817; Should be still fine, but the result is shifted left afterwards
818define i64 @c2_i64(i64 %arg) {
819; CHECK-LABEL: c2_i64:
820; CHECK:       // %bb.0:
821; CHECK-NEXT:    ubfx x8, x0, #51, #10
822; CHECK-NEXT:    lsl x0, x8, #2
823; CHECK-NEXT:    ret
824  %tmp0 = lshr i64 %arg, 51
825  %tmp1 = and i64 %tmp0, 1023
826  %tmp2 = shl i64 %tmp1, 2
827  ret i64 %tmp2
828}
829
830; The mask covers newly shifted-in bit
831define i64 @c4_i64_bad(i64 %arg) {
832; CHECK-LABEL: c4_i64_bad:
833; CHECK:       // %bb.0:
834; CHECK-NEXT:    lsr x8, x0, #51
835; CHECK-NEXT:    and x0, x8, #0x1ffe
836; CHECK-NEXT:    ret
837  %tmp0 = lshr i64 %arg, 51
838  %tmp1 = and i64 %tmp0, 16382
839  ret i64 %tmp1
840}
841
842; ---------------------------------------------------------------------------- ;
843; Constant, storing the result afterwards.
844; ---------------------------------------------------------------------------- ;
845
846; i32
847
848; The most canonical variant
849define void @c5_i32(i32 %arg, i32* %ptr) {
850; CHECK-LABEL: c5_i32:
851; CHECK:       // %bb.0:
852; CHECK-NEXT:    ubfx w8, w0, #19, #10
853; CHECK-NEXT:    str w8, [x1]
854; CHECK-NEXT:    ret
855  %tmp0 = lshr i32 %arg, 19
856  %tmp1 = and i32 %tmp0, 1023
857  store i32 %tmp1, i32* %ptr
858  ret void
859}
860
861; Should be still fine, but the mask is shifted
862define void @c6_i32(i32 %arg, i32* %ptr) {
863; CHECK-LABEL: c6_i32:
864; CHECK:       // %bb.0:
865; CHECK-NEXT:    ubfx w8, w0, #19, #12
866; CHECK-NEXT:    str w8, [x1]
867; CHECK-NEXT:    ret
868  %tmp0 = lshr i32 %arg, 19
869  %tmp1 = and i32 %tmp0, 4095
870  store i32 %tmp1, i32* %ptr
871  ret void
872}
873
874; Should be still fine, but the result is shifted left afterwards
875define void @c7_i32(i32 %arg, i32* %ptr) {
876; CHECK-LABEL: c7_i32:
877; CHECK:       // %bb.0:
878; CHECK-NEXT:    ubfx w8, w0, #19, #10
879; CHECK-NEXT:    lsl w8, w8, #2
880; CHECK-NEXT:    str w8, [x1]
881; CHECK-NEXT:    ret
882  %tmp0 = lshr i32 %arg, 19
883  %tmp1 = and i32 %tmp0, 1023
884  %tmp2 = shl i32 %tmp1, 2
885  store i32 %tmp2, i32* %ptr
886  ret void
887}
888
889; i64
890
891; The most canonical variant
892define void @c5_i64(i64 %arg, i64* %ptr) {
893; CHECK-LABEL: c5_i64:
894; CHECK:       // %bb.0:
895; CHECK-NEXT:    ubfx x8, x0, #51, #10
896; CHECK-NEXT:    str x8, [x1]
897; CHECK-NEXT:    ret
898  %tmp0 = lshr i64 %arg, 51
899  %tmp1 = and i64 %tmp0, 1023
900  store i64 %tmp1, i64* %ptr
901  ret void
902}
903
904; Should be still fine, but the mask is shifted
905define void @c6_i64(i64 %arg, i64* %ptr) {
906; CHECK-LABEL: c6_i64:
907; CHECK:       // %bb.0:
908; CHECK-NEXT:    ubfx x8, x0, #51, #12
909; CHECK-NEXT:    str x8, [x1]
910; CHECK-NEXT:    ret
911  %tmp0 = lshr i64 %arg, 51
912  %tmp1 = and i64 %tmp0, 4095
913  store i64 %tmp1, i64* %ptr
914  ret void
915}
916
917; Should be still fine, but the result is shifted left afterwards
918define void @c7_i64(i64 %arg, i64* %ptr) {
919; CHECK-LABEL: c7_i64:
920; CHECK:       // %bb.0:
921; CHECK-NEXT:    ubfx x8, x0, #51, #10
922; CHECK-NEXT:    lsl x8, x8, #2
923; CHECK-NEXT:    str x8, [x1]
924; CHECK-NEXT:    ret
925  %tmp0 = lshr i64 %arg, 51
926  %tmp1 = and i64 %tmp0, 1023
927  %tmp2 = shl i64 %tmp1, 2
928  store i64 %tmp2, i64* %ptr
929  ret void
930}
931