blob: e669a5d9cf7497b990be225cf760dd6eaef0058f [file] [log] [blame]
Roman Lebedevcb56f7a2018-06-06 19:38:10 +00001; 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: orr w8, wzr, #0x1
25; CHECK-NEXT: lsl w8, w8, w1
26; CHECK-NEXT: sub w8, w8, #1 // =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: orr w8, wzr, #0x1
39; CHECK-NEXT: lsl w8, w8, w1
40; CHECK-NEXT: sub w8, w8, #1 // =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(i32* %w, i32 %numlowbits) nounwind {
51; CHECK-LABEL: bzhi32_a2_load:
52; CHECK: // %bb.0:
53; CHECK-NEXT: ldr w8, [x0]
54; CHECK-NEXT: orr w9, wzr, #0x1
55; CHECK-NEXT: lsl w9, w9, w1
56; CHECK-NEXT: sub w9, w9, #1 // =1
57; CHECK-NEXT: and w0, w9, w8
58; CHECK-NEXT: ret
59 %val = load i32, i32* %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(i32* %w, i8 zeroext %numlowbits) nounwind {
67; CHECK-LABEL: bzhi32_a3_load_indexzext:
68; CHECK: // %bb.0:
69; CHECK-NEXT: ldr w8, [x0]
70; CHECK-NEXT: orr w9, wzr, #0x1
71; CHECK-NEXT: lsl w9, w9, w1
72; CHECK-NEXT: sub w9, w9, #1 // =1
73; CHECK-NEXT: and w0, w9, w8
74; CHECK-NEXT: ret
75 %val = load i32, i32* %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: orr w8, wzr, #0x1
87; CHECK-NEXT: lsl w8, w8, w1
88; CHECK-NEXT: sub w8, w8, #1 // =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: orr w8, wzr, #0x1
103; CHECK-NEXT: lsl x8, x8, x1
104; CHECK-NEXT: sub x8, x8, #1 // =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
113define i64 @bzhi64_a1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind {
114; CHECK-LABEL: bzhi64_a1_indexzext:
115; CHECK: // %bb.0:
116; CHECK-NEXT: orr w8, wzr, #0x1
117; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
118; CHECK-NEXT: lsl x8, x8, x1
119; CHECK-NEXT: sub x8, x8, #1 // =1
120; CHECK-NEXT: and x0, x8, x0
121; CHECK-NEXT: ret
122 %conv = zext i8 %numlowbits to i64
123 %onebit = shl i64 1, %conv
124 %mask = add nsw i64 %onebit, -1
125 %masked = and i64 %mask, %val
126 ret i64 %masked
127}
128
129define i64 @bzhi64_a2_load(i64* %w, i64 %numlowbits) nounwind {
130; CHECK-LABEL: bzhi64_a2_load:
131; CHECK: // %bb.0:
132; CHECK-NEXT: ldr x8, [x0]
133; CHECK-NEXT: orr w9, wzr, #0x1
134; CHECK-NEXT: lsl x9, x9, x1
135; CHECK-NEXT: sub x9, x9, #1 // =1
136; CHECK-NEXT: and x0, x9, x8
137; CHECK-NEXT: ret
138 %val = load i64, i64* %w
139 %onebit = shl i64 1, %numlowbits
140 %mask = add nsw i64 %onebit, -1
141 %masked = and i64 %mask, %val
142 ret i64 %masked
143}
144
145define i64 @bzhi64_a3_load_indexzext(i64* %w, i8 zeroext %numlowbits) nounwind {
146; CHECK-LABEL: bzhi64_a3_load_indexzext:
147; CHECK: // %bb.0:
148; CHECK-NEXT: ldr x8, [x0]
149; CHECK-NEXT: orr w9, wzr, #0x1
150; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
151; CHECK-NEXT: lsl x9, x9, x1
152; CHECK-NEXT: sub x9, x9, #1 // =1
153; CHECK-NEXT: and x0, x9, x8
154; CHECK-NEXT: ret
155 %val = load i64, i64* %w
156 %conv = zext i8 %numlowbits to i64
157 %onebit = shl i64 1, %conv
158 %mask = add nsw i64 %onebit, -1
159 %masked = and i64 %mask, %val
160 ret i64 %masked
161}
162
163define i64 @bzhi64_a4_commutative(i64 %val, i64 %numlowbits) nounwind {
164; CHECK-LABEL: bzhi64_a4_commutative:
165; CHECK: // %bb.0:
166; CHECK-NEXT: orr w8, wzr, #0x1
167; CHECK-NEXT: lsl x8, x8, x1
168; CHECK-NEXT: sub x8, x8, #1 // =1
169; CHECK-NEXT: and x0, x0, x8
170; CHECK-NEXT: ret
171 %onebit = shl i64 1, %numlowbits
172 %mask = add nsw i64 %onebit, -1
173 %masked = and i64 %val, %mask ; swapped order
174 ret i64 %masked
175}
176
177; ---------------------------------------------------------------------------- ;
178; Pattern b. 32-bit
179; ---------------------------------------------------------------------------- ;
180
181define i32 @bzhi32_b0(i32 %val, i32 %numlowbits) nounwind {
182; CHECK-LABEL: bzhi32_b0:
183; CHECK: // %bb.0:
184; CHECK-NEXT: mov w8, #-1
185; CHECK-NEXT: lsl w8, w8, w1
186; CHECK-NEXT: bic w0, w0, w8
187; CHECK-NEXT: ret
188 %notmask = shl i32 -1, %numlowbits
189 %mask = xor i32 %notmask, -1
190 %masked = and i32 %mask, %val
191 ret i32 %masked
192}
193
194define i32 @bzhi32_b1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind {
195; CHECK-LABEL: bzhi32_b1_indexzext:
196; CHECK: // %bb.0:
197; CHECK-NEXT: mov w8, #-1
198; CHECK-NEXT: lsl w8, w8, w1
199; CHECK-NEXT: bic w0, w0, w8
200; CHECK-NEXT: ret
201 %conv = zext i8 %numlowbits to i32
202 %notmask = shl i32 -1, %conv
203 %mask = xor i32 %notmask, -1
204 %masked = and i32 %mask, %val
205 ret i32 %masked
206}
207
208define i32 @bzhi32_b2_load(i32* %w, i32 %numlowbits) nounwind {
209; CHECK-LABEL: bzhi32_b2_load:
210; CHECK: // %bb.0:
211; CHECK-NEXT: ldr w8, [x0]
212; CHECK-NEXT: mov w9, #-1
213; CHECK-NEXT: lsl w9, w9, w1
214; CHECK-NEXT: bic w0, w8, w9
215; CHECK-NEXT: ret
216 %val = load i32, i32* %w
217 %notmask = shl i32 -1, %numlowbits
218 %mask = xor i32 %notmask, -1
219 %masked = and i32 %mask, %val
220 ret i32 %masked
221}
222
223define i32 @bzhi32_b3_load_indexzext(i32* %w, i8 zeroext %numlowbits) nounwind {
224; CHECK-LABEL: bzhi32_b3_load_indexzext:
225; CHECK: // %bb.0:
226; CHECK-NEXT: ldr w8, [x0]
227; CHECK-NEXT: mov w9, #-1
228; CHECK-NEXT: lsl w9, w9, w1
229; CHECK-NEXT: bic w0, w8, w9
230; CHECK-NEXT: ret
231 %val = load i32, i32* %w
232 %conv = zext i8 %numlowbits to i32
233 %notmask = shl i32 -1, %conv
234 %mask = xor i32 %notmask, -1
235 %masked = and i32 %mask, %val
236 ret i32 %masked
237}
238
239define i32 @bzhi32_b4_commutative(i32 %val, i32 %numlowbits) nounwind {
240; CHECK-LABEL: bzhi32_b4_commutative:
241; CHECK: // %bb.0:
242; CHECK-NEXT: mov w8, #-1
243; CHECK-NEXT: lsl w8, w8, w1
244; CHECK-NEXT: bic w0, w0, w8
245; CHECK-NEXT: ret
246 %notmask = shl i32 -1, %numlowbits
247 %mask = xor i32 %notmask, -1
248 %masked = and i32 %val, %mask ; swapped order
249 ret i32 %masked
250}
251
252; 64-bit
253
254define i64 @bzhi64_b0(i64 %val, i64 %numlowbits) nounwind {
255; CHECK-LABEL: bzhi64_b0:
256; CHECK: // %bb.0:
257; CHECK-NEXT: mov x8, #-1
258; CHECK-NEXT: lsl x8, x8, x1
259; CHECK-NEXT: bic x0, x0, x8
260; CHECK-NEXT: ret
261 %notmask = shl i64 -1, %numlowbits
262 %mask = xor i64 %notmask, -1
263 %masked = and i64 %mask, %val
264 ret i64 %masked
265}
266
267define i64 @bzhi64_b1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind {
268; CHECK-LABEL: bzhi64_b1_indexzext:
269; CHECK: // %bb.0:
270; CHECK-NEXT: mov x8, #-1
271; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
272; CHECK-NEXT: lsl x8, x8, x1
273; CHECK-NEXT: bic x0, x0, x8
274; CHECK-NEXT: ret
275 %conv = zext i8 %numlowbits to i64
276 %notmask = shl i64 -1, %conv
277 %mask = xor i64 %notmask, -1
278 %masked = and i64 %mask, %val
279 ret i64 %masked
280}
281
282define i64 @bzhi64_b2_load(i64* %w, i64 %numlowbits) nounwind {
283; CHECK-LABEL: bzhi64_b2_load:
284; CHECK: // %bb.0:
285; CHECK-NEXT: ldr x8, [x0]
286; CHECK-NEXT: mov x9, #-1
287; CHECK-NEXT: lsl x9, x9, x1
288; CHECK-NEXT: bic x0, x8, x9
289; CHECK-NEXT: ret
290 %val = load i64, i64* %w
291 %notmask = shl i64 -1, %numlowbits
292 %mask = xor i64 %notmask, -1
293 %masked = and i64 %mask, %val
294 ret i64 %masked
295}
296
297define i64 @bzhi64_b3_load_indexzext(i64* %w, i8 zeroext %numlowbits) nounwind {
298; CHECK-LABEL: bzhi64_b3_load_indexzext:
299; CHECK: // %bb.0:
300; CHECK-NEXT: ldr x8, [x0]
301; CHECK-NEXT: mov x9, #-1
302; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
303; CHECK-NEXT: lsl x9, x9, x1
304; CHECK-NEXT: bic x0, x8, x9
305; CHECK-NEXT: ret
306 %val = load i64, i64* %w
307 %conv = zext i8 %numlowbits to i64
308 %notmask = shl i64 -1, %conv
309 %mask = xor i64 %notmask, -1
310 %masked = and i64 %mask, %val
311 ret i64 %masked
312}
313
314define i64 @bzhi64_b4_commutative(i64 %val, i64 %numlowbits) nounwind {
315; CHECK-LABEL: bzhi64_b4_commutative:
316; CHECK: // %bb.0:
317; CHECK-NEXT: mov x8, #-1
318; CHECK-NEXT: lsl x8, x8, x1
319; CHECK-NEXT: bic x0, x0, x8
320; CHECK-NEXT: ret
321 %notmask = shl i64 -1, %numlowbits
322 %mask = xor i64 %notmask, -1
323 %masked = and i64 %val, %mask ; swapped order
324 ret i64 %masked
325}
326
327; ---------------------------------------------------------------------------- ;
328; Pattern c. 32-bit
329; ---------------------------------------------------------------------------- ;
330
331define i32 @bzhi32_c0(i32 %val, i32 %numlowbits) nounwind {
332; CHECK-LABEL: bzhi32_c0:
333; CHECK: // %bb.0:
334; CHECK-NEXT: neg w8, w1
335; CHECK-NEXT: mov w9, #-1
336; CHECK-NEXT: lsr w8, w9, w8
337; CHECK-NEXT: and w0, w8, w0
338; CHECK-NEXT: ret
339 %numhighbits = sub i32 32, %numlowbits
340 %mask = lshr i32 -1, %numhighbits
341 %masked = and i32 %mask, %val
342 ret i32 %masked
343}
344
345define i32 @bzhi32_c1_indexzext(i32 %val, i8 %numlowbits) nounwind {
346; CHECK-LABEL: bzhi32_c1_indexzext:
347; CHECK: // %bb.0:
348; CHECK-NEXT: orr w8, wzr, #0x20
349; CHECK-NEXT: sub w8, w8, w1
350; CHECK-NEXT: mov w9, #-1
351; CHECK-NEXT: lsr w8, w9, w8
352; CHECK-NEXT: and w0, w8, w0
353; CHECK-NEXT: ret
354 %numhighbits = sub i8 32, %numlowbits
355 %sh_prom = zext i8 %numhighbits to i32
356 %mask = lshr i32 -1, %sh_prom
357 %masked = and i32 %mask, %val
358 ret i32 %masked
359}
360
361define i32 @bzhi32_c2_load(i32* %w, i32 %numlowbits) nounwind {
362; CHECK-LABEL: bzhi32_c2_load:
363; CHECK: // %bb.0:
364; CHECK-NEXT: ldr w8, [x0]
365; CHECK-NEXT: neg w9, w1
366; CHECK-NEXT: mov w10, #-1
367; CHECK-NEXT: lsr w9, w10, w9
368; CHECK-NEXT: and w0, w9, w8
369; CHECK-NEXT: ret
370 %val = load i32, i32* %w
371 %numhighbits = sub i32 32, %numlowbits
372 %mask = lshr i32 -1, %numhighbits
373 %masked = and i32 %mask, %val
374 ret i32 %masked
375}
376
377define i32 @bzhi32_c3_load_indexzext(i32* %w, i8 %numlowbits) nounwind {
378; CHECK-LABEL: bzhi32_c3_load_indexzext:
379; CHECK: // %bb.0:
380; CHECK-NEXT: ldr w8, [x0]
381; CHECK-NEXT: orr w9, wzr, #0x20
382; CHECK-NEXT: sub w9, w9, w1
383; CHECK-NEXT: mov w10, #-1
384; CHECK-NEXT: lsr w9, w10, w9
385; CHECK-NEXT: and w0, w9, w8
386; CHECK-NEXT: ret
387 %val = load i32, i32* %w
388 %numhighbits = sub i8 32, %numlowbits
389 %sh_prom = zext i8 %numhighbits to i32
390 %mask = lshr i32 -1, %sh_prom
391 %masked = and i32 %mask, %val
392 ret i32 %masked
393}
394
395define i32 @bzhi32_c4_commutative(i32 %val, i32 %numlowbits) nounwind {
396; CHECK-LABEL: bzhi32_c4_commutative:
397; CHECK: // %bb.0:
398; CHECK-NEXT: neg w8, w1
399; CHECK-NEXT: mov w9, #-1
400; CHECK-NEXT: lsr w8, w9, w8
401; CHECK-NEXT: and w0, w0, w8
402; CHECK-NEXT: ret
403 %numhighbits = sub i32 32, %numlowbits
404 %mask = lshr i32 -1, %numhighbits
405 %masked = and i32 %val, %mask ; swapped order
406 ret i32 %masked
407}
408
409; 64-bit
410
411define i64 @bzhi64_c0(i64 %val, i64 %numlowbits) nounwind {
412; CHECK-LABEL: bzhi64_c0:
413; CHECK: // %bb.0:
414; CHECK-NEXT: neg x8, x1
415; CHECK-NEXT: mov x9, #-1
416; CHECK-NEXT: lsr x8, x9, x8
417; CHECK-NEXT: and x0, x8, x0
418; CHECK-NEXT: ret
419 %numhighbits = sub i64 64, %numlowbits
420 %mask = lshr i64 -1, %numhighbits
421 %masked = and i64 %mask, %val
422 ret i64 %masked
423}
424
425define i64 @bzhi64_c1_indexzext(i64 %val, i8 %numlowbits) nounwind {
426; CHECK-LABEL: bzhi64_c1_indexzext:
427; CHECK: // %bb.0:
428; CHECK-NEXT: orr w8, wzr, #0x40
429; CHECK-NEXT: sub w8, w8, w1
430; CHECK-NEXT: mov x9, #-1
431; CHECK-NEXT: lsr x8, x9, x8
432; CHECK-NEXT: and x0, x8, x0
433; CHECK-NEXT: ret
434 %numhighbits = sub i8 64, %numlowbits
435 %sh_prom = zext i8 %numhighbits to i64
436 %mask = lshr i64 -1, %sh_prom
437 %masked = and i64 %mask, %val
438 ret i64 %masked
439}
440
441define i64 @bzhi64_c2_load(i64* %w, i64 %numlowbits) nounwind {
442; CHECK-LABEL: bzhi64_c2_load:
443; CHECK: // %bb.0:
444; CHECK-NEXT: ldr x8, [x0]
445; CHECK-NEXT: neg x9, x1
446; CHECK-NEXT: mov x10, #-1
447; CHECK-NEXT: lsr x9, x10, x9
448; CHECK-NEXT: and x0, x9, x8
449; CHECK-NEXT: ret
450 %val = load i64, i64* %w
451 %numhighbits = sub i64 64, %numlowbits
452 %mask = lshr i64 -1, %numhighbits
453 %masked = and i64 %mask, %val
454 ret i64 %masked
455}
456
457define i64 @bzhi64_c3_load_indexzext(i64* %w, i8 %numlowbits) nounwind {
458; CHECK-LABEL: bzhi64_c3_load_indexzext:
459; CHECK: // %bb.0:
460; CHECK-NEXT: ldr x8, [x0]
461; CHECK-NEXT: orr w9, wzr, #0x40
462; CHECK-NEXT: sub w9, w9, w1
463; CHECK-NEXT: mov x10, #-1
464; CHECK-NEXT: lsr x9, x10, x9
465; CHECK-NEXT: and x0, x9, x8
466; CHECK-NEXT: ret
467 %val = load i64, i64* %w
468 %numhighbits = sub i8 64, %numlowbits
469 %sh_prom = zext i8 %numhighbits to i64
470 %mask = lshr i64 -1, %sh_prom
471 %masked = and i64 %mask, %val
472 ret i64 %masked
473}
474
475define i64 @bzhi64_c4_commutative(i64 %val, i64 %numlowbits) nounwind {
476; CHECK-LABEL: bzhi64_c4_commutative:
477; CHECK: // %bb.0:
478; CHECK-NEXT: neg x8, x1
479; CHECK-NEXT: mov x9, #-1
480; CHECK-NEXT: lsr x8, x9, x8
481; CHECK-NEXT: and x0, x0, x8
482; CHECK-NEXT: ret
483 %numhighbits = sub i64 64, %numlowbits
484 %mask = lshr i64 -1, %numhighbits
485 %masked = and i64 %val, %mask ; swapped order
486 ret i64 %masked
487}
488
489; ---------------------------------------------------------------------------- ;
490; Pattern d. 32-bit.
491; ---------------------------------------------------------------------------- ;
492
493define i32 @bzhi32_d0(i32 %val, i32 %numlowbits) nounwind {
494; CHECK-LABEL: bzhi32_d0:
495; CHECK: // %bb.0:
496; CHECK-NEXT: neg w8, w1
497; CHECK-NEXT: lsl w9, w0, w8
498; CHECK-NEXT: lsr w0, w9, w8
499; CHECK-NEXT: ret
500 %numhighbits = sub i32 32, %numlowbits
501 %highbitscleared = shl i32 %val, %numhighbits
502 %masked = lshr i32 %highbitscleared, %numhighbits
503 ret i32 %masked
504}
505
506define i32 @bzhi32_d1_indexzext(i32 %val, i8 %numlowbits) nounwind {
507; CHECK-LABEL: bzhi32_d1_indexzext:
508; CHECK: // %bb.0:
509; CHECK-NEXT: orr w8, wzr, #0x20
510; CHECK-NEXT: sub w8, w8, w1
511; CHECK-NEXT: lsl w9, w0, w8
512; CHECK-NEXT: lsr w0, w9, w8
513; CHECK-NEXT: ret
514 %numhighbits = sub i8 32, %numlowbits
515 %sh_prom = zext i8 %numhighbits to i32
516 %highbitscleared = shl i32 %val, %sh_prom
517 %masked = lshr i32 %highbitscleared, %sh_prom
518 ret i32 %masked
519}
520
521define i32 @bzhi32_d2_load(i32* %w, i32 %numlowbits) nounwind {
522; CHECK-LABEL: bzhi32_d2_load:
523; CHECK: // %bb.0:
524; CHECK-NEXT: ldr w8, [x0]
525; CHECK-NEXT: neg w9, w1
526; CHECK-NEXT: lsl w8, w8, w9
527; CHECK-NEXT: lsr w0, w8, w9
528; CHECK-NEXT: ret
529 %val = load i32, i32* %w
530 %numhighbits = sub i32 32, %numlowbits
531 %highbitscleared = shl i32 %val, %numhighbits
532 %masked = lshr i32 %highbitscleared, %numhighbits
533 ret i32 %masked
534}
535
536define i32 @bzhi32_d3_load_indexzext(i32* %w, i8 %numlowbits) nounwind {
537; CHECK-LABEL: bzhi32_d3_load_indexzext:
538; CHECK: // %bb.0:
539; CHECK-NEXT: ldr w8, [x0]
540; CHECK-NEXT: orr w9, wzr, #0x20
541; CHECK-NEXT: sub w9, w9, w1
542; CHECK-NEXT: lsl w8, w8, w9
543; CHECK-NEXT: lsr w0, w8, w9
544; CHECK-NEXT: ret
545 %val = load i32, i32* %w
546 %numhighbits = sub i8 32, %numlowbits
547 %sh_prom = zext i8 %numhighbits to i32
548 %highbitscleared = shl i32 %val, %sh_prom
549 %masked = lshr i32 %highbitscleared, %sh_prom
550 ret i32 %masked
551}
552
553; 64-bit.
554
555define i64 @bzhi64_d0(i64 %val, i64 %numlowbits) nounwind {
556; CHECK-LABEL: bzhi64_d0:
557; CHECK: // %bb.0:
558; CHECK-NEXT: neg x8, x1
559; CHECK-NEXT: lsl x9, x0, x8
560; CHECK-NEXT: lsr x0, x9, x8
561; CHECK-NEXT: ret
562 %numhighbits = sub i64 64, %numlowbits
563 %highbitscleared = shl i64 %val, %numhighbits
564 %masked = lshr i64 %highbitscleared, %numhighbits
565 ret i64 %masked
566}
567
568define i64 @bzhi64_d1_indexzext(i64 %val, i8 %numlowbits) nounwind {
569; CHECK-LABEL: bzhi64_d1_indexzext:
570; CHECK: // %bb.0:
571; CHECK-NEXT: orr w8, wzr, #0x40
572; CHECK-NEXT: sub w8, w8, w1
573; CHECK-NEXT: lsl x9, x0, x8
574; CHECK-NEXT: lsr x0, x9, x8
575; CHECK-NEXT: ret
576 %numhighbits = sub i8 64, %numlowbits
577 %sh_prom = zext i8 %numhighbits to i64
578 %highbitscleared = shl i64 %val, %sh_prom
579 %masked = lshr i64 %highbitscleared, %sh_prom
580 ret i64 %masked
581}
582
583define i64 @bzhi64_d2_load(i64* %w, i64 %numlowbits) nounwind {
584; CHECK-LABEL: bzhi64_d2_load:
585; CHECK: // %bb.0:
586; CHECK-NEXT: ldr x8, [x0]
587; CHECK-NEXT: neg x9, x1
588; CHECK-NEXT: lsl x8, x8, x9
589; CHECK-NEXT: lsr x0, x8, x9
590; CHECK-NEXT: ret
591 %val = load i64, i64* %w
592 %numhighbits = sub i64 64, %numlowbits
593 %highbitscleared = shl i64 %val, %numhighbits
594 %masked = lshr i64 %highbitscleared, %numhighbits
595 ret i64 %masked
596}
597
598define i64 @bzhi64_d3_load_indexzext(i64* %w, i8 %numlowbits) nounwind {
599; CHECK-LABEL: bzhi64_d3_load_indexzext:
600; CHECK: // %bb.0:
601; CHECK-NEXT: ldr x8, [x0]
602; CHECK-NEXT: orr w9, wzr, #0x40
603; CHECK-NEXT: sub w9, w9, w1
604; CHECK-NEXT: lsl x8, x8, x9
605; CHECK-NEXT: lsr x0, x8, x9
606; CHECK-NEXT: ret
607 %val = load i64, i64* %w
608 %numhighbits = sub i8 64, %numlowbits
609 %sh_prom = zext i8 %numhighbits to i64
610 %highbitscleared = shl i64 %val, %sh_prom
611 %masked = lshr i64 %highbitscleared, %sh_prom
612 ret i64 %masked
613}
614
615; ---------------------------------------------------------------------------- ;
616; Constant mask
617; ---------------------------------------------------------------------------- ;
618
619; 32-bit
620
621define i32 @bzhi32_constant_mask32(i32 %val) nounwind {
622; CHECK-LABEL: bzhi32_constant_mask32:
623; CHECK: // %bb.0:
624; CHECK-NEXT: and w0, w0, #0x7fffffff
625; CHECK-NEXT: ret
626 %masked = and i32 %val, 2147483647
627 ret i32 %masked
628}
629
630define i32 @bzhi32_constant_mask32_load(i32* %val) nounwind {
631; CHECK-LABEL: bzhi32_constant_mask32_load:
632; CHECK: // %bb.0:
633; CHECK-NEXT: ldr w8, [x0]
634; CHECK-NEXT: and w0, w8, #0x7fffffff
635; CHECK-NEXT: ret
636 %val1 = load i32, i32* %val
637 %masked = and i32 %val1, 2147483647
638 ret i32 %masked
639}
640
641define i32 @bzhi32_constant_mask16(i32 %val) nounwind {
642; CHECK-LABEL: bzhi32_constant_mask16:
643; CHECK: // %bb.0:
644; CHECK-NEXT: and w0, w0, #0x7fff
645; CHECK-NEXT: ret
646 %masked = and i32 %val, 32767
647 ret i32 %masked
648}
649
650define i32 @bzhi32_constant_mask16_load(i32* %val) nounwind {
651; CHECK-LABEL: bzhi32_constant_mask16_load:
652; CHECK: // %bb.0:
653; CHECK-NEXT: ldr w8, [x0]
654; CHECK-NEXT: and w0, w8, #0x7fff
655; CHECK-NEXT: ret
656 %val1 = load i32, i32* %val
657 %masked = and i32 %val1, 32767
658 ret i32 %masked
659}
660
661define i32 @bzhi32_constant_mask8(i32 %val) nounwind {
662; CHECK-LABEL: bzhi32_constant_mask8:
663; CHECK: // %bb.0:
664; CHECK-NEXT: and w0, w0, #0x7f
665; CHECK-NEXT: ret
666 %masked = and i32 %val, 127
667 ret i32 %masked
668}
669
670define i32 @bzhi32_constant_mask8_load(i32* %val) nounwind {
671; CHECK-LABEL: bzhi32_constant_mask8_load:
672; CHECK: // %bb.0:
673; CHECK-NEXT: ldr w8, [x0]
674; CHECK-NEXT: and w0, w8, #0x7f
675; CHECK-NEXT: ret
676 %val1 = load i32, i32* %val
677 %masked = and i32 %val1, 127
678 ret i32 %masked
679}
680
681; 64-bit
682
683define i64 @bzhi64_constant_mask64(i64 %val) nounwind {
684; CHECK-LABEL: bzhi64_constant_mask64:
685; CHECK: // %bb.0:
686; CHECK-NEXT: and x0, x0, #0x3fffffffffffffff
687; CHECK-NEXT: ret
688 %masked = and i64 %val, 4611686018427387903
689 ret i64 %masked
690}
691
692define i64 @bzhi64_constant_mask64_load(i64* %val) nounwind {
693; CHECK-LABEL: bzhi64_constant_mask64_load:
694; CHECK: // %bb.0:
695; CHECK-NEXT: ldr x8, [x0]
696; CHECK-NEXT: and x0, x8, #0x3fffffffffffffff
697; CHECK-NEXT: ret
698 %val1 = load i64, i64* %val
699 %masked = and i64 %val1, 4611686018427387903
700 ret i64 %masked
701}
702
703define i64 @bzhi64_constant_mask32(i64 %val) nounwind {
704; CHECK-LABEL: bzhi64_constant_mask32:
705; CHECK: // %bb.0:
706; CHECK-NEXT: and x0, x0, #0x7fffffff
707; CHECK-NEXT: ret
708 %masked = and i64 %val, 2147483647
709 ret i64 %masked
710}
711
712define i64 @bzhi64_constant_mask32_load(i64* %val) nounwind {
713; CHECK-LABEL: bzhi64_constant_mask32_load:
714; CHECK: // %bb.0:
715; CHECK-NEXT: ldr x8, [x0]
716; CHECK-NEXT: and x0, x8, #0x7fffffff
717; CHECK-NEXT: ret
718 %val1 = load i64, i64* %val
719 %masked = and i64 %val1, 2147483647
720 ret i64 %masked
721}
722
723define i64 @bzhi64_constant_mask16(i64 %val) nounwind {
724; CHECK-LABEL: bzhi64_constant_mask16:
725; CHECK: // %bb.0:
726; CHECK-NEXT: and x0, x0, #0x7fff
727; CHECK-NEXT: ret
728 %masked = and i64 %val, 32767
729 ret i64 %masked
730}
731
732define i64 @bzhi64_constant_mask16_load(i64* %val) nounwind {
733; CHECK-LABEL: bzhi64_constant_mask16_load:
734; CHECK: // %bb.0:
735; CHECK-NEXT: ldr x8, [x0]
736; CHECK-NEXT: and x0, x8, #0x7fff
737; CHECK-NEXT: ret
738 %val1 = load i64, i64* %val
739 %masked = and i64 %val1, 32767
740 ret i64 %masked
741}
742
743define i64 @bzhi64_constant_mask8(i64 %val) nounwind {
744; CHECK-LABEL: bzhi64_constant_mask8:
745; CHECK: // %bb.0:
746; CHECK-NEXT: and x0, x0, #0x7f
747; CHECK-NEXT: ret
748 %masked = and i64 %val, 127
749 ret i64 %masked
750}
751
752define i64 @bzhi64_constant_mask8_load(i64* %val) nounwind {
753; CHECK-LABEL: bzhi64_constant_mask8_load:
754; CHECK: // %bb.0:
755; CHECK-NEXT: ldr x8, [x0]
756; CHECK-NEXT: and x0, x8, #0x7f
757; CHECK-NEXT: ret
758 %val1 = load i64, i64* %val
759 %masked = and i64 %val1, 127
760 ret i64 %masked
761}