diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 69 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/fmul.ll | 12 |
2 files changed, 23 insertions, 58 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 1529911c5a9..799493c6550 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -447,35 +447,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { return Changed ? &I : nullptr; } -/// Detect pattern log2(Y * 0.5) with corresponding fast math flags. -static void detectLog2OfHalf(Value *&Op, Value *&Y, IntrinsicInst *&Log2) { - if (!Op->hasOneUse()) - return; - - IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op); - if (!II) - return; - if (II->getIntrinsicID() != Intrinsic::log2 || !II->isFast()) - return; - Log2 = II; - - Value *OpLog2Of = II->getArgOperand(0); - if (!OpLog2Of->hasOneUse()) - return; - - Instruction *I = dyn_cast<Instruction>(OpLog2Of); - if (!I) - return; - - if (I->getOpcode() != Instruction::FMul || !I->isFast()) - return; - - if (match(I->getOperand(0), m_SpecificFP(0.5))) - Y = I->getOperand(1); - else if (match(I->getOperand(1), m_SpecificFP(0.5))) - Y = I->getOperand(0); -} - /// Helper function of InstCombiner::visitFMul(). Return true iff the given /// value is FMul or FDiv with one and only one operand being a finite-non-zero /// constant (i.e. not Zero/NaN/Infinity). @@ -617,30 +588,24 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::fabs>(m_Value(X)))) return BinaryOperator::CreateFMulFMF(X, X, &I); - // Under unsafe algebra do: - // X * log2(0.5*Y) = X*log2(Y) - X - if (AllowReassociate) { - Value *OpX = nullptr; - Value *OpY = nullptr; - IntrinsicInst *Log2; - detectLog2OfHalf(Op0, OpY, Log2); - if (OpY) { - OpX = Op1; - } else { - detectLog2OfHalf(Op1, OpY, Log2); - if (OpY) { - OpX = Op0; - } + // log2(X * 0.5) * Y = log2(X) * Y - Y + if (I.isFast()) { + IntrinsicInst *Log2 = nullptr; + if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>( + m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) { + Log2 = cast<IntrinsicInst>(Op0); + Y = Op1; + } + if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::log2>( + m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) { + Log2 = cast<IntrinsicInst>(Op1); + Y = Op0; } - // if pattern detected emit alternate sequence - if (OpX && OpY) { - BuilderTy::FastMathFlagGuard Guard(Builder); - Builder.setFastMathFlags(Log2->getFastMathFlags()); - Log2->setArgOperand(0, OpY); - Value *FMulVal = Builder.CreateFMul(OpX, Log2); - Value *FSub = Builder.CreateFSub(FMulVal, OpX); - FSub->takeName(&I); - return replaceInstUsesWith(I, FSub); + if (Log2) { + Log2->setArgOperand(0, X); + Log2->copyFastMathFlags(&I); + Value *LogXTimesY = Builder.CreateFMulFMF(Log2, Y, &I); + return BinaryOperator::CreateFSubFMF(LogXTimesY, Y, &I); } } diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll index a1c0ae12153..3637f6c2b59 100644 --- a/llvm/test/Transforms/InstCombine/fmul.ll +++ b/llvm/test/Transforms/InstCombine/fmul.ll @@ -302,7 +302,7 @@ define float @reassoc_common_operand_multi_use(float %x, float %y) { declare float @llvm.log2.f32(float) -; X * log2(Y * 0.5) = X * log2(Y) - X +; log2(Y * 0.5) * X = log2(Y) * X - X define float @log2half(float %x, float %y) { ; CHECK-LABEL: @log2half( @@ -311,8 +311,8 @@ define float @log2half(float %x, float %y) { ; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]] ; CHECK-NEXT: ret float [[MUL]] ; - %halfy = fmul fast float %y, 0.5 - %log2 = call fast float @llvm.log2.f32(float %halfy) + %halfy = fmul float %y, 0.5 + %log2 = call float @llvm.log2.f32(float %halfy) %mul = fmul fast float %log2, %x ret float %mul } @@ -321,13 +321,13 @@ define float @log2half_commute(float %x1, float %y) { ; CHECK-LABEL: @log2half_commute( ; CHECK-NEXT: [[X:%.*]] = fdiv float [[X1:%.*]], 7.000000e+00 ; CHECK-NEXT: [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X]], [[LOG2]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]] ; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]] ; CHECK-NEXT: ret float [[MUL]] ; %x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization - %halfy = fmul fast float %y, 0.5 - %log2 = call fast float @llvm.log2.f32(float %halfy) + %halfy = fmul float %y, 0.5 + %log2 = call float @llvm.log2.f32(float %halfy) %mul = fmul fast float %x, %log2 ret float %mul } |