[llvm] [VectorCombine] fold fptoui(fdiv(uitofp(x),uitofp(y))) into udiv(x,y) (PR #214844)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 02:17:18 PDT 2026


================
@@ -2332,6 +2334,94 @@ bool VectorCombine::scalarizeExtExtract(Instruction &I) {
   return true;
 }
 
+/// Try to fold fptoui(fdiv(x,y)) to udiv(x,y), where x & y are either uitofp
+/// instructions or fp-constants that exactly represent integers.
+bool VectorCombine::foldFDivToUDiv(Instruction &I) {
+  const DataLayout &DL = I.getDataLayout();
+  Value *X, *Y;
+  if (!match(&I, m_FPToUI(m_OneUse(m_FDiv(m_Value(X), m_Value(Y))))))
+    return false;
+
+  Type *IntTy = I.getType();
+
+  auto MatchConstOrInst = [&](Value *V, Value *&Src) -> bool {
+    // match uitofp
+    if (match(V, m_OneUse(m_UIToFP(m_Value(Src)))))
+      return Src->getType() == IntTy;
+    // match FP constants that survive FP->integer->FP casts.
+    Constant *C;
+    if (match(V, m_Constant(C))) {
+      Constant *IntC =
+          ConstantFoldCastOperand(Instruction::FPToUI, C, IntTy, DL);
+      if (!IntC)
+        return false;
+      Constant *FloatC =
+          ConstantFoldCastOperand(Instruction::UIToFP, IntC, C->getType(), DL);
+      if (C != FloatC)
+        return false;
+      Src = IntC;
+      return true;
+    }
+    return false;
+  };
+
+  Value *SrcX;
+  if (!MatchConstOrInst(X, SrcX))
+    return false;
+  Value *SrcY;
+  if (!MatchConstOrInst(Y, SrcY))
+    return false;
+
+  SimplifyQuery S = SQ.getWithInstruction(&I);
+
+  TTI::OperandValueInfo OpSrcX = TTI::getOperandInfo(SrcX);
+  TTI::OperandValueInfo OpSrcY = TTI::getOperandInfo(SrcY);
+
+  // Require uitofp(x) and uitofp(y) to be exact conversions, i.e. IntWidth
+  // must fit within the float type's mantissa precision.
+  Type *FloatTy = X->getType();
+  unsigned Precision =
+      APFloat::semanticsPrecision(FloatTy->getScalarType()->getFltSemantics());
+
+  auto NumActiveBits = [&](Value *V) -> bool {
+    KnownBits KB = computeKnownBits(V, S);
+    unsigned AB = KB.getBitWidth() - KB.countMinLeadingZeros();
+    return AB <= Precision;
+  };
+
+  if (!NumActiveBits(SrcX) || !NumActiveBits(SrcY))
+    return false;
+
+  // Integer division by zero is UB. We must prove the divisor
+  // is known non-zero to safely transform fdiv into udiv.
+  if (!isKnownNonZero(SrcY, S))
+    return false;
+
+  InstructionCost OldCost =
+      TTI.getInstructionCost(&I, CostKind) +
+      TTI.getArithmeticInstrCost(Instruction::FDiv, FloatTy, CostKind);
+  // Add cost if the src is an uitofp instruction.
+  if (auto *InstX = dyn_cast<Instruction>(X))
+    OldCost += TTI.getInstructionCost(InstX, CostKind);
+  if (auto *InstY = dyn_cast<Instruction>(Y))
+    OldCost += TTI.getInstructionCost(InstY, CostKind);
+  // NewCost = udiv
+  InstructionCost NewCost = TTI.getArithmeticInstrCost(
+      Instruction::UDiv, IntTy, CostKind, OpSrcX, OpSrcY);
----------------
RKSimon wrote:

```suggestion
InstructionCost NewCost = TTI.getArithmeticInstrCost(
      Instruction::UDiv, IntTy, CostKind, OpSrcX, OpSrcY, {SrcX, SrcY});
```

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


More information about the llvm-commits mailing list