[llvm] [X86] Widen non-power-of-two vector div/rem under strictfp (PR #217572)
Adam Scott via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 03:12:10 PDT 2026
https://github.com/as4230 created https://github.com/llvm/llvm-project/pull/217572
Non power of two vectors bail out of the FP divide fold under strictfp and scalarize. The SAE forms are 512-bit only so operands widen into a zmm, and a non power of two lane count has no machine type to widen through.
This widens to the next power of two first but only while the result still fits one divide. Past that it splits into two chains and a scalar divide on the odd lane is cheaper so a shape like v9i32 is unchanged.
Fixes #217558
>From cb0235744e67a2ad18bed72cc7ff841135a85b47 Mon Sep 17 00:00:00 2001
From: Adam Scott <adamscott200322 at gmail.com>
Date: Thu, 20 Aug 2026 09:58:36 +0000
Subject: [PATCH 1/2] Add non pow2 strictfp vector div test cov
---
llvm/test/CodeGen/X86/vector-idiv-strictfp.ll | 283 ++++++++++++++++++
1 file changed, 283 insertions(+)
diff --git a/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll b/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
index 7add2e5ac4d6c..408c8b9e61864 100644
--- a/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
+++ b/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
@@ -201,3 +201,286 @@ define void @test_divv_32i32_strictfp(<32 x i32> %a, <32 x i32> %b, ptr %p) noun
store <32 x i32> %res, ptr %p
ret void
}
+
+define void @test_divv_7i32_strictfp(<7 x i32> %a, <7 x i32> %b, ptr %p) nounwind strictfp {
+; CHECK-LABEL: test_divv_7i32_strictfp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm2
+; CHECK-NEXT: vpextrd $1, %xmm2, %eax
+; CHECK-NEXT: vextracti128 $1, %ymm1, %xmm3
+; CHECK-NEXT: vpextrd $1, %xmm3, %ecx
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divl %ecx
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: vmovd %xmm2, %eax
+; CHECK-NEXT: vmovd %xmm3, %esi
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divl %esi
+; CHECK-NEXT: vmovd %eax, %xmm4
+; CHECK-NEXT: vpinsrd $1, %ecx, %xmm4, %xmm4
+; CHECK-NEXT: vpextrd $2, %xmm2, %eax
+; CHECK-NEXT: vpextrd $2, %xmm3, %ecx
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divl %ecx
+; CHECK-NEXT: vcvtudq2pd %ymm1, %zmm1
+; CHECK-NEXT: vcvtudq2pd %ymm0, %zmm0
+; CHECK-NEXT: vdivpd {rn-sae}, %zmm1, %zmm0, %zmm0
+; CHECK-NEXT: vcvttpd2udq {sae}, %zmm0, %ymm0
+; CHECK-NEXT: movl %eax, 24(%rdi)
+; CHECK-NEXT: vmovaps %xmm0, (%rdi)
+; CHECK-NEXT: vmovq %xmm4, 16(%rdi)
+; CHECK-NEXT: vzeroupper
+; CHECK-NEXT: retq
+ %res = udiv <7 x i32> %a, %b
+ store <7 x i32> %res, ptr %p
+ ret void
+}
+
+define void @test_divv_7i16_strictfp(<7 x i16> %a, <7 x i16> %b, ptr %p) nounwind strictfp {
+; CHECK-LABEL: test_divv_7i16_strictfp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpextrw $1, %xmm0, %eax
+; CHECK-NEXT: vpextrw $1, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: vmovd %xmm0, %eax
+; CHECK-NEXT: vmovd %xmm1, %esi
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %si
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vmovd %eax, %xmm2
+; CHECK-NEXT: vpinsrw $1, %ecx, %xmm2, %xmm2
+; CHECK-NEXT: vpextrw $2, %xmm0, %eax
+; CHECK-NEXT: vpextrw $2, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $2, %eax, %xmm2, %xmm2
+; CHECK-NEXT: vpextrw $3, %xmm0, %eax
+; CHECK-NEXT: vpextrw $3, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $3, %eax, %xmm2, %xmm2
+; CHECK-NEXT: vpextrw $4, %xmm0, %eax
+; CHECK-NEXT: vpextrw $4, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $4, %eax, %xmm2, %xmm2
+; CHECK-NEXT: vpextrw $5, %xmm0, %eax
+; CHECK-NEXT: vpextrw $5, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $5, %eax, %xmm2, %xmm2
+; CHECK-NEXT: vpextrw $6, %xmm0, %eax
+; CHECK-NEXT: vpextrw $6, %xmm1, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $6, %eax, %xmm2, %xmm0
+; CHECK-NEXT: movw %ax, 12(%rdi)
+; CHECK-NEXT: vpextrd $2, %xmm0, 8(%rdi)
+; CHECK-NEXT: vmovq %xmm0, (%rdi)
+; CHECK-NEXT: retq
+ %res = udiv <7 x i16> %a, %b
+ store <7 x i16> %res, ptr %p
+ ret void
+}
+
+define void @test_divv_15i8_strictfp(<15 x i8> %a, <15 x i8> %b, ptr %p) nounwind strictfp {
+; CHECK-LABEL: test_divv_15i8_strictfp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: vpextrb $1, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $1, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: # kill: def $al killed $al def $eax
+; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: vmovd %xmm1, %ecx
+; CHECK-NEXT: vmovd %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %esi
+; CHECK-NEXT: vpextrb $2, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $2, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %edx
+; CHECK-NEXT: vpextrb $3, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $3, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r8d
+; CHECK-NEXT: vpextrb $4, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $4, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r9d
+; CHECK-NEXT: vpextrb $5, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $5, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r10d
+; CHECK-NEXT: vpextrb $6, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $6, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r11d
+; CHECK-NEXT: vpextrb $7, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $7, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %ebx
+; CHECK-NEXT: vpextrb $8, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $8, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %ebp
+; CHECK-NEXT: vpextrb $9, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $9, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r14d
+; CHECK-NEXT: vpextrb $10, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $10, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r15d
+; CHECK-NEXT: vpextrb $11, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $11, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r12d
+; CHECK-NEXT: vpextrb $12, %xmm1, %ecx
+; CHECK-NEXT: vpextrb $12, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %r13d
+; CHECK-NEXT: vpextrb $13, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: vpextrb $13, %xmm1, %ecx
+; CHECK-NEXT: divb %cl
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: vmovd %esi, %xmm2
+; CHECK-NEXT: vpextrb $14, %xmm0, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: vpextrb $14, %xmm1, %esi
+; CHECK-NEXT: divb %sil
+; CHECK-NEXT: # kill: def $al killed $al def $eax
+; CHECK-NEXT: vpinsrb $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm2, %xmm0 # 4-byte Folded Reload
+; CHECK-NEXT: vpinsrb $2, %edx, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $3, %r8d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $4, %r9d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $5, %r10d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $6, %r11d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $7, %ebx, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $8, %ebp, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $9, %r14d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $10, %r15d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $11, %r12d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $12, %r13d, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $13, %ecx, %xmm0, %xmm0
+; CHECK-NEXT: vpinsrb $14, %eax, %xmm0, %xmm1
+; CHECK-NEXT: movb %al, 14(%rdi)
+; CHECK-NEXT: vpextrw $6, %xmm0, 12(%rdi)
+; CHECK-NEXT: vpextrd $2, %xmm1, 8(%rdi)
+; CHECK-NEXT: vmovq %xmm1, (%rdi)
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: retq
+ %res = udiv <15 x i8> %a, %b
+ store <15 x i8> %res, ptr %p
+ ret void
+}
+
+define void @test_divv_15i16_strictfp(<15 x i16> %a, <15 x i16> %b, ptr %p) nounwind strictfp {
+; CHECK-LABEL: test_divv_15i16_strictfp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm2
+; CHECK-NEXT: vpextrw $1, %xmm2, %eax
+; CHECK-NEXT: vextracti128 $1, %ymm1, %xmm3
+; CHECK-NEXT: vpextrw $1, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: vmovd %xmm2, %eax
+; CHECK-NEXT: vmovd %xmm3, %esi
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %si
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vmovd %eax, %xmm4
+; CHECK-NEXT: vpinsrw $1, %ecx, %xmm4, %xmm4
+; CHECK-NEXT: vpextrw $2, %xmm2, %eax
+; CHECK-NEXT: vpextrw $2, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $2, %eax, %xmm4, %xmm4
+; CHECK-NEXT: vpextrw $3, %xmm2, %eax
+; CHECK-NEXT: vpextrw $3, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $3, %eax, %xmm4, %xmm4
+; CHECK-NEXT: vpextrw $4, %xmm2, %eax
+; CHECK-NEXT: vpextrw $4, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $4, %eax, %xmm4, %xmm5
+; CHECK-NEXT: vpextrw $5, %xmm2, %eax
+; CHECK-NEXT: vpextrw $5, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $5, %eax, %xmm5, %xmm5
+; CHECK-NEXT: vpextrw $6, %xmm2, %eax
+; CHECK-NEXT: vpextrw $6, %xmm3, %ecx
+; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: divw %cx
+; CHECK-NEXT: # kill: def $ax killed $ax def $eax
+; CHECK-NEXT: vpinsrw $6, %eax, %xmm5, %xmm2
+; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT: vcvtdq2ps %ymm1, %ymm1
+; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT: vcvtdq2ps %ymm0, %ymm0
+; CHECK-NEXT: vdivps {rn-sae}, %zmm1, %zmm0, %zmm0
+; CHECK-NEXT: vcvttps2udq {sae}, %zmm0, %zmm0
+; CHECK-NEXT: vpmovdw %zmm0, %ymm0
+; CHECK-NEXT: movw %ax, 28(%rdi)
+; CHECK-NEXT: vmovq %xmm4, 16(%rdi)
+; CHECK-NEXT: vmovdqa %xmm0, (%rdi)
+; CHECK-NEXT: vpextrd $2, %xmm2, 24(%rdi)
+; CHECK-NEXT: vzeroupper
+; CHECK-NEXT: retq
+ %res = udiv <15 x i16> %a, %b
+ store <15 x i16> %res, ptr %p
+ ret void
+}
>From c1b784b54250098dc4c1da8f3e1104319593e42a Mon Sep 17 00:00:00 2001
From: Adam Scott <adamscott200322 at gmail.com>
Date: Thu, 20 Aug 2026 10:05:48 +0000
Subject: [PATCH 2/2] Widen non pow2 vector div/rem under strictfp
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 16 +-
llvm/test/CodeGen/X86/vector-idiv-strictfp.ll | 264 ++----------------
2 files changed, 45 insertions(+), 235 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 922657ca9e17c..1ec725f12c46c 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -50789,9 +50789,21 @@ static SDValue combineIntDivRem(SDNode *N, SelectionDAG &DAG,
Attribute::StrictFP);
if (IsStrict) {
// The SAE forms are 512-bit only. Inputs widen into a zmm below, which
- // requires 512-bit types to be legal and a power of 2 lane count.
- if (!Subtarget.useAVX512Regs() || !isPowerOf2_32(VT.getVectorNumElements()))
+ // requires 512-bit types to be legal.
+ if (!Subtarget.useAVX512Regs())
return SDValue();
+ // Widen a non-power-of-two lane count to get a machine type, but only
+ // while it still fits one divide. Two chains lose to a chain plus a scalar.
+ unsigned NumElts = VT.getVectorNumElements();
+ if (!isPowerOf2_32(NumElts)) {
+ if (NextPowerOf2(NumElts) * FPSclVT.getSizeInBits() > 512)
+ return SDValue();
+ SDValue WideDividend = DAG.WidenVector(Dividend, DL);
+ EVT WideVT = WideDividend.getValueType();
+ SDValue WideDivisor = DAG.WidenVector(Divisor, DL);
+ SDValue Wide = DAG.getNode(Opc, DL, WideVT, WideDividend, WideDivisor);
+ return DAG.getExtractSubvector(DL, VT, Wide, 0);
+ }
} else if (!IsSigned && VT.getScalarSizeInBits() == 32 &&
!Subtarget.hasAVX2()) {
// Unsigned i32 needs FP_TO_UINT(f64->u32) which is emulated and a loss
diff --git a/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll b/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
index 408c8b9e61864..31f7bac000dab 100644
--- a/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
+++ b/llvm/test/CodeGen/X86/vector-idiv-strictfp.ll
@@ -205,30 +205,14 @@ define void @test_divv_32i32_strictfp(<32 x i32> %a, <32 x i32> %b, ptr %p) noun
define void @test_divv_7i32_strictfp(<7 x i32> %a, <7 x i32> %b, ptr %p) nounwind strictfp {
; CHECK-LABEL: test_divv_7i32_strictfp:
; CHECK: # %bb.0:
-; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm2
-; CHECK-NEXT: vpextrd $1, %xmm2, %eax
-; CHECK-NEXT: vextracti128 $1, %ymm1, %xmm3
-; CHECK-NEXT: vpextrd $1, %xmm3, %ecx
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divl %ecx
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: vmovd %xmm2, %eax
-; CHECK-NEXT: vmovd %xmm3, %esi
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divl %esi
-; CHECK-NEXT: vmovd %eax, %xmm4
-; CHECK-NEXT: vpinsrd $1, %ecx, %xmm4, %xmm4
-; CHECK-NEXT: vpextrd $2, %xmm2, %eax
-; CHECK-NEXT: vpextrd $2, %xmm3, %ecx
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divl %ecx
; CHECK-NEXT: vcvtudq2pd %ymm1, %zmm1
; CHECK-NEXT: vcvtudq2pd %ymm0, %zmm0
; CHECK-NEXT: vdivpd {rn-sae}, %zmm1, %zmm0, %zmm0
; CHECK-NEXT: vcvttpd2udq {sae}, %zmm0, %ymm0
-; CHECK-NEXT: movl %eax, 24(%rdi)
+; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm1
+; CHECK-NEXT: vextractps $2, %xmm1, 24(%rdi)
+; CHECK-NEXT: vmovlps %xmm1, 16(%rdi)
; CHECK-NEXT: vmovaps %xmm0, (%rdi)
-; CHECK-NEXT: vmovq %xmm4, 16(%rdi)
; CHECK-NEXT: vzeroupper
; CHECK-NEXT: retq
%res = udiv <7 x i32> %a, %b
@@ -239,58 +223,17 @@ define void @test_divv_7i32_strictfp(<7 x i32> %a, <7 x i32> %b, ptr %p) nounwin
define void @test_divv_7i16_strictfp(<7 x i16> %a, <7 x i16> %b, ptr %p) nounwind strictfp {
; CHECK-LABEL: test_divv_7i16_strictfp:
; CHECK: # %bb.0:
-; CHECK-NEXT: vpextrw $1, %xmm0, %eax
-; CHECK-NEXT: vpextrw $1, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: vmovd %xmm0, %eax
-; CHECK-NEXT: vmovd %xmm1, %esi
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %si
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vmovd %eax, %xmm2
-; CHECK-NEXT: vpinsrw $1, %ecx, %xmm2, %xmm2
-; CHECK-NEXT: vpextrw $2, %xmm0, %eax
-; CHECK-NEXT: vpextrw $2, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $2, %eax, %xmm2, %xmm2
-; CHECK-NEXT: vpextrw $3, %xmm0, %eax
-; CHECK-NEXT: vpextrw $3, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $3, %eax, %xmm2, %xmm2
-; CHECK-NEXT: vpextrw $4, %xmm0, %eax
-; CHECK-NEXT: vpextrw $4, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $4, %eax, %xmm2, %xmm2
-; CHECK-NEXT: vpextrw $5, %xmm0, %eax
-; CHECK-NEXT: vpextrw $5, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $5, %eax, %xmm2, %xmm2
-; CHECK-NEXT: vpextrw $6, %xmm0, %eax
-; CHECK-NEXT: vpextrw $6, %xmm1, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $6, %eax, %xmm2, %xmm0
-; CHECK-NEXT: movw %ax, 12(%rdi)
+; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT: vcvtdq2ps %ymm1, %ymm1
+; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT: vcvtdq2ps %ymm0, %ymm0
+; CHECK-NEXT: vdivps {rn-sae}, %zmm1, %zmm0, %zmm0
+; CHECK-NEXT: vcvttps2udq {sae}, %zmm0, %zmm0
+; CHECK-NEXT: vpmovdw %zmm0, %ymm0
+; CHECK-NEXT: vpextrw $6, %xmm0, 12(%rdi)
; CHECK-NEXT: vpextrd $2, %xmm0, 8(%rdi)
; CHECK-NEXT: vmovq %xmm0, (%rdi)
+; CHECK-NEXT: vzeroupper
; CHECK-NEXT: retq
%res = udiv <7 x i16> %a, %b
store <7 x i16> %res, ptr %p
@@ -300,113 +243,18 @@ define void @test_divv_7i16_strictfp(<7 x i16> %a, <7 x i16> %b, ptr %p) nounwin
define void @test_divv_15i8_strictfp(<15 x i8> %a, <15 x i8> %b, ptr %p) nounwind strictfp {
; CHECK-LABEL: test_divv_15i8_strictfp:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: pushq %r14
-; CHECK-NEXT: pushq %r13
-; CHECK-NEXT: pushq %r12
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: vpextrb $1, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $1, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: # kill: def $al killed $al def $eax
-; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: vmovd %xmm1, %ecx
-; CHECK-NEXT: vmovd %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %esi
-; CHECK-NEXT: vpextrb $2, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $2, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %edx
-; CHECK-NEXT: vpextrb $3, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $3, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r8d
-; CHECK-NEXT: vpextrb $4, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $4, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r9d
-; CHECK-NEXT: vpextrb $5, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $5, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r10d
-; CHECK-NEXT: vpextrb $6, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $6, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r11d
-; CHECK-NEXT: vpextrb $7, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $7, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %ebx
-; CHECK-NEXT: vpextrb $8, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $8, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %ebp
-; CHECK-NEXT: vpextrb $9, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $9, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r14d
-; CHECK-NEXT: vpextrb $10, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $10, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r15d
-; CHECK-NEXT: vpextrb $11, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $11, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r12d
-; CHECK-NEXT: vpextrb $12, %xmm1, %ecx
-; CHECK-NEXT: vpextrb $12, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %r13d
-; CHECK-NEXT: vpextrb $13, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: vpextrb $13, %xmm1, %ecx
-; CHECK-NEXT: divb %cl
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: vmovd %esi, %xmm2
-; CHECK-NEXT: vpextrb $14, %xmm0, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: vpextrb $14, %xmm1, %esi
-; CHECK-NEXT: divb %sil
-; CHECK-NEXT: # kill: def $al killed $al def $eax
-; CHECK-NEXT: vpinsrb $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm2, %xmm0 # 4-byte Folded Reload
-; CHECK-NEXT: vpinsrb $2, %edx, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $3, %r8d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $4, %r9d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $5, %r10d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $6, %r11d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $7, %ebx, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $8, %ebp, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $9, %r14d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $10, %r15d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $11, %r12d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $12, %r13d, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $13, %ecx, %xmm0, %xmm0
-; CHECK-NEXT: vpinsrb $14, %eax, %xmm0, %xmm1
-; CHECK-NEXT: movb %al, 14(%rdi)
+; CHECK-NEXT: vpmovzxbd {{.*#+}} zmm1 = xmm1[0],zero,zero,zero,xmm1[1],zero,zero,zero,xmm1[2],zero,zero,zero,xmm1[3],zero,zero,zero,xmm1[4],zero,zero,zero,xmm1[5],zero,zero,zero,xmm1[6],zero,zero,zero,xmm1[7],zero,zero,zero,xmm1[8],zero,zero,zero,xmm1[9],zero,zero,zero,xmm1[10],zero,zero,zero,xmm1[11],zero,zero,zero,xmm1[12],zero,zero,zero,xmm1[13],zero,zero,zero,xmm1[14],zero,zero,zero,xmm1[15],zero,zero,zero
+; CHECK-NEXT: vcvtdq2ps %zmm1, %zmm1
+; CHECK-NEXT: vpmovzxbd {{.*#+}} zmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero,xmm0[8],zero,zero,zero,xmm0[9],zero,zero,zero,xmm0[10],zero,zero,zero,xmm0[11],zero,zero,zero,xmm0[12],zero,zero,zero,xmm0[13],zero,zero,zero,xmm0[14],zero,zero,zero,xmm0[15],zero,zero,zero
+; CHECK-NEXT: vcvtdq2ps %zmm0, %zmm0
+; CHECK-NEXT: vdivps {rn-sae}, %zmm1, %zmm0, %zmm0
+; CHECK-NEXT: vcvttps2udq {sae}, %zmm0, %zmm0
+; CHECK-NEXT: vpmovdb %zmm0, %xmm0
+; CHECK-NEXT: vpextrb $14, %xmm0, 14(%rdi)
; CHECK-NEXT: vpextrw $6, %xmm0, 12(%rdi)
-; CHECK-NEXT: vpextrd $2, %xmm1, 8(%rdi)
-; CHECK-NEXT: vmovq %xmm1, (%rdi)
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: popq %r12
-; CHECK-NEXT: popq %r13
-; CHECK-NEXT: popq %r14
-; CHECK-NEXT: popq %r15
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: vpextrd $2, %xmm0, 8(%rdi)
+; CHECK-NEXT: vmovq %xmm0, (%rdi)
+; CHECK-NEXT: vzeroupper
; CHECK-NEXT: retq
%res = udiv <15 x i8> %a, %b
store <15 x i8> %res, ptr %p
@@ -416,68 +264,18 @@ define void @test_divv_15i8_strictfp(<15 x i8> %a, <15 x i8> %b, ptr %p) nounwin
define void @test_divv_15i16_strictfp(<15 x i16> %a, <15 x i16> %b, ptr %p) nounwind strictfp {
; CHECK-LABEL: test_divv_15i16_strictfp:
; CHECK: # %bb.0:
-; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm2
-; CHECK-NEXT: vpextrw $1, %xmm2, %eax
-; CHECK-NEXT: vextracti128 $1, %ymm1, %xmm3
-; CHECK-NEXT: vpextrw $1, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: vmovd %xmm2, %eax
-; CHECK-NEXT: vmovd %xmm3, %esi
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %si
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vmovd %eax, %xmm4
-; CHECK-NEXT: vpinsrw $1, %ecx, %xmm4, %xmm4
-; CHECK-NEXT: vpextrw $2, %xmm2, %eax
-; CHECK-NEXT: vpextrw $2, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $2, %eax, %xmm4, %xmm4
-; CHECK-NEXT: vpextrw $3, %xmm2, %eax
-; CHECK-NEXT: vpextrw $3, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $3, %eax, %xmm4, %xmm4
-; CHECK-NEXT: vpextrw $4, %xmm2, %eax
-; CHECK-NEXT: vpextrw $4, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $4, %eax, %xmm4, %xmm5
-; CHECK-NEXT: vpextrw $5, %xmm2, %eax
-; CHECK-NEXT: vpextrw $5, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $5, %eax, %xmm5, %xmm5
-; CHECK-NEXT: vpextrw $6, %xmm2, %eax
-; CHECK-NEXT: vpextrw $6, %xmm3, %ecx
-; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: divw %cx
-; CHECK-NEXT: # kill: def $ax killed $ax def $eax
-; CHECK-NEXT: vpinsrw $6, %eax, %xmm5, %xmm2
-; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
-; CHECK-NEXT: vcvtdq2ps %ymm1, %ymm1
-; CHECK-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
-; CHECK-NEXT: vcvtdq2ps %ymm0, %ymm0
+; CHECK-NEXT: vpmovzxwd {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero
+; CHECK-NEXT: vcvtdq2ps %zmm1, %zmm1
+; CHECK-NEXT: vpmovzxwd {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero
+; CHECK-NEXT: vcvtdq2ps %zmm0, %zmm0
; CHECK-NEXT: vdivps {rn-sae}, %zmm1, %zmm0, %zmm0
; CHECK-NEXT: vcvttps2udq {sae}, %zmm0, %zmm0
; CHECK-NEXT: vpmovdw %zmm0, %ymm0
-; CHECK-NEXT: movw %ax, 28(%rdi)
-; CHECK-NEXT: vmovq %xmm4, 16(%rdi)
+; CHECK-NEXT: vextracti128 $1, %ymm0, %xmm1
+; CHECK-NEXT: vpextrw $6, %xmm1, 28(%rdi)
+; CHECK-NEXT: vpextrd $2, %xmm1, 24(%rdi)
+; CHECK-NEXT: vmovq %xmm1, 16(%rdi)
; CHECK-NEXT: vmovdqa %xmm0, (%rdi)
-; CHECK-NEXT: vpextrd $2, %xmm2, 24(%rdi)
; CHECK-NEXT: vzeroupper
; CHECK-NEXT: retq
%res = udiv <15 x i16> %a, %b
More information about the llvm-commits
mailing list