1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
4 ; Check that we recognize this idiom for rotation too:
5 ; a << (b & (OpSize-1)) | a >> ((0 - b) & (OpSize-1))
7 define i32 @rotate_left_32(i32 %a, i32 %b) {
8 ; CHECK-LABEL: rotate_left_32:
10 ; CHECK-NEXT: movl %esi, %ecx
11 ; CHECK-NEXT: roll %cl, %edi
12 ; CHECK-NEXT: movl %edi, %eax
15 %shl = shl i32 %a, %and
17 %and3 = and i32 %t0, 31
18 %shr = lshr i32 %a, %and3
19 %or = or i32 %shl, %shr
23 define i32 @rotate_right_32(i32 %a, i32 %b) {
24 ; CHECK-LABEL: rotate_right_32:
26 ; CHECK-NEXT: movl %esi, %ecx
27 ; CHECK-NEXT: rorl %cl, %edi
28 ; CHECK-NEXT: movl %edi, %eax
31 %shl = lshr i32 %a, %and
33 %and3 = and i32 %t0, 31
34 %shr = shl i32 %a, %and3
35 %or = or i32 %shl, %shr
39 define i64 @rotate_left_64(i64 %a, i64 %b) {
40 ; CHECK-LABEL: rotate_left_64:
42 ; CHECK-NEXT: movl %esi, %ecx
43 ; CHECK-NEXT: rolq %cl, %rdi
44 ; CHECK-NEXT: movq %rdi, %rax
47 %shl = shl i64 %a, %and
49 %and3 = and i64 %t0, 63
50 %shr = lshr i64 %a, %and3
51 %or = or i64 %shl, %shr
55 define i64 @rotate_right_64(i64 %a, i64 %b) {
56 ; CHECK-LABEL: rotate_right_64:
58 ; CHECK-NEXT: movl %esi, %ecx
59 ; CHECK-NEXT: rorq %cl, %rdi
60 ; CHECK-NEXT: movq %rdi, %rax
63 %shl = lshr i64 %a, %and
65 %and3 = and i64 %t0, 63
66 %shr = shl i64 %a, %and3
67 %or = or i64 %shl, %shr
71 ; Also check mem operand.
73 define void @rotate_left_m32(i32 *%pa, i32 %b) {
74 ; CHECK-LABEL: rotate_left_m32:
76 ; CHECK-NEXT: movl %esi, %ecx
77 ; CHECK-NEXT: roll %cl, (%rdi)
79 %a = load i32, i32* %pa, align 16
81 %shl = shl i32 %a, %and
83 %and3 = and i32 %t0, 31
84 %shr = lshr i32 %a, %and3
85 %or = or i32 %shl, %shr
86 store i32 %or, i32* %pa, align 32
90 define void @rotate_right_m32(i32 *%pa, i32 %b) {
91 ; CHECK-LABEL: rotate_right_m32:
93 ; CHECK-NEXT: movl %esi, %ecx
94 ; CHECK-NEXT: rorl %cl, (%rdi)
96 %a = load i32, i32* %pa, align 16
98 %shl = lshr i32 %a, %and
100 %and3 = and i32 %t0, 31
101 %shr = shl i32 %a, %and3
102 %or = or i32 %shl, %shr
103 store i32 %or, i32* %pa, align 32
107 define void @rotate_left_m64(i64 *%pa, i64 %b) {
108 ; CHECK-LABEL: rotate_left_m64:
110 ; CHECK-NEXT: movl %esi, %ecx
111 ; CHECK-NEXT: rolq %cl, (%rdi)
113 %a = load i64, i64* %pa, align 16
114 %and = and i64 %b, 63
115 %shl = shl i64 %a, %and
117 %and3 = and i64 %t0, 63
118 %shr = lshr i64 %a, %and3
119 %or = or i64 %shl, %shr
120 store i64 %or, i64* %pa, align 64
124 define void @rotate_right_m64(i64 *%pa, i64 %b) {
125 ; CHECK-LABEL: rotate_right_m64:
127 ; CHECK-NEXT: movl %esi, %ecx
128 ; CHECK-NEXT: rorq %cl, (%rdi)
130 %a = load i64, i64* %pa, align 16
131 %and = and i64 %b, 63
132 %shl = lshr i64 %a, %and
134 %and3 = and i64 %t0, 63
135 %shr = shl i64 %a, %and3
136 %or = or i64 %shl, %shr
137 store i64 %or, i64* %pa, align 64
141 ; The next 8 tests include masks of the narrow width shift amounts that should be eliminated.
142 ; These patterns are produced by instcombine after r310509.
144 define i8 @rotate_left_8(i8 %x, i32 %amount) {
145 ; CHECK-LABEL: rotate_left_8:
147 ; CHECK-NEXT: movl %esi, %ecx
148 ; CHECK-NEXT: rolb %cl, %dil
149 ; CHECK-NEXT: movl %edi, %eax
151 %amt = trunc i32 %amount to i8
152 %sub = sub i8 0, %amt
153 %maskamt = and i8 %amt, 7
154 %masksub = and i8 %sub, 7
155 %shl = shl i8 %x, %maskamt
156 %shr = lshr i8 %x, %masksub
157 %or = or i8 %shl, %shr
161 define i8 @rotate_right_8(i8 %x, i32 %amount) {
162 ; CHECK-LABEL: rotate_right_8:
164 ; CHECK-NEXT: movl %esi, %ecx
165 ; CHECK-NEXT: rorb %cl, %dil
166 ; CHECK-NEXT: movl %edi, %eax
168 %amt = trunc i32 %amount to i8
169 %sub = sub i8 0, %amt
170 %maskamt = and i8 %amt, 7
171 %masksub = and i8 %sub, 7
172 %shr = lshr i8 %x, %maskamt
173 %shl = shl i8 %x, %masksub
174 %or = or i8 %shr, %shl
178 define i16 @rotate_left_16(i16 %x, i32 %amount) {
179 ; CHECK-LABEL: rotate_left_16:
181 ; CHECK-NEXT: movl %esi, %ecx
182 ; CHECK-NEXT: rolw %cl, %di
183 ; CHECK-NEXT: movl %edi, %eax
185 %amt = trunc i32 %amount to i16
186 %sub = sub i16 0, %amt
187 %maskamt = and i16 %amt, 15
188 %masksub = and i16 %sub, 15
189 %shl = shl i16 %x, %maskamt
190 %shr = lshr i16 %x, %masksub
191 %or = or i16 %shl, %shr
195 define i16 @rotate_right_16(i16 %x, i32 %amount) {
196 ; CHECK-LABEL: rotate_right_16:
198 ; CHECK-NEXT: movl %esi, %ecx
199 ; CHECK-NEXT: rorw %cl, %di
200 ; CHECK-NEXT: movl %edi, %eax
202 %amt = trunc i32 %amount to i16
203 %sub = sub i16 0, %amt
204 %maskamt = and i16 %amt, 15
205 %masksub = and i16 %sub, 15
206 %shr = lshr i16 %x, %maskamt
207 %shl = shl i16 %x, %masksub
208 %or = or i16 %shr, %shl
212 define void @rotate_left_m8(i8* %p, i32 %amount) {
213 ; CHECK-LABEL: rotate_left_m8:
215 ; CHECK-NEXT: movl %esi, %ecx
216 ; CHECK-NEXT: rolb %cl, (%rdi)
218 %x = load i8, i8* %p, align 1
219 %amt = trunc i32 %amount to i8
220 %sub = sub i8 0, %amt
221 %maskamt = and i8 %amt, 7
222 %masksub = and i8 %sub, 7
223 %shl = shl i8 %x, %maskamt
224 %shr = lshr i8 %x, %masksub
225 %or = or i8 %shl, %shr
226 store i8 %or, i8* %p, align 1
230 define void @rotate_right_m8(i8* %p, i32 %amount) {
231 ; CHECK-LABEL: rotate_right_m8:
233 ; CHECK-NEXT: movl %esi, %ecx
234 ; CHECK-NEXT: rorb %cl, (%rdi)
236 %x = load i8, i8* %p, align 1
237 %amt = trunc i32 %amount to i8
238 %sub = sub i8 0, %amt
239 %maskamt = and i8 %amt, 7
240 %masksub = and i8 %sub, 7
241 %shl = shl i8 %x, %masksub
242 %shr = lshr i8 %x, %maskamt
243 %or = or i8 %shl, %shr
244 store i8 %or, i8* %p, align 1
248 define void @rotate_left_m16(i16* %p, i32 %amount) {
249 ; CHECK-LABEL: rotate_left_m16:
251 ; CHECK-NEXT: movl %esi, %ecx
252 ; CHECK-NEXT: rolw %cl, (%rdi)
254 %x = load i16, i16* %p, align 1
255 %amt = trunc i32 %amount to i16
256 %sub = sub i16 0, %amt
257 %maskamt = and i16 %amt, 15
258 %masksub = and i16 %sub, 15
259 %shl = shl i16 %x, %maskamt
260 %shr = lshr i16 %x, %masksub
261 %or = or i16 %shl, %shr
262 store i16 %or, i16* %p, align 1
266 define void @rotate_right_m16(i16* %p, i32 %amount) {
267 ; CHECK-LABEL: rotate_right_m16:
269 ; CHECK-NEXT: movl %esi, %ecx
270 ; CHECK-NEXT: rorw %cl, (%rdi)
272 %x = load i16, i16* %p, align 1
273 %amt = trunc i32 %amount to i16
274 %sub = sub i16 0, %amt
275 %maskamt = and i16 %amt, 15
276 %masksub = and i16 %sub, 15
277 %shl = shl i16 %x, %masksub
278 %shr = lshr i16 %x, %maskamt
279 %or = or i16 %shl, %shr
280 store i16 %or, i16* %p, align 1