Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -2732,9 +2732,10 @@ return SDValue(); } - /// Indicate whether this target prefers to combine the given number of FDIVs - /// with the same divisor. - virtual bool combineRepeatedFPDivisors(unsigned NumUsers) const { + /// Indicate whether this target prefers to combine FDIVs with the same + /// divisor. If the transform should be done, return the minimum number of + /// divisor uses that should exist before doing the transform in MinUses. + virtual bool combineRepeatedFPDivisors(unsigned &MinUses) const { return false; } Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -8247,23 +8247,29 @@ if (!DAG.getTarget().Options.UnsafeFPMath) return SDValue(); + // Skip if current node is a reciprocal. SDValue N0 = N->getOperand(0); ConstantFPSDNode *N0CFP = dyn_cast(N0); - - // Skip if current node is a reciprocal. if (N0CFP && N0CFP->isExactlyValue(1.0)) return SDValue(); + // 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. SDValue N1 = N->getOperand(1); - SmallVector Users; + unsigned MinUses; + if (!TLI.combineRepeatedFPDivisors(MinUses) || N1->use_size() < MinUses) + return SDValue(); // Find all FDIV users of the same divisor. + SmallVector Users; for (auto *U : N1->uses()) { if (U->getOpcode() == ISD::FDIV && U->getOperand(1) == N1) Users.push_back(U); } - if (!TLI.combineRepeatedFPDivisors(Users.size())) + // Now that we have the actual number of divisor uses, make sure it meets + // the minimum threshold specified by the target. + if (Users.size() < MinUses) return SDValue(); EVT VT = N->getValueType(0); Index: lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.h +++ lib/Target/AArch64/AArch64ISelLowering.h @@ -475,7 +475,7 @@ SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, std::vector *Created) const override; - bool combineRepeatedFPDivisors(unsigned NumUsers) const override; + bool combineRepeatedFPDivisors(unsigned &MinUses) const override; ConstraintType getConstraintType(StringRef Constraint) const override; unsigned getRegisterByName(const char* RegName, EVT VT, Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9406,10 +9406,11 @@ return true; } -bool AArch64TargetLowering::combineRepeatedFPDivisors(unsigned NumUsers) const { +bool AArch64TargetLowering::combineRepeatedFPDivisors(unsigned &MinUses) const { // Combine multiple FDIVs with the same divisor into multiple FMULs by the // reciprocal if there are three or more FDIVs. - return NumUsers > 2; + MinUses = 3; + return true; } TargetLoweringBase::LegalizeTypeAction Index: lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- lib/Target/PowerPC/PPCISelLowering.h +++ lib/Target/PowerPC/PPCISelLowering.h @@ -853,7 +853,7 @@ bool &UseOneConstNR) const override; SDValue getRecipEstimate(SDValue Operand, DAGCombinerInfo &DCI, unsigned &RefinementSteps) const override; - bool combineRepeatedFPDivisors(unsigned NumUsers) const override; + bool combineRepeatedFPDivisors(unsigned &MinUses) const override; CCAssignFn *useFastISelCCs(unsigned Flag) const; }; Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -9128,7 +9128,7 @@ return SDValue(); } -bool PPCTargetLowering::combineRepeatedFPDivisors(unsigned NumUsers) const { +bool PPCTargetLowering::combineRepeatedFPDivisors(unsigned &MinUses) const { // Note: This functionality is used only when unsafe-fp-math is enabled, and // on cores with reciprocal estimates (which are used when unsafe-fp-math is // enabled for division), this functionality is redundant with the default @@ -9141,13 +9141,14 @@ // one FP pipeline) for three or more FDIVs (for generic OOO cores). switch (Subtarget.getDarwinDirective()) { default: - return NumUsers > 2; + MinUses = 3; case PPC::DIR_440: case PPC::DIR_A2: case PPC::DIR_E500mc: case PPC::DIR_E5500: - return NumUsers > 1; + MinUses = 2; } + return true; } static bool isConsecutiveLSLoc(SDValue Loc, EVT VT, LSBaseSDNode *Base, Index: lib/Target/X86/X86ISelLowering.h =================================================================== --- lib/Target/X86/X86ISelLowering.h +++ lib/Target/X86/X86ISelLowering.h @@ -1124,7 +1124,7 @@ unsigned &RefinementSteps) const override; /// Reassociate floating point divisions into multiply by reciprocal. - bool combineRepeatedFPDivisors(unsigned NumUsers) const override; + bool combineRepeatedFPDivisors(unsigned &MinUses) const override; }; namespace X86 { Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -13300,8 +13300,9 @@ /// This is because we still need one division to calculate the reciprocal and /// then we need two multiplies by that reciprocal as replacements for the /// original divisions. -bool X86TargetLowering::combineRepeatedFPDivisors(unsigned NumUsers) const { - return NumUsers > 1; +bool X86TargetLowering::combineRepeatedFPDivisors(unsigned &MinUses) const { + MinUses = 2; + return true; } static bool isAllOnes(SDValue V) {