xref: /llvm-project/llvm/test/CodeGen/AArch64/shift-amount-mod.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
3
4;==============================================================================;
5; the shift amount is negated (shiftbitwidth - shiftamt)
6;==============================================================================;
7
8; shift left
9;------------------------------------------------------------------------------;
10
11define i32 @reg32_shl_by_negated(i32 %val, i32 %shamt) nounwind {
12; CHECK-LABEL: reg32_shl_by_negated:
13; CHECK:       // %bb.0:
14; CHECK-NEXT:    neg w8, w1
15; CHECK-NEXT:    lsl w0, w0, w8
16; CHECK-NEXT:    ret
17  %negshamt = sub i32 32, %shamt
18  %shifted = shl i32 %val, %negshamt
19  ret i32 %shifted
20}
21define i32 @load32_shl_by_negated(ptr %valptr, i32 %shamt) nounwind {
22; CHECK-LABEL: load32_shl_by_negated:
23; CHECK:       // %bb.0:
24; CHECK-NEXT:    ldr w8, [x0]
25; CHECK-NEXT:    neg w9, w1
26; CHECK-NEXT:    lsl w0, w8, w9
27; CHECK-NEXT:    ret
28  %val = load i32, ptr %valptr
29  %negshamt = sub i32 32, %shamt
30  %shifted = shl i32 %val, %negshamt
31  ret i32 %shifted
32}
33define void @store32_shl_by_negated(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
34; CHECK-LABEL: store32_shl_by_negated:
35; CHECK:       // %bb.0:
36; CHECK-NEXT:    neg w8, w2
37; CHECK-NEXT:    lsl w8, w0, w8
38; CHECK-NEXT:    str w8, [x1]
39; CHECK-NEXT:    ret
40  %negshamt = sub i32 32, %shamt
41  %shifted = shl i32 %val, %negshamt
42  store i32 %shifted, ptr %dstptr
43  ret void
44}
45define void @modify32_shl_by_negated(ptr %valptr, i32 %shamt) nounwind {
46; CHECK-LABEL: modify32_shl_by_negated:
47; CHECK:       // %bb.0:
48; CHECK-NEXT:    ldr w8, [x0]
49; CHECK-NEXT:    neg w9, w1
50; CHECK-NEXT:    lsl w8, w8, w9
51; CHECK-NEXT:    str w8, [x0]
52; CHECK-NEXT:    ret
53  %val = load i32, ptr %valptr
54  %negshamt = sub i32 32, %shamt
55  %shifted = shl i32 %val, %negshamt
56  store i32 %shifted, ptr %valptr
57  ret void
58}
59define void @modify32_shl_by_negated_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
60; CHECK-LABEL: modify32_shl_by_negated_multi_use:
61; CHECK:       // %bb.0:
62; CHECK-NEXT:    ldr w8, [x0]
63; CHECK-NEXT:    neg w9, w1
64; CHECK-NEXT:    lsl w8, w8, w9
65; CHECK-NEXT:    mov w9, #32 // =0x20
66; CHECK-NEXT:    sub w9, w9, w1
67; CHECK-NEXT:    str w8, [x0]
68; CHECK-NEXT:    str w9, [x2]
69; CHECK-NEXT:    ret
70  %val = load i32, ptr %valptr
71  %negshamt = sub i32 32, %shamt
72  %shifted = shl i32 %val, %negshamt
73  store i32 %shifted, ptr %valptr
74  store i32 %negshamt, ptr %shamtptr
75  ret void
76}
77
78define i64 @reg64_shl_by_negated(i64 %val, i64 %shamt) nounwind {
79; CHECK-LABEL: reg64_shl_by_negated:
80; CHECK:       // %bb.0:
81; CHECK-NEXT:    neg x8, x1
82; CHECK-NEXT:    lsl x0, x0, x8
83; CHECK-NEXT:    ret
84  %negshamt = sub i64 64, %shamt
85  %shifted = shl i64 %val, %negshamt
86  ret i64 %shifted
87}
88define i64 @load64_shl_by_negated(ptr %valptr, i64 %shamt) nounwind {
89; CHECK-LABEL: load64_shl_by_negated:
90; CHECK:       // %bb.0:
91; CHECK-NEXT:    ldr x8, [x0]
92; CHECK-NEXT:    neg x9, x1
93; CHECK-NEXT:    lsl x0, x8, x9
94; CHECK-NEXT:    ret
95  %val = load i64, ptr %valptr
96  %negshamt = sub i64 64, %shamt
97  %shifted = shl i64 %val, %negshamt
98  ret i64 %shifted
99}
100define void @store64_shl_by_negated(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
101; CHECK-LABEL: store64_shl_by_negated:
102; CHECK:       // %bb.0:
103; CHECK-NEXT:    neg x8, x2
104; CHECK-NEXT:    lsl x8, x0, x8
105; CHECK-NEXT:    str x8, [x1]
106; CHECK-NEXT:    ret
107  %negshamt = sub i64 64, %shamt
108  %shifted = shl i64 %val, %negshamt
109  store i64 %shifted, ptr %dstptr
110  ret void
111}
112define void @modify64_shl_by_negated(ptr %valptr, i64 %shamt) nounwind {
113; CHECK-LABEL: modify64_shl_by_negated:
114; CHECK:       // %bb.0:
115; CHECK-NEXT:    ldr x8, [x0]
116; CHECK-NEXT:    neg x9, x1
117; CHECK-NEXT:    lsl x8, x8, x9
118; CHECK-NEXT:    str x8, [x0]
119; CHECK-NEXT:    ret
120  %val = load i64, ptr %valptr
121  %negshamt = sub i64 64, %shamt
122  %shifted = shl i64 %val, %negshamt
123  store i64 %shifted, ptr %valptr
124  ret void
125}
126define void @modify64_shl_by_negated_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
127; CHECK-LABEL: modify64_shl_by_negated_multi_use:
128; CHECK:       // %bb.0:
129; CHECK-NEXT:    ldr x8, [x0]
130; CHECK-NEXT:    neg x9, x1
131; CHECK-NEXT:    lsl x8, x8, x9
132; CHECK-NEXT:    mov w9, #64 // =0x40
133; CHECK-NEXT:    sub x9, x9, x1
134; CHECK-NEXT:    str x8, [x0]
135; CHECK-NEXT:    str x9, [x2]
136; CHECK-NEXT:    ret
137  %val = load i64, ptr %valptr
138  %negshamt = sub i64 64, %shamt
139  %shifted = shl i64 %val, %negshamt
140  store i64 %shifted, ptr %valptr
141  store i64 %negshamt, ptr %shamtptr
142  ret void
143}
144
145; logical shift right
146;------------------------------------------------------------------------------;
147
148define i32 @reg32_lshr_by_negated(i32 %val, i32 %shamt) nounwind {
149; CHECK-LABEL: reg32_lshr_by_negated:
150; CHECK:       // %bb.0:
151; CHECK-NEXT:    neg w8, w1
152; CHECK-NEXT:    lsr w0, w0, w8
153; CHECK-NEXT:    ret
154  %negshamt = sub i32 32, %shamt
155  %shifted = lshr i32 %val, %negshamt
156  ret i32 %shifted
157}
158define i32 @load32_lshr_by_negated(ptr %valptr, i32 %shamt) nounwind {
159; CHECK-LABEL: load32_lshr_by_negated:
160; CHECK:       // %bb.0:
161; CHECK-NEXT:    ldr w8, [x0]
162; CHECK-NEXT:    neg w9, w1
163; CHECK-NEXT:    lsr w0, w8, w9
164; CHECK-NEXT:    ret
165  %val = load i32, ptr %valptr
166  %negshamt = sub i32 32, %shamt
167  %shifted = lshr i32 %val, %negshamt
168  ret i32 %shifted
169}
170define void @store32_lshr_by_negated(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
171; CHECK-LABEL: store32_lshr_by_negated:
172; CHECK:       // %bb.0:
173; CHECK-NEXT:    neg w8, w2
174; CHECK-NEXT:    lsr w8, w0, w8
175; CHECK-NEXT:    str w8, [x1]
176; CHECK-NEXT:    ret
177  %negshamt = sub i32 32, %shamt
178  %shifted = lshr i32 %val, %negshamt
179  store i32 %shifted, ptr %dstptr
180  ret void
181}
182define void @modify32_lshr_by_negated(ptr %valptr, i32 %shamt) nounwind {
183; CHECK-LABEL: modify32_lshr_by_negated:
184; CHECK:       // %bb.0:
185; CHECK-NEXT:    ldr w8, [x0]
186; CHECK-NEXT:    neg w9, w1
187; CHECK-NEXT:    lsr w8, w8, w9
188; CHECK-NEXT:    str w8, [x0]
189; CHECK-NEXT:    ret
190  %val = load i32, ptr %valptr
191  %negshamt = sub i32 32, %shamt
192  %shifted = lshr i32 %val, %negshamt
193  store i32 %shifted, ptr %valptr
194  ret void
195}
196define void @modify32_lshr_by_negated_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
197; CHECK-LABEL: modify32_lshr_by_negated_multi_use:
198; CHECK:       // %bb.0:
199; CHECK-NEXT:    ldr w8, [x0]
200; CHECK-NEXT:    neg w9, w1
201; CHECK-NEXT:    lsr w8, w8, w9
202; CHECK-NEXT:    mov w9, #32 // =0x20
203; CHECK-NEXT:    sub w9, w9, w1
204; CHECK-NEXT:    str w8, [x0]
205; CHECK-NEXT:    str w9, [x2]
206; CHECK-NEXT:    ret
207  %val = load i32, ptr %valptr
208  %negshamt = sub i32 32, %shamt
209  %shifted = lshr i32 %val, %negshamt
210  store i32 %shifted, ptr %valptr
211  store i32 %negshamt, ptr %shamtptr
212  ret void
213}
214
215define i64 @reg64_lshr_by_negated(i64 %val, i64 %shamt) nounwind {
216; CHECK-LABEL: reg64_lshr_by_negated:
217; CHECK:       // %bb.0:
218; CHECK-NEXT:    neg x8, x1
219; CHECK-NEXT:    lsr x0, x0, x8
220; CHECK-NEXT:    ret
221  %negshamt = sub i64 64, %shamt
222  %shifted = lshr i64 %val, %negshamt
223  ret i64 %shifted
224}
225define i64 @load64_lshr_by_negated(ptr %valptr, i64 %shamt) nounwind {
226; CHECK-LABEL: load64_lshr_by_negated:
227; CHECK:       // %bb.0:
228; CHECK-NEXT:    ldr x8, [x0]
229; CHECK-NEXT:    neg x9, x1
230; CHECK-NEXT:    lsr x0, x8, x9
231; CHECK-NEXT:    ret
232  %val = load i64, ptr %valptr
233  %negshamt = sub i64 64, %shamt
234  %shifted = lshr i64 %val, %negshamt
235  ret i64 %shifted
236}
237define void @store64_lshr_by_negated(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
238; CHECK-LABEL: store64_lshr_by_negated:
239; CHECK:       // %bb.0:
240; CHECK-NEXT:    neg x8, x2
241; CHECK-NEXT:    lsr x8, x0, x8
242; CHECK-NEXT:    str x8, [x1]
243; CHECK-NEXT:    ret
244  %negshamt = sub i64 64, %shamt
245  %shifted = lshr i64 %val, %negshamt
246  store i64 %shifted, ptr %dstptr
247  ret void
248}
249define void @modify64_lshr_by_negated(ptr %valptr, i64 %shamt) nounwind {
250; CHECK-LABEL: modify64_lshr_by_negated:
251; CHECK:       // %bb.0:
252; CHECK-NEXT:    ldr x8, [x0]
253; CHECK-NEXT:    neg x9, x1
254; CHECK-NEXT:    lsr x8, x8, x9
255; CHECK-NEXT:    str x8, [x0]
256; CHECK-NEXT:    ret
257  %val = load i64, ptr %valptr
258  %negshamt = sub i64 64, %shamt
259  %shifted = lshr i64 %val, %negshamt
260  store i64 %shifted, ptr %valptr
261  ret void
262}
263define void @modify64_lshr_by_negated_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
264; CHECK-LABEL: modify64_lshr_by_negated_multi_use:
265; CHECK:       // %bb.0:
266; CHECK-NEXT:    ldr x8, [x0]
267; CHECK-NEXT:    neg x9, x1
268; CHECK-NEXT:    lsr x8, x8, x9
269; CHECK-NEXT:    mov w9, #64 // =0x40
270; CHECK-NEXT:    sub x9, x9, x1
271; CHECK-NEXT:    str x8, [x0]
272; CHECK-NEXT:    str x9, [x2]
273; CHECK-NEXT:    ret
274  %val = load i64, ptr %valptr
275  %negshamt = sub i64 64, %shamt
276  %shifted = lshr i64 %val, %negshamt
277  store i64 %shifted, ptr %valptr
278  store i64 %negshamt, ptr %shamtptr
279  ret void
280}
281
282; arithmetic shift right
283;------------------------------------------------------------------------------;
284
285define i32 @reg32_ashr_by_negated(i32 %val, i32 %shamt) nounwind {
286; CHECK-LABEL: reg32_ashr_by_negated:
287; CHECK:       // %bb.0:
288; CHECK-NEXT:    neg w8, w1
289; CHECK-NEXT:    asr w0, w0, w8
290; CHECK-NEXT:    ret
291  %negshamt = sub i32 32, %shamt
292  %shifted = ashr i32 %val, %negshamt
293  ret i32 %shifted
294}
295define i32 @load32_ashr_by_negated(ptr %valptr, i32 %shamt) nounwind {
296; CHECK-LABEL: load32_ashr_by_negated:
297; CHECK:       // %bb.0:
298; CHECK-NEXT:    ldr w8, [x0]
299; CHECK-NEXT:    neg w9, w1
300; CHECK-NEXT:    asr w0, w8, w9
301; CHECK-NEXT:    ret
302  %val = load i32, ptr %valptr
303  %negshamt = sub i32 32, %shamt
304  %shifted = ashr i32 %val, %negshamt
305  ret i32 %shifted
306}
307define void @store32_ashr_by_negated(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
308; CHECK-LABEL: store32_ashr_by_negated:
309; CHECK:       // %bb.0:
310; CHECK-NEXT:    neg w8, w2
311; CHECK-NEXT:    asr w8, w0, w8
312; CHECK-NEXT:    str w8, [x1]
313; CHECK-NEXT:    ret
314  %negshamt = sub i32 32, %shamt
315  %shifted = ashr i32 %val, %negshamt
316  store i32 %shifted, ptr %dstptr
317  ret void
318}
319define void @modify32_ashr_by_negated(ptr %valptr, i32 %shamt) nounwind {
320; CHECK-LABEL: modify32_ashr_by_negated:
321; CHECK:       // %bb.0:
322; CHECK-NEXT:    ldr w8, [x0]
323; CHECK-NEXT:    neg w9, w1
324; CHECK-NEXT:    asr w8, w8, w9
325; CHECK-NEXT:    str w8, [x0]
326; CHECK-NEXT:    ret
327  %val = load i32, ptr %valptr
328  %negshamt = sub i32 32, %shamt
329  %shifted = ashr i32 %val, %negshamt
330  store i32 %shifted, ptr %valptr
331  ret void
332}
333define void @modify32_ashr_by_negated_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
334; CHECK-LABEL: modify32_ashr_by_negated_multi_use:
335; CHECK:       // %bb.0:
336; CHECK-NEXT:    ldr w8, [x0]
337; CHECK-NEXT:    neg w9, w1
338; CHECK-NEXT:    asr w8, w8, w9
339; CHECK-NEXT:    mov w9, #32 // =0x20
340; CHECK-NEXT:    sub w9, w9, w1
341; CHECK-NEXT:    str w8, [x0]
342; CHECK-NEXT:    str w9, [x2]
343; CHECK-NEXT:    ret
344  %val = load i32, ptr %valptr
345  %negshamt = sub i32 32, %shamt
346  %shifted = ashr i32 %val, %negshamt
347  store i32 %shifted, ptr %valptr
348  store i32 %negshamt, ptr %shamtptr
349  ret void
350}
351
352define i64 @reg64_ashr_by_negated(i64 %val, i64 %shamt) nounwind {
353; CHECK-LABEL: reg64_ashr_by_negated:
354; CHECK:       // %bb.0:
355; CHECK-NEXT:    neg x8, x1
356; CHECK-NEXT:    asr x0, x0, x8
357; CHECK-NEXT:    ret
358  %negshamt = sub i64 64, %shamt
359  %shifted = ashr i64 %val, %negshamt
360  ret i64 %shifted
361}
362define i64 @load64_ashr_by_negated(ptr %valptr, i64 %shamt) nounwind {
363; CHECK-LABEL: load64_ashr_by_negated:
364; CHECK:       // %bb.0:
365; CHECK-NEXT:    ldr x8, [x0]
366; CHECK-NEXT:    neg x9, x1
367; CHECK-NEXT:    asr x0, x8, x9
368; CHECK-NEXT:    ret
369  %val = load i64, ptr %valptr
370  %negshamt = sub i64 64, %shamt
371  %shifted = ashr i64 %val, %negshamt
372  ret i64 %shifted
373}
374define void @store64_ashr_by_negated(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
375; CHECK-LABEL: store64_ashr_by_negated:
376; CHECK:       // %bb.0:
377; CHECK-NEXT:    neg x8, x2
378; CHECK-NEXT:    asr x8, x0, x8
379; CHECK-NEXT:    str x8, [x1]
380; CHECK-NEXT:    ret
381  %negshamt = sub i64 64, %shamt
382  %shifted = ashr i64 %val, %negshamt
383  store i64 %shifted, ptr %dstptr
384  ret void
385}
386define void @modify64_ashr_by_negated(ptr %valptr, i64 %shamt) nounwind {
387; CHECK-LABEL: modify64_ashr_by_negated:
388; CHECK:       // %bb.0:
389; CHECK-NEXT:    ldr x8, [x0]
390; CHECK-NEXT:    neg x9, x1
391; CHECK-NEXT:    asr x8, x8, x9
392; CHECK-NEXT:    str x8, [x0]
393; CHECK-NEXT:    ret
394  %val = load i64, ptr %valptr
395  %negshamt = sub i64 64, %shamt
396  %shifted = ashr i64 %val, %negshamt
397  store i64 %shifted, ptr %valptr
398  ret void
399}
400define void @modify64_ashr_by_negated_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
401; CHECK-LABEL: modify64_ashr_by_negated_multi_use:
402; CHECK:       // %bb.0:
403; CHECK-NEXT:    ldr x8, [x0]
404; CHECK-NEXT:    neg x9, x1
405; CHECK-NEXT:    asr x8, x8, x9
406; CHECK-NEXT:    mov w9, #64 // =0x40
407; CHECK-NEXT:    sub x9, x9, x1
408; CHECK-NEXT:    str x8, [x0]
409; CHECK-NEXT:    str x9, [x2]
410; CHECK-NEXT:    ret
411  %val = load i64, ptr %valptr
412  %negshamt = sub i64 64, %shamt
413  %shifted = ashr i64 %val, %negshamt
414  store i64 %shifted, ptr %valptr
415  store i64 %negshamt, ptr %shamtptr
416  ret void
417}
418
419;==============================================================================;
420; the shift amount is complemented (shiftbitwidth - 1 - shiftamt)
421;==============================================================================;
422
423; shift left
424;------------------------------------------------------------------------------;
425
426define i32 @reg32_shl_by_complemented(i32 %val, i32 %shamt) nounwind {
427; CHECK-LABEL: reg32_shl_by_complemented:
428; CHECK:       // %bb.0:
429; CHECK-NEXT:    mvn w8, w1
430; CHECK-NEXT:    lsl w0, w0, w8
431; CHECK-NEXT:    ret
432  %negshamt = sub i32 31, %shamt
433  %shifted = shl i32 %val, %negshamt
434  ret i32 %shifted
435}
436define i32 @load32_shl_by_complemented(ptr %valptr, i32 %shamt) nounwind {
437; CHECK-LABEL: load32_shl_by_complemented:
438; CHECK:       // %bb.0:
439; CHECK-NEXT:    ldr w8, [x0]
440; CHECK-NEXT:    mvn w9, w1
441; CHECK-NEXT:    lsl w0, w8, w9
442; CHECK-NEXT:    ret
443  %val = load i32, ptr %valptr
444  %negshamt = sub i32 31, %shamt
445  %shifted = shl i32 %val, %negshamt
446  ret i32 %shifted
447}
448define void @store32_shl_by_complemented(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
449; CHECK-LABEL: store32_shl_by_complemented:
450; CHECK:       // %bb.0:
451; CHECK-NEXT:    mvn w8, w2
452; CHECK-NEXT:    lsl w8, w0, w8
453; CHECK-NEXT:    str w8, [x1]
454; CHECK-NEXT:    ret
455  %negshamt = sub i32 31, %shamt
456  %shifted = shl i32 %val, %negshamt
457  store i32 %shifted, ptr %dstptr
458  ret void
459}
460define void @modify32_shl_by_complemented(ptr %valptr, i32 %shamt) nounwind {
461; CHECK-LABEL: modify32_shl_by_complemented:
462; CHECK:       // %bb.0:
463; CHECK-NEXT:    ldr w8, [x0]
464; CHECK-NEXT:    mvn w9, w1
465; CHECK-NEXT:    lsl w8, w8, w9
466; CHECK-NEXT:    str w8, [x0]
467; CHECK-NEXT:    ret
468  %val = load i32, ptr %valptr
469  %negshamt = sub i32 31, %shamt
470  %shifted = shl i32 %val, %negshamt
471  store i32 %shifted, ptr %valptr
472  ret void
473}
474define void @modify32_shl_by_complemented_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
475; CHECK-LABEL: modify32_shl_by_complemented_multi_use:
476; CHECK:       // %bb.0:
477; CHECK-NEXT:    ldr w8, [x0]
478; CHECK-NEXT:    mvn w9, w1
479; CHECK-NEXT:    lsl w8, w8, w9
480; CHECK-NEXT:    mov w9, #31 // =0x1f
481; CHECK-NEXT:    sub w9, w9, w1
482; CHECK-NEXT:    str w8, [x0]
483; CHECK-NEXT:    str w9, [x2]
484; CHECK-NEXT:    ret
485  %val = load i32, ptr %valptr
486  %negshamt = sub i32 31, %shamt
487  %shifted = shl i32 %val, %negshamt
488  store i32 %shifted, ptr %valptr
489  store i32 %negshamt, ptr %shamtptr
490  ret void
491}
492
493define i64 @reg64_shl_by_complemented(i64 %val, i64 %shamt) nounwind {
494; CHECK-LABEL: reg64_shl_by_complemented:
495; CHECK:       // %bb.0:
496; CHECK-NEXT:    mvn x8, x1
497; CHECK-NEXT:    lsl x0, x0, x8
498; CHECK-NEXT:    ret
499  %negshamt = sub i64 63, %shamt
500  %shifted = shl i64 %val, %negshamt
501  ret i64 %shifted
502}
503define i64 @load64_shl_by_complemented(ptr %valptr, i64 %shamt) nounwind {
504; CHECK-LABEL: load64_shl_by_complemented:
505; CHECK:       // %bb.0:
506; CHECK-NEXT:    ldr x8, [x0]
507; CHECK-NEXT:    mvn x9, x1
508; CHECK-NEXT:    lsl x0, x8, x9
509; CHECK-NEXT:    ret
510  %val = load i64, ptr %valptr
511  %negshamt = sub i64 63, %shamt
512  %shifted = shl i64 %val, %negshamt
513  ret i64 %shifted
514}
515define void @store64_shl_by_complemented(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
516; CHECK-LABEL: store64_shl_by_complemented:
517; CHECK:       // %bb.0:
518; CHECK-NEXT:    mvn x8, x2
519; CHECK-NEXT:    lsl x8, x0, x8
520; CHECK-NEXT:    str x8, [x1]
521; CHECK-NEXT:    ret
522  %negshamt = sub i64 63, %shamt
523  %shifted = shl i64 %val, %negshamt
524  store i64 %shifted, ptr %dstptr
525  ret void
526}
527define void @modify64_shl_by_complemented(ptr %valptr, i64 %shamt) nounwind {
528; CHECK-LABEL: modify64_shl_by_complemented:
529; CHECK:       // %bb.0:
530; CHECK-NEXT:    ldr x8, [x0]
531; CHECK-NEXT:    mvn x9, x1
532; CHECK-NEXT:    lsl x8, x8, x9
533; CHECK-NEXT:    str x8, [x0]
534; CHECK-NEXT:    ret
535  %val = load i64, ptr %valptr
536  %negshamt = sub i64 63, %shamt
537  %shifted = shl i64 %val, %negshamt
538  store i64 %shifted, ptr %valptr
539  ret void
540}
541define void @modify64_shl_by_complemented_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
542; CHECK-LABEL: modify64_shl_by_complemented_multi_use:
543; CHECK:       // %bb.0:
544; CHECK-NEXT:    ldr x8, [x0]
545; CHECK-NEXT:    mvn x9, x1
546; CHECK-NEXT:    lsl x8, x8, x9
547; CHECK-NEXT:    mov w9, #63 // =0x3f
548; CHECK-NEXT:    sub x9, x9, x1
549; CHECK-NEXT:    str x8, [x0]
550; CHECK-NEXT:    str x9, [x2]
551; CHECK-NEXT:    ret
552  %val = load i64, ptr %valptr
553  %negshamt = sub i64 63, %shamt
554  %shifted = shl i64 %val, %negshamt
555  store i64 %shifted, ptr %valptr
556  store i64 %negshamt, ptr %shamtptr
557  ret void
558}
559
560; logical shift right
561;------------------------------------------------------------------------------;
562
563define i32 @reg32_lshr_by_complemented(i32 %val, i32 %shamt) nounwind {
564; CHECK-LABEL: reg32_lshr_by_complemented:
565; CHECK:       // %bb.0:
566; CHECK-NEXT:    mvn w8, w1
567; CHECK-NEXT:    lsr w0, w0, w8
568; CHECK-NEXT:    ret
569  %negshamt = sub i32 31, %shamt
570  %shifted = lshr i32 %val, %negshamt
571  ret i32 %shifted
572}
573define i32 @load32_lshr_by_complemented(ptr %valptr, i32 %shamt) nounwind {
574; CHECK-LABEL: load32_lshr_by_complemented:
575; CHECK:       // %bb.0:
576; CHECK-NEXT:    ldr w8, [x0]
577; CHECK-NEXT:    mvn w9, w1
578; CHECK-NEXT:    lsr w0, w8, w9
579; CHECK-NEXT:    ret
580  %val = load i32, ptr %valptr
581  %negshamt = sub i32 31, %shamt
582  %shifted = lshr i32 %val, %negshamt
583  ret i32 %shifted
584}
585define void @store32_lshr_by_complemented(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
586; CHECK-LABEL: store32_lshr_by_complemented:
587; CHECK:       // %bb.0:
588; CHECK-NEXT:    mvn w8, w2
589; CHECK-NEXT:    lsr w8, w0, w8
590; CHECK-NEXT:    str w8, [x1]
591; CHECK-NEXT:    ret
592  %negshamt = sub i32 31, %shamt
593  %shifted = lshr i32 %val, %negshamt
594  store i32 %shifted, ptr %dstptr
595  ret void
596}
597define void @modify32_lshr_by_complemented(ptr %valptr, i32 %shamt) nounwind {
598; CHECK-LABEL: modify32_lshr_by_complemented:
599; CHECK:       // %bb.0:
600; CHECK-NEXT:    ldr w8, [x0]
601; CHECK-NEXT:    mvn w9, w1
602; CHECK-NEXT:    lsr w8, w8, w9
603; CHECK-NEXT:    str w8, [x0]
604; CHECK-NEXT:    ret
605  %val = load i32, ptr %valptr
606  %negshamt = sub i32 31, %shamt
607  %shifted = lshr i32 %val, %negshamt
608  store i32 %shifted, ptr %valptr
609  ret void
610}
611define void @modify32_lshr_by_complemented_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
612; CHECK-LABEL: modify32_lshr_by_complemented_multi_use:
613; CHECK:       // %bb.0:
614; CHECK-NEXT:    ldr w8, [x0]
615; CHECK-NEXT:    mvn w9, w1
616; CHECK-NEXT:    lsr w8, w8, w9
617; CHECK-NEXT:    mov w9, #31 // =0x1f
618; CHECK-NEXT:    sub w9, w9, w1
619; CHECK-NEXT:    str w8, [x0]
620; CHECK-NEXT:    str w9, [x2]
621; CHECK-NEXT:    ret
622  %val = load i32, ptr %valptr
623  %negshamt = sub i32 31, %shamt
624  %shifted = lshr i32 %val, %negshamt
625  store i32 %shifted, ptr %valptr
626  store i32 %negshamt, ptr %shamtptr
627  ret void
628}
629
630define i64 @reg64_lshr_by_complemented(i64 %val, i64 %shamt) nounwind {
631; CHECK-LABEL: reg64_lshr_by_complemented:
632; CHECK:       // %bb.0:
633; CHECK-NEXT:    mvn x8, x1
634; CHECK-NEXT:    lsr x0, x0, x8
635; CHECK-NEXT:    ret
636  %negshamt = sub i64 63, %shamt
637  %shifted = lshr i64 %val, %negshamt
638  ret i64 %shifted
639}
640define i64 @load64_lshr_by_complemented(ptr %valptr, i64 %shamt) nounwind {
641; CHECK-LABEL: load64_lshr_by_complemented:
642; CHECK:       // %bb.0:
643; CHECK-NEXT:    ldr x8, [x0]
644; CHECK-NEXT:    mvn x9, x1
645; CHECK-NEXT:    lsr x0, x8, x9
646; CHECK-NEXT:    ret
647  %val = load i64, ptr %valptr
648  %negshamt = sub i64 63, %shamt
649  %shifted = lshr i64 %val, %negshamt
650  ret i64 %shifted
651}
652define void @store64_lshr_by_complemented(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
653; CHECK-LABEL: store64_lshr_by_complemented:
654; CHECK:       // %bb.0:
655; CHECK-NEXT:    mvn x8, x2
656; CHECK-NEXT:    lsr x8, x0, x8
657; CHECK-NEXT:    str x8, [x1]
658; CHECK-NEXT:    ret
659  %negshamt = sub i64 63, %shamt
660  %shifted = lshr i64 %val, %negshamt
661  store i64 %shifted, ptr %dstptr
662  ret void
663}
664define void @modify64_lshr_by_complemented(ptr %valptr, i64 %shamt) nounwind {
665; CHECK-LABEL: modify64_lshr_by_complemented:
666; CHECK:       // %bb.0:
667; CHECK-NEXT:    ldr x8, [x0]
668; CHECK-NEXT:    mvn x9, x1
669; CHECK-NEXT:    lsr x8, x8, x9
670; CHECK-NEXT:    str x8, [x0]
671; CHECK-NEXT:    ret
672  %val = load i64, ptr %valptr
673  %negshamt = sub i64 63, %shamt
674  %shifted = lshr i64 %val, %negshamt
675  store i64 %shifted, ptr %valptr
676  ret void
677}
678define void @modify64_lshr_by_complemented_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
679; CHECK-LABEL: modify64_lshr_by_complemented_multi_use:
680; CHECK:       // %bb.0:
681; CHECK-NEXT:    ldr x8, [x0]
682; CHECK-NEXT:    mvn x9, x1
683; CHECK-NEXT:    lsr x8, x8, x9
684; CHECK-NEXT:    mov w9, #63 // =0x3f
685; CHECK-NEXT:    sub x9, x9, x1
686; CHECK-NEXT:    str x8, [x0]
687; CHECK-NEXT:    str x9, [x2]
688; CHECK-NEXT:    ret
689  %val = load i64, ptr %valptr
690  %negshamt = sub i64 63, %shamt
691  %shifted = lshr i64 %val, %negshamt
692  store i64 %shifted, ptr %valptr
693  store i64 %negshamt, ptr %shamtptr
694  ret void
695}
696
697; arithmetic shift right
698;------------------------------------------------------------------------------;
699
700define i32 @reg32_ashr_by_complemented(i32 %val, i32 %shamt) nounwind {
701; CHECK-LABEL: reg32_ashr_by_complemented:
702; CHECK:       // %bb.0:
703; CHECK-NEXT:    mvn w8, w1
704; CHECK-NEXT:    asr w0, w0, w8
705; CHECK-NEXT:    ret
706  %negshamt = sub i32 31, %shamt
707  %shifted = ashr i32 %val, %negshamt
708  ret i32 %shifted
709}
710define i32 @load32_ashr_by_complemented(ptr %valptr, i32 %shamt) nounwind {
711; CHECK-LABEL: load32_ashr_by_complemented:
712; CHECK:       // %bb.0:
713; CHECK-NEXT:    ldr w8, [x0]
714; CHECK-NEXT:    mvn w9, w1
715; CHECK-NEXT:    asr w0, w8, w9
716; CHECK-NEXT:    ret
717  %val = load i32, ptr %valptr
718  %negshamt = sub i32 31, %shamt
719  %shifted = ashr i32 %val, %negshamt
720  ret i32 %shifted
721}
722define void @store32_ashr_by_complemented(i32 %val, ptr %dstptr, i32 %shamt) nounwind {
723; CHECK-LABEL: store32_ashr_by_complemented:
724; CHECK:       // %bb.0:
725; CHECK-NEXT:    mvn w8, w2
726; CHECK-NEXT:    asr w8, w0, w8
727; CHECK-NEXT:    str w8, [x1]
728; CHECK-NEXT:    ret
729  %negshamt = sub i32 31, %shamt
730  %shifted = ashr i32 %val, %negshamt
731  store i32 %shifted, ptr %dstptr
732  ret void
733}
734define void @modify32_ashr_by_complemented(ptr %valptr, i32 %shamt) nounwind {
735; CHECK-LABEL: modify32_ashr_by_complemented:
736; CHECK:       // %bb.0:
737; CHECK-NEXT:    ldr w8, [x0]
738; CHECK-NEXT:    mvn w9, w1
739; CHECK-NEXT:    asr w8, w8, w9
740; CHECK-NEXT:    str w8, [x0]
741; CHECK-NEXT:    ret
742  %val = load i32, ptr %valptr
743  %negshamt = sub i32 31, %shamt
744  %shifted = ashr i32 %val, %negshamt
745  store i32 %shifted, ptr %valptr
746  ret void
747}
748define void @modify32_ashr_by_complemented_multi_use(ptr %valptr, i32 %shamt, ptr %shamtptr) nounwind {
749; CHECK-LABEL: modify32_ashr_by_complemented_multi_use:
750; CHECK:       // %bb.0:
751; CHECK-NEXT:    ldr w8, [x0]
752; CHECK-NEXT:    mvn w9, w1
753; CHECK-NEXT:    asr w8, w8, w9
754; CHECK-NEXT:    mov w9, #31 // =0x1f
755; CHECK-NEXT:    sub w9, w9, w1
756; CHECK-NEXT:    str w8, [x0]
757; CHECK-NEXT:    str w9, [x2]
758; CHECK-NEXT:    ret
759  %val = load i32, ptr %valptr
760  %negshamt = sub i32 31, %shamt
761  %shifted = ashr i32 %val, %negshamt
762  store i32 %shifted, ptr %valptr
763  store i32 %negshamt, ptr %shamtptr
764  ret void
765}
766
767define i64 @reg64_ashr_by_complemented(i64 %val, i64 %shamt) nounwind {
768; CHECK-LABEL: reg64_ashr_by_complemented:
769; CHECK:       // %bb.0:
770; CHECK-NEXT:    mvn x8, x1
771; CHECK-NEXT:    asr x0, x0, x8
772; CHECK-NEXT:    ret
773  %negshamt = sub i64 63, %shamt
774  %shifted = ashr i64 %val, %negshamt
775  ret i64 %shifted
776}
777define i64 @load64_ashr_by_complemented(ptr %valptr, i64 %shamt) nounwind {
778; CHECK-LABEL: load64_ashr_by_complemented:
779; CHECK:       // %bb.0:
780; CHECK-NEXT:    ldr x8, [x0]
781; CHECK-NEXT:    mvn x9, x1
782; CHECK-NEXT:    asr x0, x8, x9
783; CHECK-NEXT:    ret
784  %val = load i64, ptr %valptr
785  %negshamt = sub i64 63, %shamt
786  %shifted = ashr i64 %val, %negshamt
787  ret i64 %shifted
788}
789define void @store64_ashr_by_complemented(i64 %val, ptr %dstptr, i64 %shamt) nounwind {
790; CHECK-LABEL: store64_ashr_by_complemented:
791; CHECK:       // %bb.0:
792; CHECK-NEXT:    mvn x8, x2
793; CHECK-NEXT:    asr x8, x0, x8
794; CHECK-NEXT:    str x8, [x1]
795; CHECK-NEXT:    ret
796  %negshamt = sub i64 63, %shamt
797  %shifted = ashr i64 %val, %negshamt
798  store i64 %shifted, ptr %dstptr
799  ret void
800}
801define void @modify64_ashr_by_complemented(ptr %valptr, i64 %shamt) nounwind {
802; CHECK-LABEL: modify64_ashr_by_complemented:
803; CHECK:       // %bb.0:
804; CHECK-NEXT:    ldr x8, [x0]
805; CHECK-NEXT:    mvn x9, x1
806; CHECK-NEXT:    asr x8, x8, x9
807; CHECK-NEXT:    str x8, [x0]
808; CHECK-NEXT:    ret
809  %val = load i64, ptr %valptr
810  %negshamt = sub i64 63, %shamt
811  %shifted = ashr i64 %val, %negshamt
812  store i64 %shifted, ptr %valptr
813  ret void
814}
815define void @modify64_ashr_by_complemented_multi_use(ptr %valptr, i64 %shamt, ptr %shamtptr) nounwind {
816; CHECK-LABEL: modify64_ashr_by_complemented_multi_use:
817; CHECK:       // %bb.0:
818; CHECK-NEXT:    ldr x8, [x0]
819; CHECK-NEXT:    mvn x9, x1
820; CHECK-NEXT:    asr x8, x8, x9
821; CHECK-NEXT:    mov w9, #63 // =0x3f
822; CHECK-NEXT:    sub x9, x9, x1
823; CHECK-NEXT:    str x8, [x0]
824; CHECK-NEXT:    str x9, [x2]
825; CHECK-NEXT:    ret
826  %val = load i64, ptr %valptr
827  %negshamt = sub i64 63, %shamt
828  %shifted = ashr i64 %val, %negshamt
829  store i64 %shifted, ptr %valptr
830  store i64 %negshamt, ptr %shamtptr
831  ret void
832}
833
834;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||;
835; next let's only test simple reg pattern, and only lshr.
836;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||;
837
838;==============================================================================;
839; subtraction from negated shift amount
840
841define i32 @reg32_lshr_by_sub_from_negated(i32 %val, i32 %a, i32 %b) nounwind {
842; CHECK-LABEL: reg32_lshr_by_sub_from_negated:
843; CHECK:       // %bb.0:
844; CHECK-NEXT:    add w8, w1, w2
845; CHECK-NEXT:    neg w8, w8
846; CHECK-NEXT:    lsr w0, w0, w8
847; CHECK-NEXT:    ret
848  %nega = sub i32 32, %a
849  %negasubb = sub i32 %nega, %b
850  %shifted = lshr i32 %val, %negasubb
851  ret i32 %shifted
852}
853define i64 @reg64_lshr_by_sub_from_negated(i64 %val, i64 %a, i64 %b) nounwind {
854; CHECK-LABEL: reg64_lshr_by_sub_from_negated:
855; CHECK:       // %bb.0:
856; CHECK-NEXT:    add x8, x1, x2
857; CHECK-NEXT:    neg x8, x8
858; CHECK-NEXT:    lsr x0, x0, x8
859; CHECK-NEXT:    ret
860  %nega = sub i64 64, %a
861  %negasubb = sub i64 %nega, %b
862  %shifted = lshr i64 %val, %negasubb
863  ret i64 %shifted
864}
865
866;==============================================================================;
867; subtraction of negated shift amount
868
869define i32 @reg32_lshr_by_sub_of_negated(i32 %val, i32 %a, i32 %b) nounwind {
870; CHECK-LABEL: reg32_lshr_by_sub_of_negated:
871; CHECK:       // %bb.0:
872; CHECK-NEXT:    add w8, w1, w2
873; CHECK-NEXT:    lsr w0, w0, w8
874; CHECK-NEXT:    ret
875  %nega = sub i32 32, %a
876  %negasubb = sub i32 %b, %nega
877  %shifted = lshr i32 %val, %negasubb
878  ret i32 %shifted
879}
880define i64 @reg64_lshr_by_sub_of_negated(i64 %val, i64 %a, i64 %b) nounwind {
881; CHECK-LABEL: reg64_lshr_by_sub_of_negated:
882; CHECK:       // %bb.0:
883; CHECK-NEXT:    add x8, x1, x2
884; CHECK-NEXT:    lsr x0, x0, x8
885; CHECK-NEXT:    ret
886  %nega = sub i64 64, %a
887  %negasubb = sub i64 %b, %nega
888  %shifted = lshr i64 %val, %negasubb
889  ret i64 %shifted
890}
891
892;==============================================================================;
893; add to negated shift amount
894;
895
896define i32 @reg32_lshr_by_add_to_negated(i32 %val, i32 %a, i32 %b) nounwind {
897; CHECK-LABEL: reg32_lshr_by_add_to_negated:
898; CHECK:       // %bb.0:
899; CHECK-NEXT:    sub w8, w2, w1
900; CHECK-NEXT:    lsr w0, w0, w8
901; CHECK-NEXT:    ret
902  %nega = sub i32 32, %a
903  %negasubb = add i32 %nega, %b
904  %shifted = lshr i32 %val, %negasubb
905  ret i32 %shifted
906}
907define i64 @reg64_lshr_by_add_to_negated(i64 %val, i64 %a, i64 %b) nounwind {
908; CHECK-LABEL: reg64_lshr_by_add_to_negated:
909; CHECK:       // %bb.0:
910; CHECK-NEXT:    sub x8, x2, x1
911; CHECK-NEXT:    lsr x0, x0, x8
912; CHECK-NEXT:    ret
913  %nega = sub i64 64, %a
914  %negasubb = add i64 %nega, %b
915  %shifted = lshr i64 %val, %negasubb
916  ret i64 %shifted
917}
918
919;==============================================================================;
920; subtraction of negated shift amounts
921
922define i32 @reg32_lshr_by_sub_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind {
923; CHECK-LABEL: reg32_lshr_by_sub_of_negated_amts:
924; CHECK:       // %bb.0:
925; CHECK-NEXT:    sub w8, w2, w1
926; CHECK-NEXT:    lsr w0, w0, w8
927; CHECK-NEXT:    ret
928  %nega = sub i32 32, %a
929  %negb = sub i32 32, %b
930  %negasubnegb = sub i32 %nega, %negb
931  %shifted = lshr i32 %val, %negasubnegb
932  ret i32 %shifted
933}
934define i64 @reg64_lshr_by_sub_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind {
935; CHECK-LABEL: reg64_lshr_by_sub_of_negated_amts:
936; CHECK:       // %bb.0:
937; CHECK-NEXT:    sub x8, x2, x1
938; CHECK-NEXT:    lsr x0, x0, x8
939; CHECK-NEXT:    ret
940  %nega = sub i64 64, %a
941  %negb = sub i64 64, %b
942  %negasubnegb = sub i64 %nega, %negb
943  %shifted = lshr i64 %val, %negasubnegb
944  ret i64 %shifted
945}
946
947;==============================================================================;
948; addition of negated shift amounts
949
950define i32 @reg32_lshr_by_add_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind {
951; CHECK-LABEL: reg32_lshr_by_add_of_negated_amts:
952; CHECK:       // %bb.0:
953; CHECK-NEXT:    add w8, w1, w2
954; CHECK-NEXT:    neg w8, w8
955; CHECK-NEXT:    lsr w0, w0, w8
956; CHECK-NEXT:    ret
957  %nega = sub i32 32, %a
958  %negb = sub i32 32, %b
959  %negasubnegb = add i32 %nega, %negb
960  %shifted = lshr i32 %val, %negasubnegb
961  ret i32 %shifted
962}
963define i64 @reg64_lshr_by_add_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind {
964; CHECK-LABEL: reg64_lshr_by_add_of_negated_amts:
965; CHECK:       // %bb.0:
966; CHECK-NEXT:    add x8, x1, x2
967; CHECK-NEXT:    neg x8, x8
968; CHECK-NEXT:    lsr x0, x0, x8
969; CHECK-NEXT:    ret
970  %nega = sub i64 64, %a
971  %negb = sub i64 64, %b
972  %negasubnegb = add i64 %nega, %negb
973  %shifted = lshr i64 %val, %negasubnegb
974  ret i64 %shifted
975}
976
977;==============================================================================;
978; and patterns with an actual negation+addition
979
980define i32 @reg32_lshr_by_negated_unfolded(i32 %val, i32 %shamt) nounwind {
981; CHECK-LABEL: reg32_lshr_by_negated_unfolded:
982; CHECK:       // %bb.0:
983; CHECK-NEXT:    neg w8, w1
984; CHECK-NEXT:    lsr w0, w0, w8
985; CHECK-NEXT:    ret
986  %negshamt = sub i32 0, %shamt
987  %negaaddbitwidth = add i32 %negshamt, 32
988  %shifted = lshr i32 %val, %negaaddbitwidth
989  ret i32 %shifted
990}
991define i64 @reg64_lshr_by_negated_unfolded(i64 %val, i64 %shamt) nounwind {
992; CHECK-LABEL: reg64_lshr_by_negated_unfolded:
993; CHECK:       // %bb.0:
994; CHECK-NEXT:    neg x8, x1
995; CHECK-NEXT:    lsr x0, x0, x8
996; CHECK-NEXT:    ret
997  %negshamt = sub i64 0, %shamt
998  %negaaddbitwidth = add i64 %negshamt, 64
999  %shifted = lshr i64 %val, %negaaddbitwidth
1000  ret i64 %shifted
1001}
1002
1003define i32 @reg32_lshr_by_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind {
1004; CHECK-LABEL: reg32_lshr_by_negated_unfolded_sub_b:
1005; CHECK:       // %bb.0:
1006; CHECK-NEXT:    add w8, w1, w2
1007; CHECK-NEXT:    neg w8, w8
1008; CHECK-NEXT:    lsr w0, w0, w8
1009; CHECK-NEXT:    ret
1010  %nega = sub i32 0, %a
1011  %negaaddbitwidth = add i32 %nega, 32
1012  %negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b
1013  %shifted = lshr i32 %val, %negaaddbitwidthsubb
1014  ret i32 %shifted
1015}
1016define i64 @reg64_lshr_by_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind {
1017; CHECK-LABEL: reg64_lshr_by_negated_unfolded_sub_b:
1018; CHECK:       // %bb.0:
1019; CHECK-NEXT:    add x8, x1, x2
1020; CHECK-NEXT:    neg x8, x8
1021; CHECK-NEXT:    lsr x0, x0, x8
1022; CHECK-NEXT:    ret
1023  %nega = sub i64 0, %a
1024  %negaaddbitwidth = add i64 %nega, 64
1025  %negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b
1026  %shifted = lshr i64 %val, %negaaddbitwidthsubb
1027  ret i64 %shifted
1028}
1029
1030define i32 @reg32_lshr_by_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind {
1031; CHECK-LABEL: reg32_lshr_by_b_sub_negated_unfolded:
1032; CHECK:       // %bb.0:
1033; CHECK-NEXT:    add w8, w2, w1
1034; CHECK-NEXT:    lsr w0, w0, w8
1035; CHECK-NEXT:    ret
1036  %nega = sub i32 0, %a
1037  %negaaddbitwidth = add i32 %nega, 32
1038  %negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth
1039  %shifted = lshr i32 %val, %negaaddbitwidthsubb
1040  ret i32 %shifted
1041}
1042define i64 @reg64_lshr_by_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind {
1043; CHECK-LABEL: reg64_lshr_by_b_sub_negated_unfolded:
1044; CHECK:       // %bb.0:
1045; CHECK-NEXT:    add x8, x2, x1
1046; CHECK-NEXT:    lsr x0, x0, x8
1047; CHECK-NEXT:    ret
1048  %nega = sub i64 0, %a
1049  %negaaddbitwidth = add i64 %nega, 64
1050  %negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth
1051  %shifted = lshr i64 %val, %negaaddbitwidthsubb
1052  ret i64 %shifted
1053}
1054
1055define i32 @reg32_lshr_by_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind {
1056; CHECK-LABEL: reg32_lshr_by_negated_unfolded_add_b:
1057; CHECK:       // %bb.0:
1058; CHECK-NEXT:    sub w8, w2, w1
1059; CHECK-NEXT:    lsr w0, w0, w8
1060; CHECK-NEXT:    ret
1061  %nega = sub i32 0, %a
1062  %negaaddbitwidth = add i32 %nega, 32
1063  %negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b
1064  %shifted = lshr i32 %val, %negaaddbitwidthaddb
1065  ret i32 %shifted
1066}
1067define i64 @reg64_lshr_by_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind {
1068; CHECK-LABEL: reg64_lshr_by_negated_unfolded_add_b:
1069; CHECK:       // %bb.0:
1070; CHECK-NEXT:    sub x8, x2, x1
1071; CHECK-NEXT:    lsr x0, x0, x8
1072; CHECK-NEXT:    ret
1073  %nega = sub i64 0, %a
1074  %negaaddbitwidth = add i64 %nega, 64
1075  %negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b
1076  %shifted = lshr i64 %val, %negaaddbitwidthaddb
1077  ret i64 %shifted
1078}
1079
1080;==============================================================================;
1081; and patterns with an actual negation+mask
1082
1083define i32 @reg32_lshr_by_masked_negated_unfolded(i32 %val, i32 %shamt) nounwind {
1084; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded:
1085; CHECK:       // %bb.0:
1086; CHECK-NEXT:    neg w8, w1
1087; CHECK-NEXT:    lsr w0, w0, w8
1088; CHECK-NEXT:    ret
1089  %negshamt = sub i32 0, %shamt
1090  %negaaddbitwidth = and i32 %negshamt, 31
1091  %shifted = lshr i32 %val, %negaaddbitwidth
1092  ret i32 %shifted
1093}
1094define i64 @reg64_lshr_by_masked_negated_unfolded(i64 %val, i64 %shamt) nounwind {
1095; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded:
1096; CHECK:       // %bb.0:
1097; CHECK-NEXT:    neg w8, w1
1098; CHECK-NEXT:    lsr x0, x0, x8
1099; CHECK-NEXT:    ret
1100  %negshamt = sub i64 0, %shamt
1101  %negaaddbitwidth = and i64 %negshamt, 63
1102  %shifted = lshr i64 %val, %negaaddbitwidth
1103  ret i64 %shifted
1104}
1105
1106define i32 @reg32_lshr_by_masked_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind {
1107; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded_sub_b:
1108; CHECK:       // %bb.0:
1109; CHECK-NEXT:    neg w8, w1
1110; CHECK-NEXT:    and w8, w8, #0x1f
1111; CHECK-NEXT:    sub w8, w8, w2
1112; CHECK-NEXT:    lsr w0, w0, w8
1113; CHECK-NEXT:    ret
1114  %nega = sub i32 0, %a
1115  %negaaddbitwidth = and i32 %nega, 31
1116  %negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b
1117  %shifted = lshr i32 %val, %negaaddbitwidthsubb
1118  ret i32 %shifted
1119}
1120define i64 @reg64_lshr_by_masked_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind {
1121; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded_sub_b:
1122; CHECK:       // %bb.0:
1123; CHECK-NEXT:    neg w8, w1
1124; CHECK-NEXT:    and x8, x8, #0x3f
1125; CHECK-NEXT:    sub x8, x8, x2
1126; CHECK-NEXT:    lsr x0, x0, x8
1127; CHECK-NEXT:    ret
1128  %nega = sub i64 0, %a
1129  %negaaddbitwidth = and i64 %nega, 63
1130  %negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b
1131  %shifted = lshr i64 %val, %negaaddbitwidthsubb
1132  ret i64 %shifted
1133}
1134
1135define i32 @reg32_lshr_by_masked_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind {
1136; CHECK-LABEL: reg32_lshr_by_masked_b_sub_negated_unfolded:
1137; CHECK:       // %bb.0:
1138; CHECK-NEXT:    neg w8, w1
1139; CHECK-NEXT:    and w8, w8, #0x1f
1140; CHECK-NEXT:    sub w8, w2, w8
1141; CHECK-NEXT:    lsr w0, w0, w8
1142; CHECK-NEXT:    ret
1143  %nega = sub i32 0, %a
1144  %negaaddbitwidth = and i32 %nega, 31
1145  %negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth
1146  %shifted = lshr i32 %val, %negaaddbitwidthsubb
1147  ret i32 %shifted
1148}
1149define i64 @reg64_lshr_by_masked_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind {
1150; CHECK-LABEL: reg64_lshr_by_masked_b_sub_negated_unfolded:
1151; CHECK:       // %bb.0:
1152; CHECK-NEXT:    neg w8, w1
1153; CHECK-NEXT:    and x8, x8, #0x3f
1154; CHECK-NEXT:    sub x8, x2, x8
1155; CHECK-NEXT:    lsr x0, x0, x8
1156; CHECK-NEXT:    ret
1157  %nega = sub i64 0, %a
1158  %negaaddbitwidth = and i64 %nega, 63
1159  %negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth
1160  %shifted = lshr i64 %val, %negaaddbitwidthsubb
1161  ret i64 %shifted
1162}
1163
1164define i32 @reg32_lshr_by_masked_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind {
1165; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded_add_b:
1166; CHECK:       // %bb.0:
1167; CHECK-NEXT:    neg w8, w1
1168; CHECK-NEXT:    and w8, w8, #0x1f
1169; CHECK-NEXT:    add w8, w8, w2
1170; CHECK-NEXT:    lsr w0, w0, w8
1171; CHECK-NEXT:    ret
1172  %nega = sub i32 0, %a
1173  %negaaddbitwidth = and i32 %nega, 31
1174  %negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b
1175  %shifted = lshr i32 %val, %negaaddbitwidthaddb
1176  ret i32 %shifted
1177}
1178define i64 @reg64_lshr_by_masked_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind {
1179; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded_add_b:
1180; CHECK:       // %bb.0:
1181; CHECK-NEXT:    neg w8, w1
1182; CHECK-NEXT:    and x8, x8, #0x3f
1183; CHECK-NEXT:    add x8, x8, x2
1184; CHECK-NEXT:    lsr x0, x0, x8
1185; CHECK-NEXT:    ret
1186  %nega = sub i64 0, %a
1187  %negaaddbitwidth = and i64 %nega, 63
1188  %negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b
1189  %shifted = lshr i64 %val, %negaaddbitwidthaddb
1190  ret i64 %shifted
1191}
1192
1193define i32 @t(i64 %x) {
1194; CHECK-LABEL: t:
1195; CHECK:       // %bb.0:
1196; CHECK-NEXT:    ubfx x0, x0, #17, #28
1197; CHECK-NEXT:    // kill: def $w0 killed $w0 killed $x0
1198; CHECK-NEXT:    ret
1199  %s = lshr i64 %x, 13
1200  %t = trunc i64 %s to i32
1201  %r = lshr i32 %t, 4
1202  ret i32 %r
1203}
1204