[llvm] [X86] Lower vector integer division and remainder through float division (PR #205263)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 19 03:42:08 PDT 2026


================
@@ -50516,6 +50524,190 @@ static SDValue combineMulToPMADD52(SDNode *N, const SDLoc &DL,
   return SDValue();
 }
 
+// x86 has no vector integer divide instructions. Lower vector
+// UDIV/SDIV/UREM/SREM through float division instead of scalarizing into N
+// scalar hardware divides.
+static SDValue combineIntDivRem(SDNode *N, SelectionDAG &DAG,
+                                TargetLowering::DAGCombinerInfo &DCI,
+                                const X86Subtarget &Subtarget) {
+  EVT VT = N->getValueType(0);
+  SDLoc DL(N);
+
+  // Run before the legalizer expands the division.
+  if (!VT.isVector() || !Subtarget.hasSSE2() || !DCI.isBeforeLegalizeOps())
+    return SDValue();
+
+  SDValue Dividend = N->getOperand(0);
+  SDValue Divisor = N->getOperand(1);
+  unsigned Opc = N->getOpcode();
+
+  // Disabled lanes are poison and fdiv never traps, so ignore the mask.
+  if (Opc == ISD::MASKED_UDIV || Opc == ISD::MASKED_SDIV ||
+      Opc == ISD::MASKED_UREM || Opc == ISD::MASKED_SREM)
+    Opc = ISD::getUnmaskedBinOpOpcode(Opc);
+  bool IsRem = Opc == ISD::UREM || Opc == ISD::SREM;
+  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;
+      }))
+    return SDValue();
+
+  // Magic multiply lowers constant divisors cheaper than a divide.
+  if (DAG.isConstantIntBuildVectorOrConstantInt(Divisor))
+    return SDValue();
+
+  // i8/i16/i32: the operands fit the float mantissa exactly so one float
+  // divide recovers the exact quotient.
+  if (VT.getScalarSizeInBits() <= 32) {
+    // f32 recovers the quotient exactly when both operands fit in 24 bits
+    unsigned EltBits = VT.getScalarSizeInBits();
+    unsigned Precision = APFloat::semanticsPrecision(APFloat::IEEEsingle());
+    auto FitsF32 = [&](SDValue V) {
----------------
Andarwinux wrote:

Maybe could use the same method to shrink int64 to f32 (fit in 24 bits) or plain f64 (fit in 52bits) to keep vectorization as much as possible on non-avx512 as well?

https://github.com/llvm/llvm-project/pull/205263


More information about the llvm-commits mailing list