[Alignment][NFC] migrate DataLayout internal struct to llvm::Align
[llvm-core.git] / test / CodeGen / AArch64 / rotate-extract.ll
blob41664294b1c2d763240d6ab0160ebbf7b967c875
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
4 ; Check that under certain conditions we can factor out a rotate
5 ; from the following idioms:
6 ;   (a*c0) >> s1 | (a*c1)
7 ;   (a/c0) << s1 | (a/c1)
8 ; This targets cases where instcombine has folded a shl/srl/mul/udiv
9 ; with one of the shifts from the rotate idiom
11 define i64 @ror_extract_shl(i64 %i) nounwind {
12 ; CHECK-LABEL: ror_extract_shl:
13 ; CHECK:       // %bb.0:
14 ; CHECK-NEXT:    lsl x8, x0, #3
15 ; CHECK-NEXT:    ror x0, x8, #57
16 ; CHECK-NEXT:    ret
17   %lhs_mul = shl i64 %i, 3
18   %rhs_mul = shl i64 %i, 10
19   %lhs_shift = lshr i64 %lhs_mul, 57
20   %out = or i64 %lhs_shift, %rhs_mul
21   ret i64 %out
24 define i32 @ror_extract_shrl(i32 %i) nounwind {
25 ; CHECK-LABEL: ror_extract_shrl:
26 ; CHECK:       // %bb.0:
27 ; CHECK-NEXT:    lsr w8, w0, #3
28 ; CHECK-NEXT:    ror w0, w8, #4
29 ; CHECK-NEXT:    ret
30   %lhs_div = lshr i32 %i, 7
31   %rhs_div = lshr i32 %i, 3
32   %rhs_shift = shl i32 %rhs_div, 28
33   %out = or i32 %lhs_div, %rhs_shift
34   ret i32 %out
37 define i32 @ror_extract_mul(i32 %i) nounwind {
38 ; CHECK-LABEL: ror_extract_mul:
39 ; CHECK:       // %bb.0:
40 ; CHECK-NEXT:    add w8, w0, w0, lsl #3
41 ; CHECK-NEXT:    ror w0, w8, #25
42 ; CHECK-NEXT:    ret
43   %lhs_mul = mul i32 %i, 9
44   %rhs_mul = mul i32 %i, 1152
45   %lhs_shift = lshr i32 %lhs_mul, 25
46   %out = or i32 %lhs_shift, %rhs_mul
47   ret i32 %out
50 define i64 @ror_extract_udiv(i64 %i) nounwind {
51 ; CHECK-LABEL: ror_extract_udiv:
52 ; CHECK:       // %bb.0:
53 ; CHECK-NEXT:    mov x8, #-6148914691236517206
54 ; CHECK-NEXT:    movk x8, #43691
55 ; CHECK-NEXT:    umulh x8, x0, x8
56 ; CHECK-NEXT:    lsr x8, x8, #1
57 ; CHECK-NEXT:    ror x0, x8, #4
58 ; CHECK-NEXT:    ret
59   %lhs_div = udiv i64 %i, 3
60   %rhs_div = udiv i64 %i, 48
61   %lhs_shift = shl i64 %lhs_div, 60
62   %out = or i64 %lhs_shift, %rhs_div
63   ret i64 %out
66 define i64 @ror_extract_mul_with_mask(i64 %i) nounwind {
67 ; CHECK-LABEL: ror_extract_mul_with_mask:
68 ; CHECK:       // %bb.0:
69 ; CHECK-NEXT:    add x8, x0, x0, lsl #3
70 ; CHECK-NEXT:    ror x8, x8, #57
71 ; CHECK-NEXT:    and x0, x8, #0xff
72 ; CHECK-NEXT:    ret
73   %lhs_mul = mul i64 %i, 1152
74   %rhs_mul = mul i64 %i, 9
75   %lhs_and = and i64 %lhs_mul, 160
76   %rhs_shift = lshr i64 %rhs_mul, 57
77   %out = or i64 %lhs_and, %rhs_shift
78   ret i64 %out
81 ; Result would undershift
82 define i64 @no_extract_shl(i64 %i) nounwind {
83 ; CHECK-LABEL: no_extract_shl:
84 ; CHECK:       // %bb.0:
85 ; CHECK-NEXT:    lsl x8, x0, #10
86 ; CHECK-NEXT:    bfxil x8, x0, #52, #7
87 ; CHECK-NEXT:    mov x0, x8
88 ; CHECK-NEXT:    ret
89   %lhs_mul = shl i64 %i, 5
90   %rhs_mul = shl i64 %i, 10
91   %lhs_shift = lshr i64 %lhs_mul, 57
92   %out = or i64 %lhs_shift, %rhs_mul
93   ret i64 %out
96 ; Result would overshift
97 define i32 @no_extract_shrl(i32 %i) nounwind {
98 ; CHECK-LABEL: no_extract_shrl:
99 ; CHECK:       // %bb.0:
100 ; CHECK-NEXT:    lsr w8, w0, #3
101 ; CHECK-NEXT:    lsr w0, w0, #9
102 ; CHECK-NEXT:    bfi w0, w8, #28, #4
103 ; CHECK-NEXT:    ret
104   %lhs_div = lshr i32 %i, 3
105   %rhs_div = lshr i32 %i, 9
106   %lhs_shift = shl i32 %lhs_div, 28
107   %out = or i32 %lhs_shift, %rhs_div
108   ret i32 %out
111 ; Can factor 128 from 2304, but result is 18 instead of 9
112 define i64 @no_extract_mul(i64 %i) nounwind {
113 ; CHECK-LABEL: no_extract_mul:
114 ; CHECK:       // %bb.0:
115 ; CHECK-NEXT:    add x8, x0, x0, lsl #3
116 ; CHECK-NEXT:    lsr x0, x8, #57
117 ; CHECK-NEXT:    bfi x0, x8, #8, #56
118 ; CHECK-NEXT:    ret
119   %lhs_mul = mul i64 %i, 2304
120   %rhs_mul = mul i64 %i, 9
121   %rhs_shift = lshr i64 %rhs_mul, 57
122   %out = or i64 %lhs_mul, %rhs_shift
123   ret i64 %out
126 ; Can't evenly factor 16 from 49
127 define i32 @no_extract_udiv(i32 %i) nounwind {
128 ; CHECK-LABEL: no_extract_udiv:
129 ; CHECK:       // %bb.0:
130 ; CHECK-NEXT:    mov w8, #43691
131 ; CHECK-NEXT:    mov w9, #33437
132 ; CHECK-NEXT:    movk w8, #43690, lsl #16
133 ; CHECK-NEXT:    movk w9, #21399, lsl #16
134 ; CHECK-NEXT:    umull x8, w0, w8
135 ; CHECK-NEXT:    umull x9, w0, w9
136 ; CHECK-NEXT:    lsr x8, x8, #33
137 ; CHECK-NEXT:    lsr x9, x9, #32
138 ; CHECK-NEXT:    extr w0, w8, w9, #4
139 ; CHECK-NEXT:    ret
140   %lhs_div = udiv i32 %i, 3
141   %rhs_div = udiv i32 %i, 49
142   %lhs_shift = shl i32 %lhs_div, 28
143   %out = or i32 %lhs_shift, %rhs_div
144   ret i32 %out