[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