| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s -check-prefixes=CHECK,SSE,SSE2 |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s -check-prefixes=CHECK,SSE,SSE42 |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s -check-prefixes=CHECK,AVX,AVX2 |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=knl | FileCheck %s -check-prefixes=CHECK,AVX,AVX512,AVX512F |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s -check-prefixes=CHECK,AVX,AVX512,AVX512VL |
| ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 -mattr=+avx512vbmi2 | FileCheck %s -check-prefixes=CHECK,AVX,AVX512,AVX512VBMI |
| |
| define i128 @fshl_i128(i128 %a0, i128 %a1, i128 %a2) nounwind { |
| ; CHECK-LABEL: fshl_i128: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: testb $64, %r8b |
| ; CHECK-NEXT: cmovneq %rdi, %rsi |
| ; CHECK-NEXT: cmoveq %rcx, %rdx |
| ; CHECK-NEXT: cmovneq %rcx, %rdi |
| ; CHECK-NEXT: movq %rdi, %rax |
| ; CHECK-NEXT: movl %r8d, %ecx |
| ; CHECK-NEXT: shldq %cl, %rdx, %rax |
| ; CHECK-NEXT: shldq %cl, %rdi, %rsi |
| ; CHECK-NEXT: movq %rsi, %rdx |
| ; CHECK-NEXT: retq |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_i128(i128 %a0, i128 %a1, i128 %a2) nounwind { |
| ; SSE-LABEL: fshr_i128: |
| ; SSE: # %bb.0: |
| ; SSE-NEXT: testb $64, %r8b |
| ; SSE-NEXT: cmoveq %rdi, %rsi |
| ; SSE-NEXT: cmoveq %rcx, %rdi |
| ; SSE-NEXT: movq %rdx, %rax |
| ; SSE-NEXT: cmovneq %rcx, %rax |
| ; SSE-NEXT: movl %r8d, %ecx |
| ; SSE-NEXT: shrdq %cl, %rdi, %rax |
| ; SSE-NEXT: shrdq %cl, %rsi, %rdi |
| ; SSE-NEXT: movq %rdi, %rdx |
| ; SSE-NEXT: retq |
| ; |
| ; AVX-LABEL: fshr_i128: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: movq %rdx, %rax |
| ; AVX-NEXT: testb $64, %r8b |
| ; AVX-NEXT: cmoveq %rdi, %rsi |
| ; AVX-NEXT: cmoveq %rcx, %rdi |
| ; AVX-NEXT: cmovneq %rcx, %rax |
| ; AVX-NEXT: movl %r8d, %ecx |
| ; AVX-NEXT: shrdq %cl, %rdi, %rax |
| ; AVX-NEXT: shrdq %cl, %rsi, %rdi |
| ; AVX-NEXT: movq %rdi, %rdx |
| ; AVX-NEXT: retq |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshl_rot_i128(i128 %a0, i128 %a1) nounwind { |
| ; CHECK-LABEL: fshl_rot_i128: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rdx, %rcx |
| ; CHECK-NEXT: testb $64, %cl |
| ; CHECK-NEXT: movq %rsi, %rdx |
| ; CHECK-NEXT: cmovneq %rdi, %rdx |
| ; CHECK-NEXT: cmovneq %rsi, %rdi |
| ; CHECK-NEXT: movq %rdi, %rax |
| ; CHECK-NEXT: shldq %cl, %rdx, %rax |
| ; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; CHECK-NEXT: shldq %cl, %rdi, %rdx |
| ; CHECK-NEXT: retq |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a0, i128 %a1) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_rot_i128(i128 %a0, i128 %a1) nounwind { |
| ; CHECK-LABEL: fshr_rot_i128: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rdx, %rcx |
| ; CHECK-NEXT: testb $64, %cl |
| ; CHECK-NEXT: movq %rdi, %rdx |
| ; CHECK-NEXT: cmoveq %rsi, %rdx |
| ; CHECK-NEXT: cmoveq %rdi, %rsi |
| ; CHECK-NEXT: movq %rsi, %rax |
| ; CHECK-NEXT: shrdq %cl, %rdx, %rax |
| ; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; CHECK-NEXT: shrdq %cl, %rsi, %rdx |
| ; CHECK-NEXT: retq |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a0, i128 %a1) |
| ret i128 %r |
| } |
| |
| define i128 @fshl_i128_load(ptr %p0, ptr %p1, i128 %a2) nounwind { |
| ; SSE-LABEL: fshl_i128_load: |
| ; SSE: # %bb.0: |
| ; SSE-NEXT: movq %rdx, %rcx |
| ; SSE-NEXT: movq (%rdi), %r8 |
| ; SSE-NEXT: testb $64, %cl |
| ; SSE-NEXT: movq 8(%rdi), %rdx |
| ; SSE-NEXT: cmovneq %r8, %rdx |
| ; SSE-NEXT: movq 8(%rsi), %rax |
| ; SSE-NEXT: movq (%rsi), %rsi |
| ; SSE-NEXT: cmoveq %rax, %rsi |
| ; SSE-NEXT: cmovneq %rax, %r8 |
| ; SSE-NEXT: movq %r8, %rax |
| ; SSE-NEXT: shldq %cl, %rsi, %rax |
| ; SSE-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE-NEXT: shldq %cl, %r8, %rdx |
| ; SSE-NEXT: retq |
| ; |
| ; AVX-LABEL: fshl_i128_load: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: movq %rdx, %rcx |
| ; AVX-NEXT: movq (%rdi), %r8 |
| ; AVX-NEXT: movq 8(%rsi), %rax |
| ; AVX-NEXT: testb $64, %cl |
| ; AVX-NEXT: movq 8(%rdi), %rdx |
| ; AVX-NEXT: cmovneq %r8, %rdx |
| ; AVX-NEXT: movq (%rsi), %rsi |
| ; AVX-NEXT: cmoveq %rax, %rsi |
| ; AVX-NEXT: cmovneq %rax, %r8 |
| ; AVX-NEXT: movq %r8, %rax |
| ; AVX-NEXT: shldq %cl, %rsi, %rax |
| ; AVX-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX-NEXT: shldq %cl, %r8, %rdx |
| ; AVX-NEXT: retq |
| %a0 = load i128, ptr %p0 |
| %a1 = load i128, ptr %p1 |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_i128_load(ptr %p0, ptr %p1, i128 %a2) nounwind { |
| ; CHECK-LABEL: fshr_i128_load: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rdx, %rcx |
| ; CHECK-NEXT: movq (%rdi), %rdx |
| ; CHECK-NEXT: movq 8(%rsi), %rax |
| ; CHECK-NEXT: testb $64, %cl |
| ; CHECK-NEXT: movq 8(%rdi), %rdi |
| ; CHECK-NEXT: cmoveq %rdx, %rdi |
| ; CHECK-NEXT: cmoveq %rax, %rdx |
| ; CHECK-NEXT: cmoveq (%rsi), %rax |
| ; CHECK-NEXT: shrdq %cl, %rdx, %rax |
| ; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; CHECK-NEXT: shrdq %cl, %rdi, %rdx |
| ; CHECK-NEXT: retq |
| %a0 = load i128, ptr %p0 |
| %a1 = load i128, ptr %p1 |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshl_rot_i128_load(ptr %p0, i128 %a2) nounwind { |
| ; CHECK-LABEL: fshl_rot_i128_load: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rsi, %rcx |
| ; CHECK-NEXT: movq (%rdi), %rsi |
| ; CHECK-NEXT: movq 8(%rdi), %rax |
| ; CHECK-NEXT: testb $64, %cl |
| ; CHECK-NEXT: movq %rax, %rdx |
| ; CHECK-NEXT: cmovneq %rsi, %rdx |
| ; CHECK-NEXT: cmovneq %rax, %rsi |
| ; CHECK-NEXT: movq %rsi, %rax |
| ; CHECK-NEXT: shldq %cl, %rdx, %rax |
| ; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; CHECK-NEXT: shldq %cl, %rsi, %rdx |
| ; CHECK-NEXT: retq |
| %a0 = load i128, ptr %p0 |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a0, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_rot_i128_load(ptr %p0, i128 %a2) nounwind { |
| ; CHECK-LABEL: fshr_rot_i128_load: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq %rsi, %rcx |
| ; CHECK-NEXT: movq (%rdi), %rax |
| ; CHECK-NEXT: movq 8(%rdi), %rsi |
| ; CHECK-NEXT: testb $64, %cl |
| ; CHECK-NEXT: movq %rax, %rdx |
| ; CHECK-NEXT: cmoveq %rsi, %rdx |
| ; CHECK-NEXT: cmoveq %rax, %rsi |
| ; CHECK-NEXT: movq %rsi, %rax |
| ; CHECK-NEXT: shrdq %cl, %rdx, %rax |
| ; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; CHECK-NEXT: shrdq %cl, %rsi, %rdx |
| ; CHECK-NEXT: retq |
| %a0 = load i128, ptr %p0 |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a0, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshl_i128_vector(<2 x i64> %v0, <2 x i64> %v1, i128 %a2) nounwind { |
| ; SSE2-LABEL: fshl_i128_vector: |
| ; SSE2: # %bb.0: |
| ; SSE2-NEXT: movq %rdi, %rcx |
| ; SSE2-NEXT: movq %xmm0, %rsi |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rdx |
| ; SSE2-NEXT: movq %xmm1, %rdi |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rax |
| ; SSE2-NEXT: testb $64, %cl |
| ; SSE2-NEXT: cmovneq %rsi, %rdx |
| ; SSE2-NEXT: cmoveq %rax, %rdi |
| ; SSE2-NEXT: cmovneq %rax, %rsi |
| ; SSE2-NEXT: movq %rsi, %rax |
| ; SSE2-NEXT: shldq %cl, %rdi, %rax |
| ; SSE2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE2-NEXT: shldq %cl, %rsi, %rdx |
| ; SSE2-NEXT: retq |
| ; |
| ; SSE42-LABEL: fshl_i128_vector: |
| ; SSE42: # %bb.0: |
| ; SSE42-NEXT: movq %rdi, %rcx |
| ; SSE42-NEXT: movq %xmm0, %rsi |
| ; SSE42-NEXT: pextrq $1, %xmm0, %rdx |
| ; SSE42-NEXT: movq %xmm1, %rdi |
| ; SSE42-NEXT: pextrq $1, %xmm1, %rax |
| ; SSE42-NEXT: testb $64, %cl |
| ; SSE42-NEXT: cmovneq %rsi, %rdx |
| ; SSE42-NEXT: cmoveq %rax, %rdi |
| ; SSE42-NEXT: cmovneq %rax, %rsi |
| ; SSE42-NEXT: movq %rsi, %rax |
| ; SSE42-NEXT: shldq %cl, %rdi, %rax |
| ; SSE42-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE42-NEXT: shldq %cl, %rsi, %rdx |
| ; SSE42-NEXT: retq |
| ; |
| ; AVX2-LABEL: fshl_i128_vector: |
| ; AVX2: # %bb.0: |
| ; AVX2-NEXT: movq %rdi, %rcx |
| ; AVX2-NEXT: vmovq %xmm0, %rsi |
| ; AVX2-NEXT: vpextrq $1, %xmm0, %rdx |
| ; AVX2-NEXT: vpextrq $1, %xmm1, %rax |
| ; AVX2-NEXT: vmovq %xmm1, %rdi |
| ; AVX2-NEXT: testb $64, %cl |
| ; AVX2-NEXT: cmovneq %rsi, %rdx |
| ; AVX2-NEXT: cmoveq %rax, %rdi |
| ; AVX2-NEXT: cmovneq %rax, %rsi |
| ; AVX2-NEXT: movq %rsi, %rax |
| ; AVX2-NEXT: shldq %cl, %rdi, %rax |
| ; AVX2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX2-NEXT: shldq %cl, %rsi, %rdx |
| ; AVX2-NEXT: retq |
| ; |
| ; AVX512F-LABEL: fshl_i128_vector: |
| ; AVX512F: # %bb.0: |
| ; AVX512F-NEXT: movq %rdi, %rcx |
| ; AVX512F-NEXT: vmovq %xmm0, %rsi |
| ; AVX512F-NEXT: vpextrq $1, %xmm0, %rdx |
| ; AVX512F-NEXT: vpextrq $1, %xmm1, %rax |
| ; AVX512F-NEXT: vmovq %xmm1, %rdi |
| ; AVX512F-NEXT: testb $64, %cl |
| ; AVX512F-NEXT: cmovneq %rsi, %rdx |
| ; AVX512F-NEXT: cmoveq %rax, %rdi |
| ; AVX512F-NEXT: cmovneq %rax, %rsi |
| ; AVX512F-NEXT: movq %rsi, %rax |
| ; AVX512F-NEXT: shldq %cl, %rdi, %rax |
| ; AVX512F-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512F-NEXT: shldq %cl, %rsi, %rdx |
| ; AVX512F-NEXT: retq |
| ; |
| ; AVX512VL-LABEL: fshl_i128_vector: |
| ; AVX512VL: # %bb.0: |
| ; AVX512VL-NEXT: movq %rdi, %rcx |
| ; AVX512VL-NEXT: vpextrq $1, %xmm0, %rdx |
| ; AVX512VL-NEXT: vmovq %xmm0, %rsi |
| ; AVX512VL-NEXT: vmovq %xmm1, %rdi |
| ; AVX512VL-NEXT: vpextrq $1, %xmm1, %rax |
| ; AVX512VL-NEXT: testb $64, %cl |
| ; AVX512VL-NEXT: cmovneq %rsi, %rdx |
| ; AVX512VL-NEXT: cmoveq %rax, %rdi |
| ; AVX512VL-NEXT: cmovneq %rax, %rsi |
| ; AVX512VL-NEXT: movq %rsi, %rax |
| ; AVX512VL-NEXT: shldq %cl, %rdi, %rax |
| ; AVX512VL-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512VL-NEXT: shldq %cl, %rsi, %rdx |
| ; AVX512VL-NEXT: retq |
| ; |
| ; AVX512VBMI-LABEL: fshl_i128_vector: |
| ; AVX512VBMI: # %bb.0: |
| ; AVX512VBMI-NEXT: movq %rdi, %rcx |
| ; AVX512VBMI-NEXT: vpextrq $1, %xmm0, %rdx |
| ; AVX512VBMI-NEXT: vmovq %xmm0, %rsi |
| ; AVX512VBMI-NEXT: vmovq %xmm1, %rdi |
| ; AVX512VBMI-NEXT: vpextrq $1, %xmm1, %rax |
| ; AVX512VBMI-NEXT: testb $64, %cl |
| ; AVX512VBMI-NEXT: cmovneq %rsi, %rdx |
| ; AVX512VBMI-NEXT: cmoveq %rax, %rdi |
| ; AVX512VBMI-NEXT: cmovneq %rax, %rsi |
| ; AVX512VBMI-NEXT: movq %rsi, %rax |
| ; AVX512VBMI-NEXT: shldq %cl, %rdi, %rax |
| ; AVX512VBMI-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512VBMI-NEXT: shldq %cl, %rsi, %rdx |
| ; AVX512VBMI-NEXT: retq |
| %a0 = bitcast <2 x i64> %v0 to i128 |
| %a1 = bitcast <2 x i64> %v1 to i128 |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_i128_vector(<2 x i64> %v0, <2 x i64> %v1, i128 %a2) nounwind { |
| ; SSE2-LABEL: fshr_i128_vector: |
| ; SSE2: # %bb.0: |
| ; SSE2-NEXT: movq %rdi, %rcx |
| ; SSE2-NEXT: movq %xmm0, %rdx |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rsi |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rdi |
| ; SSE2-NEXT: testb $64, %cl |
| ; SSE2-NEXT: cmoveq %rdx, %rsi |
| ; SSE2-NEXT: cmoveq %rdi, %rdx |
| ; SSE2-NEXT: movq %xmm1, %rax |
| ; SSE2-NEXT: cmovneq %rdi, %rax |
| ; SSE2-NEXT: shrdq %cl, %rdx, %rax |
| ; SSE2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE2-NEXT: shrdq %cl, %rsi, %rdx |
| ; SSE2-NEXT: retq |
| ; |
| ; SSE42-LABEL: fshr_i128_vector: |
| ; SSE42: # %bb.0: |
| ; SSE42-NEXT: movq %rdi, %rcx |
| ; SSE42-NEXT: pextrq $1, %xmm0, %rsi |
| ; SSE42-NEXT: movq %xmm0, %rdx |
| ; SSE42-NEXT: pextrq $1, %xmm1, %rdi |
| ; SSE42-NEXT: testb $64, %cl |
| ; SSE42-NEXT: cmoveq %rdx, %rsi |
| ; SSE42-NEXT: cmoveq %rdi, %rdx |
| ; SSE42-NEXT: movq %xmm1, %rax |
| ; SSE42-NEXT: cmovneq %rdi, %rax |
| ; SSE42-NEXT: shrdq %cl, %rdx, %rax |
| ; SSE42-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE42-NEXT: shrdq %cl, %rsi, %rdx |
| ; SSE42-NEXT: retq |
| ; |
| ; AVX2-LABEL: fshr_i128_vector: |
| ; AVX2: # %bb.0: |
| ; AVX2-NEXT: movq %rdi, %rcx |
| ; AVX2-NEXT: vmovq %xmm0, %rdx |
| ; AVX2-NEXT: vpextrq $1, %xmm0, %rsi |
| ; AVX2-NEXT: vpextrq $1, %xmm1, %rdi |
| ; AVX2-NEXT: vmovq %xmm1, %rax |
| ; AVX2-NEXT: testb $64, %cl |
| ; AVX2-NEXT: cmoveq %rdx, %rsi |
| ; AVX2-NEXT: cmoveq %rdi, %rdx |
| ; AVX2-NEXT: cmovneq %rdi, %rax |
| ; AVX2-NEXT: shrdq %cl, %rdx, %rax |
| ; AVX2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX2-NEXT: shrdq %cl, %rsi, %rdx |
| ; AVX2-NEXT: retq |
| ; |
| ; AVX512F-LABEL: fshr_i128_vector: |
| ; AVX512F: # %bb.0: |
| ; AVX512F-NEXT: movq %rdi, %rcx |
| ; AVX512F-NEXT: vmovq %xmm0, %rdx |
| ; AVX512F-NEXT: vpextrq $1, %xmm0, %rsi |
| ; AVX512F-NEXT: vpextrq $1, %xmm1, %rdi |
| ; AVX512F-NEXT: vmovq %xmm1, %rax |
| ; AVX512F-NEXT: testb $64, %cl |
| ; AVX512F-NEXT: cmoveq %rdx, %rsi |
| ; AVX512F-NEXT: cmoveq %rdi, %rdx |
| ; AVX512F-NEXT: cmovneq %rdi, %rax |
| ; AVX512F-NEXT: shrdq %cl, %rdx, %rax |
| ; AVX512F-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512F-NEXT: shrdq %cl, %rsi, %rdx |
| ; AVX512F-NEXT: retq |
| ; |
| ; AVX512VL-LABEL: fshr_i128_vector: |
| ; AVX512VL: # %bb.0: |
| ; AVX512VL-NEXT: movq %rdi, %rcx |
| ; AVX512VL-NEXT: vpextrq $1, %xmm0, %rsi |
| ; AVX512VL-NEXT: vmovq %xmm0, %rdx |
| ; AVX512VL-NEXT: vmovq %xmm1, %rax |
| ; AVX512VL-NEXT: vpextrq $1, %xmm1, %rdi |
| ; AVX512VL-NEXT: testb $64, %cl |
| ; AVX512VL-NEXT: cmoveq %rdx, %rsi |
| ; AVX512VL-NEXT: cmoveq %rdi, %rdx |
| ; AVX512VL-NEXT: cmovneq %rdi, %rax |
| ; AVX512VL-NEXT: shrdq %cl, %rdx, %rax |
| ; AVX512VL-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512VL-NEXT: shrdq %cl, %rsi, %rdx |
| ; AVX512VL-NEXT: retq |
| ; |
| ; AVX512VBMI-LABEL: fshr_i128_vector: |
| ; AVX512VBMI: # %bb.0: |
| ; AVX512VBMI-NEXT: movq %rdi, %rcx |
| ; AVX512VBMI-NEXT: vpextrq $1, %xmm0, %rsi |
| ; AVX512VBMI-NEXT: vmovq %xmm0, %rdx |
| ; AVX512VBMI-NEXT: vmovq %xmm1, %rax |
| ; AVX512VBMI-NEXT: vpextrq $1, %xmm1, %rdi |
| ; AVX512VBMI-NEXT: testb $64, %cl |
| ; AVX512VBMI-NEXT: cmoveq %rdx, %rsi |
| ; AVX512VBMI-NEXT: cmoveq %rdi, %rdx |
| ; AVX512VBMI-NEXT: cmovneq %rdi, %rax |
| ; AVX512VBMI-NEXT: shrdq %cl, %rdx, %rax |
| ; AVX512VBMI-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX512VBMI-NEXT: shrdq %cl, %rsi, %rdx |
| ; AVX512VBMI-NEXT: retq |
| %a0 = bitcast <2 x i64> %v0 to i128 |
| %a1 = bitcast <2 x i64> %v1 to i128 |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a1, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshl_rot_i128_vector(<2 x i64> %v0, i128 %a2) nounwind { |
| ; SSE2-LABEL: fshl_rot_i128_vector: |
| ; SSE2: # %bb.0: |
| ; SSE2-NEXT: movq %rdi, %rcx |
| ; SSE2-NEXT: movq %xmm0, %rsi |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rax |
| ; SSE2-NEXT: testb $64, %cl |
| ; SSE2-NEXT: movq %rax, %rdx |
| ; SSE2-NEXT: cmovneq %rsi, %rdx |
| ; SSE2-NEXT: cmovneq %rax, %rsi |
| ; SSE2-NEXT: movq %rsi, %rax |
| ; SSE2-NEXT: shldq %cl, %rdx, %rax |
| ; SSE2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE2-NEXT: shldq %cl, %rsi, %rdx |
| ; SSE2-NEXT: retq |
| ; |
| ; SSE42-LABEL: fshl_rot_i128_vector: |
| ; SSE42: # %bb.0: |
| ; SSE42-NEXT: movq %rdi, %rcx |
| ; SSE42-NEXT: movq %xmm0, %rsi |
| ; SSE42-NEXT: pextrq $1, %xmm0, %rax |
| ; SSE42-NEXT: testb $64, %cl |
| ; SSE42-NEXT: movq %rax, %rdx |
| ; SSE42-NEXT: cmovneq %rsi, %rdx |
| ; SSE42-NEXT: cmovneq %rax, %rsi |
| ; SSE42-NEXT: movq %rsi, %rax |
| ; SSE42-NEXT: shldq %cl, %rdx, %rax |
| ; SSE42-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE42-NEXT: shldq %cl, %rsi, %rdx |
| ; SSE42-NEXT: retq |
| ; |
| ; AVX-LABEL: fshl_rot_i128_vector: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: movq %rdi, %rcx |
| ; AVX-NEXT: vmovq %xmm0, %rsi |
| ; AVX-NEXT: vpextrq $1, %xmm0, %rax |
| ; AVX-NEXT: testb $64, %cl |
| ; AVX-NEXT: movq %rax, %rdx |
| ; AVX-NEXT: cmovneq %rsi, %rdx |
| ; AVX-NEXT: cmovneq %rax, %rsi |
| ; AVX-NEXT: movq %rsi, %rax |
| ; AVX-NEXT: shldq %cl, %rdx, %rax |
| ; AVX-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX-NEXT: shldq %cl, %rsi, %rdx |
| ; AVX-NEXT: retq |
| %a0 = bitcast <2 x i64> %v0 to i128 |
| %r = call i128 @llvm.fshl.i128(i128 %a0, i128 %a0, i128 %a2) |
| ret i128 %r |
| } |
| |
| define i128 @fshr_rot_i128_vector(<2 x i64> %v0, i128 %a2) nounwind { |
| ; SSE2-LABEL: fshr_rot_i128_vector: |
| ; SSE2: # %bb.0: |
| ; SSE2-NEXT: movq %rdi, %rcx |
| ; SSE2-NEXT: movq %xmm0, %rax |
| ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] |
| ; SSE2-NEXT: movq %xmm0, %rsi |
| ; SSE2-NEXT: testb $64, %cl |
| ; SSE2-NEXT: movq %rax, %rdx |
| ; SSE2-NEXT: cmoveq %rsi, %rdx |
| ; SSE2-NEXT: cmoveq %rax, %rsi |
| ; SSE2-NEXT: movq %rsi, %rax |
| ; SSE2-NEXT: shrdq %cl, %rdx, %rax |
| ; SSE2-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE2-NEXT: shrdq %cl, %rsi, %rdx |
| ; SSE2-NEXT: retq |
| ; |
| ; SSE42-LABEL: fshr_rot_i128_vector: |
| ; SSE42: # %bb.0: |
| ; SSE42-NEXT: movq %rdi, %rcx |
| ; SSE42-NEXT: pextrq $1, %xmm0, %rsi |
| ; SSE42-NEXT: movq %xmm0, %rax |
| ; SSE42-NEXT: testb $64, %cl |
| ; SSE42-NEXT: movq %rax, %rdx |
| ; SSE42-NEXT: cmoveq %rsi, %rdx |
| ; SSE42-NEXT: cmoveq %rax, %rsi |
| ; SSE42-NEXT: movq %rsi, %rax |
| ; SSE42-NEXT: shrdq %cl, %rdx, %rax |
| ; SSE42-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; SSE42-NEXT: shrdq %cl, %rsi, %rdx |
| ; SSE42-NEXT: retq |
| ; |
| ; AVX-LABEL: fshr_rot_i128_vector: |
| ; AVX: # %bb.0: |
| ; AVX-NEXT: movq %rdi, %rcx |
| ; AVX-NEXT: vpextrq $1, %xmm0, %rsi |
| ; AVX-NEXT: vmovq %xmm0, %rax |
| ; AVX-NEXT: testb $64, %cl |
| ; AVX-NEXT: movq %rax, %rdx |
| ; AVX-NEXT: cmoveq %rsi, %rdx |
| ; AVX-NEXT: cmoveq %rax, %rsi |
| ; AVX-NEXT: movq %rsi, %rax |
| ; AVX-NEXT: shrdq %cl, %rdx, %rax |
| ; AVX-NEXT: # kill: def $cl killed $cl killed $rcx |
| ; AVX-NEXT: shrdq %cl, %rsi, %rdx |
| ; AVX-NEXT: retq |
| %a0 = bitcast <2 x i64> %v0 to i128 |
| %r = call i128 @llvm.fshr.i128(i128 %a0, i128 %a0, i128 %a2) |
| ret i128 %r |
| } |
| |
| ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: |
| ; AVX512: {{.*}} |