summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp37
1 files changed, 16 insertions, 21 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 6d0b9ac9c62..7b15076546a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1289,32 +1289,27 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
}
/// Try to convert X/C into X * (1/C).
-static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
- // TODO: Handle non-splat vector constants.
- const APFloat *C;
- if (!match(FDiv.getOperand(1), m_APFloat(C)))
+static Instruction *foldFDivConstantDivisor(BinaryOperator &I) {
+ Constant *C;
+ if (!match(I.getOperand(1), m_Constant(C)))
return nullptr;
- // This returns false if the inverse would be a denormal.
- APFloat Reciprocal(C->getSemantics());
- bool HasRecip = C->getExactInverse(&Reciprocal);
- // If the inverse is not exact, we may still be able to convert if we are
- // not operating with strict math.
- if (!HasRecip && FDiv.hasAllowReciprocal() && C->isFiniteNonZero()) {
- Reciprocal = APFloat(C->getSemantics(), 1.0f);
- Reciprocal.divide(*C, APFloat::rmNearestTiesToEven);
- // Disallow denormal constants because we don't know what would happen
- // on all targets.
- // TODO: Function attributes can tell us that denorms are flushed?
- HasRecip = !Reciprocal.isDenormal();
- }
+ // If the constant divisor has an exact inverse, this is always safe. If not,
+ // then we can still create a reciprocal if fast-math-flags allow it and the
+ // constant is a regular number (not zero, infinite, or denormal).
+ if (!(C->hasExactInverseFP() || (I.hasAllowReciprocal() && C->isNormalFP())))
+ return nullptr;
- if (!HasRecip)
+ // Disallow denormal constants because we don't know what would happen
+ // on all targets.
+ // TODO: Use Intrinsic::canonicalize or let function attributes tell us that
+ // denorms are flushed?
+ auto *RecipC = ConstantExpr::getFDiv(ConstantFP::get(I.getType(), 1.0), C);
+ if (!RecipC->isNormalFP())
return nullptr;
- auto *RecipCFP = ConstantFP::get(FDiv.getType(), Reciprocal);
- return BinaryOperator::CreateWithCopiedFlags(Instruction::FMul, RecipCFP,
- FDiv.getOperand(0), &FDiv);
+ return BinaryOperator::CreateWithCopiedFlags(
+ Instruction::FMul, I.getOperand(0), RecipC, &I);
}
/// Try to reassociate C / X expressions where X includes another constant.
OpenPOWER on IntegriCloud