[llvm] [X86] Vectorize non-power-of-two integer division (PR #215076)
Patrick Ribbsaeter via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 9 11:14:38 PDT 2026
https://github.com/patrickswedish updated https://github.com/llvm/llvm-project/pull/215076
>From 9215cfff69f10398c42c89de81ca811773227095 Mon Sep 17 00:00:00 2001
From: Patrick Ribbsaeter <patrickswedish at gmail.com>
Date: Sun, 9 Aug 2026 10:18:13 +0200
Subject: [PATCH 1/2] [X86] Vectorize non-power-of-two integer division
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 22 +++++++++++++---
.../CodeGen/X86/vector-idiv-udiv-non-pow2.ll | 26 +++++++++++++++++++
2 files changed, 44 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c74d342fed1cb..8902a9560f3cc 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -50643,10 +50643,24 @@ static SDValue combineIntDivRem(SDNode *N, SelectionDAG &DAG,
bool IsSigned = Opc == ISD::SDIV || Opc == ISD::SREM;
// If the result is only read back as scalar extracts, scalarization computes
- // just the demanded lanes.
- if (all_of(N->users(), [](const SDNode *U) {
- return U->getOpcode() == ISD::EXTRACT_VECTOR_ELT;
- }))
+ // just the demanded lanes. Keep the vector operation when every lane is
+ // extracted, which occurs when non-power-of-two vectors are returned.
+ APInt ExtractedElts = APInt::getZero(VT.getVectorNumElements());
+ bool OnlyExtracts = true;
+ for (const SDNode *U : N->users()) {
+ if (U->getOpcode() != ISD::EXTRACT_VECTOR_ELT) {
+ OnlyExtracts = false;
+ break;
+ }
+ auto *Idx = dyn_cast<ConstantSDNode>(U->getOperand(1));
+ if (!Idx)
+ return SDValue();
+ uint64_t IdxVal = Idx->getZExtValue();
+ if (IdxVal >= VT.getVectorNumElements())
+ return SDValue();
+ ExtractedElts.setBit(IdxVal);
+ }
+ if (OnlyExtracts && !ExtractedElts.isAllOnes())
return SDValue();
// Magic multiply lowers constant divisors cheaper than a divide.
diff --git a/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll b/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
new file mode 100644
index 0000000000000..4b5d55acfcc54
--- /dev/null
+++ b/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
@@ -0,0 +1,26 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s
+
+define <7 x i32> @udiv_v7i32(<7 x i32> %x, <7 x i32> %y) {
+; CHECK-LABEL: udiv_v7i32:
+; CHECK-NOT: divl
+; CHECK: vcvtudq2pd
+; CHECK: vcvtudq2pd
+; CHECK: vdivpd
+; CHECK: vcvttpd2udq
+; CHECK-NOT: divl
+; CHECK: retq
+ %div = udiv <7 x i32> %x, %y
+ ret <7 x i32> %div
+}
+
+; Keep scalarizing when only one result lane is demanded.
+define i32 @udiv_v7i32_extract0(<7 x i32> %x, <7 x i32> %y) {
+; CHECK-LABEL: udiv_v7i32_extract0:
+; CHECK-NOT: vdivpd
+; CHECK: divl
+; CHECK-NOT: vdivpd
+; CHECK: retq
+ %div = udiv <7 x i32> %x, %y
+ %elt = extractelement <7 x i32> %div, i32 0
+ ret i32 %elt
+}
>From fd567029164477446ace2af89ec7a1094c76a2a3 Mon Sep 17 00:00:00 2001
From: Patrick Ribbsaeter <hello at glasheldereindhoven.nl>
Date: Sun, 9 Aug 2026 20:14:28 +0200
Subject: [PATCH 2/2] [X86] Address vector idiv review
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 6 +++---
llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8902a9560f3cc..5f415a1437f9d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -50655,10 +50655,10 @@ static SDValue combineIntDivRem(SDNode *N, SelectionDAG &DAG,
auto *Idx = dyn_cast<ConstantSDNode>(U->getOperand(1));
if (!Idx)
return SDValue();
- uint64_t IdxVal = Idx->getZExtValue();
- if (IdxVal >= VT.getVectorNumElements())
+ const APInt &IdxVal = Idx->getAPIntValue();
+ if (IdxVal.uge(VT.getVectorNumElements()))
return SDValue();
- ExtractedElts.setBit(IdxVal);
+ ExtractedElts.setBit(IdxVal.getZExtValue());
}
if (OnlyExtracts && !ExtractedElts.isAllOnes())
return SDValue();
diff --git a/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll b/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
index 4b5d55acfcc54..5d2ffb9fad12a 100644
--- a/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
+++ b/llvm/test/CodeGen/X86/vector-idiv-udiv-non-pow2.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=skylake-avx512 | FileCheck %s
define <7 x i32> @udiv_v7i32(<7 x i32> %x, <7 x i32> %y) {
; CHECK-LABEL: udiv_v7i32:
More information about the llvm-commits
mailing list