[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