[llvm] [GlobalISel] fdiv to fmul transform (PR #144305)
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 16 03:03:01 PDT 2025
================
@@ -6389,6 +6389,76 @@ bool CombinerHelper::matchCombineFMinMaxNaN(MachineInstr &MI,
return MatchNaN(1) || MatchNaN(2);
}
+// Combine multiple FDIVs with the same divisor into multiple FMULs by the
+// reciprocal.
+// E.g., (a / D; b / D;) -> (recip = 1.0 / D; a * recip; b * recip)
+bool CombinerHelper::matchRepeatedFPDivisor(
+ MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
+ assert(MI.getOpcode() == TargetOpcode::G_FDIV);
+ auto *MF = MI.getMF();
+ const TargetOptions &Options = MF->getTarget().Options;
+
+ Register X = MI.getOperand(1).getReg();
+ Register Y = MI.getOperand(2).getReg();
+
+ bool UnsafeMath = Options.UnsafeFPMath;
+ if (!UnsafeMath && !MI.getFlag(MachineInstr::MIFlag::FmArcp))
+ return false;
+
+ // Skip if current node is a reciprocal/fneg-reciprocal.
+ auto N0CFP = isConstantOrConstantSplatVectorFP(*MRI.getVRegDef(X), MRI);
+ if (N0CFP && (N0CFP->isExactlyValue(1.0) || N0CFP->isExactlyValue(-1.0)))
+ return false;
+
+ // Exit early if the target does not want this transform or if there can't
+ // possibly be enough uses of the divisor to make the transform worthwhile.
+ unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
+
+ if (!MinUses)
+ return false;
+
+ // Find all FDIV users of the same divisor. Use a set because duplicates may
+ // be present in the user list. For the moment we limit all instructions to a
+ // single BB and use the first Instr in MatchInfo as the dominating position.
+ MatchInfo.push_back(&MI);
+ for (auto &U : MRI.use_nodbg_instructions(Y)) {
+ if (&U == &MI || U.getParent() != MI.getParent())
+ continue;
+ if (U.getOpcode() == TargetOpcode::G_FDIV &&
+ U.getOperand(2).getReg() == Y) {
+ // This division is eligible for optimization only if global unsafe math
+ // is enabled or if this division allows reciprocal formation.
+ if (UnsafeMath || U.getFlag(MachineInstr::MIFlag::FmArcp)) {
+ MatchInfo.push_back(&U);
+ if (dominates(U, *MatchInfo[0]))
+ std::swap(MatchInfo[0], MatchInfo.back());
----------------
jayfoad wrote:
I don't think you're handling the case where neither FDIV dominates the other. In that case, where would you insert the reciprocal instruction?
https://github.com/llvm/llvm-project/pull/144305
More information about the llvm-commits
mailing list