From: Sanjay Patel Date: Wed, 24 Feb 2021 20:31:59 +0000 (-0500) Subject: [InstCombine] add helper for x/pow(); NFC X-Git-Tag: llvmorg-14-init~14114 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=868d43fbd6571d11f91564969676bb0f1b19b455;p=platform%2Fupstream%2Fllvm.git [InstCombine] add helper for x/pow(); NFC We at least want to add powi to this list, so split it off into a switch to reduce code duplication. --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 702f76d..5cfa922 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1274,6 +1274,37 @@ static Instruction *foldFDivConstantDividend(BinaryOperator &I) { return BinaryOperator::CreateFDivFMF(NewC, X, &I); } +/// Negate the exponent of pow/exp to fold division-by-pow() into multiply. +static Instruction *foldFDivPowDivisor(BinaryOperator &I, + InstCombiner::BuilderTy &Builder) { + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + auto *II = dyn_cast(Op1); + if (!II || !II->hasOneUse() || !I.hasAllowReassoc() || + !I.hasAllowReciprocal()) + return nullptr; + + // Z / pow(X, Y) --> Z * pow(X, -Y) + // Z / exp{2}(Y) --> Z * exp{2}(-Y) + // In the general case, this creates an extra instruction, but fmul allows + // for better canonicalization and optimization than fdiv. + Intrinsic::ID IID = II->getIntrinsicID(); + SmallVector Args; + switch (IID) { + case Intrinsic::pow: + Args.push_back(II->getArgOperand(0)); + Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(1), &I)); + break; + case Intrinsic::exp: + case Intrinsic::exp2: + Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(0), &I)); + break; + default: + return nullptr; + } + Value *Pow = Builder.CreateIntrinsic(IID, I.getType(), Args, &I); + return BinaryOperator::CreateFMulFMF(Op0, Pow, &I); +} + Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { if (Value *V = SimplifyFDivInst(I.getOperand(0), I.getOperand(1), I.getFastMathFlags(), @@ -1325,28 +1356,6 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { // replaced by a multiplication. if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) return BinaryOperator::CreateFMulFMF(Y, Op0, &I); - - // Negate the exponent of pow/exp to fold division-by-pow() into multiply: - // Z / pow(X, Y) --> Z * pow(X, -Y) - // Z / exp{2}(Y) --> Z * exp{2}(-Y) - // In the general case, this creates an extra instruction, but fmul allows - // for better canonicalization and optimization than fdiv. - if (match(Op1, - m_OneUse(m_Intrinsic(m_Value(X), m_Value(Y))))) { - Value *NegY = Builder.CreateFNegFMF(Y, &I); - Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, NegY, &I); - return BinaryOperator::CreateFMulFMF(Op0, Pow, &I); - } - if (match(Op1, m_OneUse(m_Intrinsic(m_Value(Y))))) { - Value *NegY = Builder.CreateFNegFMF(Y, &I); - Value *Pow = Builder.CreateUnaryIntrinsic(Intrinsic::exp, NegY, &I); - return BinaryOperator::CreateFMulFMF(Op0, Pow, &I); - } - if (match(Op1, m_OneUse(m_Intrinsic(m_Value(Y))))) { - Value *NegY = Builder.CreateFNegFMF(Y, &I); - Value *Pow = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, NegY, &I); - return BinaryOperator::CreateFMulFMF(Op0, Pow, &I); - } } if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) { @@ -1394,6 +1403,10 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { Intrinsic::copysign, ConstantFP::get(I.getType(), 1.0), X, &I); return replaceInstUsesWith(I, V); } + + if (Instruction *Mul = foldFDivPowDivisor(I, Builder)) + return Mul; + return nullptr; }