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