Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Show First 20 Lines • Show All 1,233 Lines • ▼ Show 20 Lines | if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) && | ||||
return BinaryOperator::CreateFDivFMF(X, YZ, &I); | return BinaryOperator::CreateFDivFMF(X, YZ, &I); | ||||
} | } | ||||
if (match(Op1, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) && | if (match(Op1, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) && | ||||
(!isa<Constant>(Y) || !isa<Constant>(Op0))) { | (!isa<Constant>(Y) || !isa<Constant>(Op0))) { | ||||
// Z / (X / Y) => (Y * Z) / X | // Z / (X / Y) => (Y * Z) / X | ||||
Value *YZ = Builder.CreateFMulFMF(Y, Op0, &I); | Value *YZ = Builder.CreateFMulFMF(Y, Op0, &I); | ||||
return BinaryOperator::CreateFDivFMF(YZ, X, &I); | return BinaryOperator::CreateFDivFMF(YZ, X, &I); | ||||
} | } | ||||
// Z / (1.0 / Y) => (Y * Z) | |||||
// | |||||
// This is a special case of Z / (X / Y) => (Y * Z) / X, with X = 1.0. The | |||||
// m_OneUse check is avoided because even in the case of the multiple uses | |||||
// for 1.0/Y, the number of instructions remain the same and a division is | |||||
// replaced by a multiplication. | |||||
if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) | |||||
return BinaryOperator::CreateFMulFMF(Y, Op0, &I); | |||||
spatel: I don't think these constant checks are necessary. (I'm not sure why they are part of the… | |||||
} | } | ||||
if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) { | if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) { | ||||
// sin(X) / cos(X) -> tan(X) | // sin(X) / cos(X) -> tan(X) | ||||
// cos(X) / sin(X) -> 1/tan(X) (cotangent) | // cos(X) / sin(X) -> 1/tan(X) (cotangent) | ||||
Value *X; | Value *X; | ||||
bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) && | bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) && | ||||
match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X))); | match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X))); | ||||
▲ Show 20 Lines • Show All 235 Lines • Show Last 20 Lines |
I don't think these constant checks are necessary. (I'm not sure why they are part of the existing code either - maybe some corner case with denorm values?)
If Y is a constant, 1.0/C will get constant folded and Z/C' will eventually get folded too, so this should just get to canonical form quicker. The 'Z' is constant pattern is similar.
FDiv with constant operand are generally handled within:
foldFDivConstantDivisor()
foldFDivConstantDividend()