diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 52 |
1 files changed, 17 insertions, 35 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index b445c33e88c..2959c09cbb5 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -669,42 +669,24 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) return replaceInstUsesWith(I, V); - // Handle symmetric situation in a 2-iteration loop - Value *Opnd0 = Op0; - Value *Opnd1 = Op1; - for (int i = 0; i < 2; i++) { - // (X*Y) * X => (X*X) * Y where Y != X - // The purpose is two-fold: - // 1) to form a power expression (of X). - // 2) potentially shorten the critical path: After transformation, the - // latency of the instruction Y is amortized by the expression of X*X, - // and therefore Y is in a "less critical" position compared to what it - // was before the transformation. - if (AllowReassociate) { - Value *Opnd0_0, *Opnd0_1; - if (Opnd0->hasOneUse() && - match(Opnd0, m_FMul(m_Value(Opnd0_0), m_Value(Opnd0_1)))) { - Value *Y = nullptr; - if (Opnd0_0 == Opnd1 && Opnd0_1 != Opnd1) - Y = Opnd0_1; - else if (Opnd0_1 == Opnd1 && Opnd0_0 != Opnd1) - Y = Opnd0_0; - - if (Y) { - BuilderTy::FastMathFlagGuard Guard(Builder); - Builder.setFastMathFlags(I.getFastMathFlags()); - Value *T = Builder.CreateFMul(Opnd1, Opnd1); - Value *R = Builder.CreateFMul(T, Y); - R->takeName(&I); - return replaceInstUsesWith(I, R); - } - } + // (X*Y) * X => (X*X) * Y where Y != X + // The purpose is two-fold: + // 1) to form a power expression (of X). + // 2) potentially shorten the critical path: After transformation, the + // latency of the instruction Y is amortized by the expression of X*X, + // and therefore Y is in a "less critical" position compared to what it + // was before the transformation. + if (I.isFast()) { + if (match(Op0, m_OneUse(m_c_FMul(m_Specific(Op1), m_Value(Y)))) && + Op1 != Y) { + Value *XX = Builder.CreateFMulFMF(Op1, Op1, &I); + return BinaryOperator::CreateFMulFMF(XX, Y, &I); + } + if (match(Op1, m_OneUse(m_c_FMul(m_Specific(Op0), m_Value(Y)))) && + Op0 != Y) { + Value *XX = Builder.CreateFMulFMF(Op0, Op0, &I); + return BinaryOperator::CreateFMulFMF(XX, Y, &I); } - - if (!isa<Constant>(Op1)) - std::swap(Opnd0, Opnd1); - else - break; } return Changed ? &I : nullptr; |