1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=i686-- | FileCheck %s --check-prefixes=X86,X86-BASE
3 ; RUN: llc < %s -mtriple=i686-- -mattr=movbe | FileCheck %s --check-prefixes=X86,X86-MOVBE
4 ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=X64,X64-BASE
5 ; RUN: llc < %s -mtriple=x86_64-- -mattr=movbe | FileCheck %s --check-prefixes=X64,X64-MOVBE
7 define i16 @foo(i16 %x, i16 %y, i16 %z) nounwind {
10 ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
11 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
12 ; X86-NEXT: rolw %cl, %ax
17 ; X64-NEXT: movl %edx, %ecx
18 ; X64-NEXT: movl %edi, %eax
19 ; X64-NEXT: # kill: def $cl killed $cl killed $ecx
20 ; X64-NEXT: rolw %cl, %ax
21 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
25 %t2 = lshr i16 %x, %t1
30 define i16 @bar(i16 %x, i16 %y, i16 %z) nounwind {
33 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx
34 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
35 ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
36 ; X86-NEXT: andb $15, %cl
37 ; X86-NEXT: shldw %cl, %dx, %ax
42 ; X64-NEXT: movl %edx, %ecx
43 ; X64-NEXT: movl %esi, %eax
44 ; X64-NEXT: andb $15, %cl
45 ; X64-NEXT: # kill: def $cl killed $cl killed $ecx
46 ; X64-NEXT: shldw %cl, %di, %ax
47 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
51 %t2 = lshr i16 %x, %t1
56 define i16 @un(i16 %x, i16 %y, i16 %z) nounwind {
59 ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
60 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
61 ; X86-NEXT: rorw %cl, %ax
66 ; X64-NEXT: movl %edx, %ecx
67 ; X64-NEXT: movl %edi, %eax
68 ; X64-NEXT: # kill: def $cl killed $cl killed $ecx
69 ; X64-NEXT: rorw %cl, %ax
70 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
79 define i16 @bu(i16 %x, i16 %y, i16 %z) nounwind {
82 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx
83 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
84 ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
85 ; X86-NEXT: andb $15, %cl
86 ; X86-NEXT: shrdw %cl, %dx, %ax
91 ; X64-NEXT: movl %edx, %ecx
92 ; X64-NEXT: movl %esi, %eax
93 ; X64-NEXT: andb $15, %cl
94 ; X64-NEXT: # kill: def $cl killed $cl killed $ecx
95 ; X64-NEXT: shrdw %cl, %di, %ax
96 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
100 %t2 = shl i16 %x, %t1
101 %t3 = or i16 %t2, %t0
105 define i16 @xfoo(i16 %x, i16 %y, i16 %z) nounwind {
108 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
109 ; X86-NEXT: rolw $5, %ax
114 ; X64-NEXT: movl %edi, %eax
115 ; X64-NEXT: rolw $5, %ax
116 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
118 %t0 = lshr i16 %x, 11
120 %t2 = or i16 %t0, %t1
124 define i16 @xbar(i16 %x, i16 %y, i16 %z) nounwind {
127 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %ecx
128 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
129 ; X86-NEXT: shldw $5, %cx, %ax
134 ; X64-NEXT: movl %esi, %eax
135 ; X64-NEXT: shldw $5, %di, %ax
136 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
139 %t1 = lshr i16 %x, 11
140 %t2 = or i16 %t0, %t1
144 define i16 @xun(i16 %x, i16 %y, i16 %z) nounwind {
147 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
148 ; X86-NEXT: rolw $11, %ax
153 ; X64-NEXT: movl %edi, %eax
154 ; X64-NEXT: rolw $11, %ax
155 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
159 %t2 = or i16 %t0, %t1
163 define i16 @xbu(i16 %x, i16 %y, i16 %z) nounwind {
166 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %ecx
167 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
168 ; X86-NEXT: shldw $11, %cx, %ax
173 ; X64-NEXT: movl %edi, %eax
174 ; X64-NEXT: shldw $11, %si, %ax
175 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
179 %t2 = or i16 %t0, %t1
183 define i32 @rot16_demandedbits(i32 %x, i32 %y) nounwind {
184 ; X86-LABEL: rot16_demandedbits:
186 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
187 ; X86-NEXT: movl %eax, %ecx
188 ; X86-NEXT: shrl $11, %ecx
189 ; X86-NEXT: shll $5, %eax
190 ; X86-NEXT: orl %ecx, %eax
191 ; X86-NEXT: movzwl %ax, %eax
194 ; X64-LABEL: rot16_demandedbits:
196 ; X64-NEXT: movl %edi, %eax
197 ; X64-NEXT: shrl $11, %eax
198 ; X64-NEXT: shll $5, %edi
199 ; X64-NEXT: orl %eax, %edi
200 ; X64-NEXT: movzwl %di, %eax
202 %t0 = lshr i32 %x, 11
204 %t2 = or i32 %t0, %t1
205 %t3 = and i32 %t2, 65535
209 define i16 @rot16_trunc(i32 %x, i32 %y) nounwind {
210 ; X86-LABEL: rot16_trunc:
212 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
213 ; X86-NEXT: movl %eax, %ecx
214 ; X86-NEXT: shrl $11, %ecx
215 ; X86-NEXT: shll $5, %eax
216 ; X86-NEXT: orl %ecx, %eax
217 ; X86-NEXT: # kill: def $ax killed $ax killed $eax
220 ; X64-LABEL: rot16_trunc:
222 ; X64-NEXT: movl %edi, %eax
223 ; X64-NEXT: shrl $11, %eax
224 ; X64-NEXT: shll $5, %edi
225 ; X64-NEXT: orl %edi, %eax
226 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
228 %t0 = lshr i32 %x, 11
230 %t2 = or i32 %t0, %t1
231 %t3 = trunc i32 %t2 to i16
235 define i16 @rotate16(i16 %x) {
236 ; X86-BASE-LABEL: rotate16:
238 ; X86-BASE-NEXT: movzwl {{[0-9]+}}(%esp), %eax
239 ; X86-BASE-NEXT: rolw $8, %ax
240 ; X86-BASE-NEXT: retl
242 ; X86-MOVBE-LABEL: rotate16:
243 ; X86-MOVBE: # %bb.0:
244 ; X86-MOVBE-NEXT: movbew {{[0-9]+}}(%esp), %ax
245 ; X86-MOVBE-NEXT: retl
247 ; X64-LABEL: rotate16:
249 ; X64-NEXT: movl %edi, %eax
250 ; X64-NEXT: rolw $8, %ax
251 ; X64-NEXT: # kill: def $ax killed $ax killed $eax
253 %r = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 8)
257 ; TODO: Should this always be rolw with memory operand?
259 define void @rotate16_in_place_memory(ptr %p) {
260 ; X86-BASE-LABEL: rotate16_in_place_memory:
262 ; X86-BASE-NEXT: movl {{[0-9]+}}(%esp), %eax
263 ; X86-BASE-NEXT: rolw $8, (%eax)
264 ; X86-BASE-NEXT: retl
266 ; X86-MOVBE-LABEL: rotate16_in_place_memory:
267 ; X86-MOVBE: # %bb.0:
268 ; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax
269 ; X86-MOVBE-NEXT: movzwl (%eax), %ecx
270 ; X86-MOVBE-NEXT: movbew %cx, (%eax)
271 ; X86-MOVBE-NEXT: retl
273 ; X64-BASE-LABEL: rotate16_in_place_memory:
275 ; X64-BASE-NEXT: rolw $8, (%rdi)
276 ; X64-BASE-NEXT: retq
278 ; X64-MOVBE-LABEL: rotate16_in_place_memory:
279 ; X64-MOVBE: # %bb.0:
280 ; X64-MOVBE-NEXT: movzwl (%rdi), %eax
281 ; X64-MOVBE-NEXT: movbew %ax, (%rdi)
282 ; X64-MOVBE-NEXT: retq
283 %p1 = getelementptr i8, ptr %p, i64 1
284 %i0 = load i8, ptr %p, align 1
285 %i1 = load i8, ptr %p1, align 1
286 store i8 %i1, ptr %p, align 1
287 store i8 %i0, ptr %p1, align 1
291 define void @rotate16_memory(ptr %p, ptr %q) {
292 ; X86-BASE-LABEL: rotate16_memory:
294 ; X86-BASE-NEXT: movl {{[0-9]+}}(%esp), %eax
295 ; X86-BASE-NEXT: movl {{[0-9]+}}(%esp), %ecx
296 ; X86-BASE-NEXT: movzwl (%ecx), %ecx
297 ; X86-BASE-NEXT: rolw $8, %cx
298 ; X86-BASE-NEXT: movw %cx, (%eax)
299 ; X86-BASE-NEXT: retl
301 ; X86-MOVBE-LABEL: rotate16_memory:
302 ; X86-MOVBE: # %bb.0:
303 ; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax
304 ; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %ecx
305 ; X86-MOVBE-NEXT: movzwl (%ecx), %ecx
306 ; X86-MOVBE-NEXT: movbew %cx, (%eax)
307 ; X86-MOVBE-NEXT: retl
309 ; X64-BASE-LABEL: rotate16_memory:
311 ; X64-BASE-NEXT: movzwl (%rdi), %eax
312 ; X64-BASE-NEXT: rolw $8, %ax
313 ; X64-BASE-NEXT: movw %ax, (%rsi)
314 ; X64-BASE-NEXT: retq
316 ; X64-MOVBE-LABEL: rotate16_memory:
317 ; X64-MOVBE: # %bb.0:
318 ; X64-MOVBE-NEXT: movzwl (%rdi), %eax
319 ; X64-MOVBE-NEXT: movbew %ax, (%rsi)
320 ; X64-MOVBE-NEXT: retq
321 %p1 = getelementptr i8, ptr %p, i64 1
322 %q1 = getelementptr i8, ptr %q, i64 1
323 %i0 = load i8, ptr %p, align 1
324 %i1 = load i8, ptr %p1, align 1
325 store i8 %i1, ptr %q, align 1
326 store i8 %i0, ptr %q1, align 1
330 declare i16 @llvm.fshl.i16(i16, i16, i16)