diff options
author | Pedro Artigas <partigas@apple.com> | 2012-11-30 19:09:41 +0000 |
---|---|---|
committer | Pedro Artigas <partigas@apple.com> | 2012-11-30 19:09:41 +0000 |
commit | 84030dcb3f532f66b13d54da7bdef9621527c5c5 (patch) | |
tree | 7a7be4aace9603cb85f0461996dd3a1ed04653e0 /lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | |
parent | cb4953089bb845afedeaaf5dfd03d8d5639fd656 (diff) | |
download | llvm-84030dcb3f532f66b13d54da7bdef9621527c5c5.tar.gz llvm-84030dcb3f532f66b13d54da7bdef9621527c5c5.tar.bz2 llvm-84030dcb3f532f66b13d54da7bdef9621527c5c5.tar.xz |
Add fast math inst combine X*log2(Y*0.5)-->X*log2(Y)-X
reviewed by Michael Ilseman <milseman@apple.com>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169025 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index cefe45ec86..dc41e16469 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -284,6 +284,83 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { if (Value *Op1v = dyn_castFNegVal(Op1)) return BinaryOperator::CreateFMul(Op0v, Op1v); + // Under unsafe algebra do: + // X * log2(0.5*Y) = X*log2(Y) - X + if (I.hasUnsafeAlgebra()) { + Value *OpX = NULL; + Value *OpY = NULL; + IntrinsicInst *Log2; + if (Op0->hasOneUse()) { + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) { + if (II->getIntrinsicID() == Intrinsic::log2 && + II->hasUnsafeAlgebra()) + { + Log2 = II; + Value *OpLog2Of = II->getArgOperand(0); + if (OpLog2Of->hasOneUse()) { + if (Instruction *I = dyn_cast<Instruction>(OpLog2Of)) { + if (I->getOpcode() == Instruction::FMul && + I->hasUnsafeAlgebra()) + { + ConstantFP *CFP = dyn_cast<ConstantFP>(I->getOperand(0)); + if (CFP && CFP->isExactlyValue(0.5)) { + OpY = I->getOperand(1); + OpX = Op1; + } else { + CFP = dyn_cast<ConstantFP>(I->getOperand(1)); + if (CFP && CFP->isExactlyValue(0.5)) { + OpY = I->getOperand(0); + OpX = Op1; + } + } + } + } + } + } + } + } + if (Op1->hasOneUse()) { + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op1)) { + if (II->getIntrinsicID() == Intrinsic::log2 && + II->hasUnsafeAlgebra()) + { + Log2 = II; + Value *OpLog2Of = II->getArgOperand(0); + if (OpLog2Of->hasOneUse()) { + if (Instruction *I = dyn_cast<Instruction>(OpLog2Of)) { + if (I->getOpcode() == Instruction::FMul && + I->hasUnsafeAlgebra()) + { + ConstantFP *CFP = dyn_cast<ConstantFP>(I->getOperand(0)); + if (CFP && CFP->isExactlyValue(0.5)) { + OpY = I->getOperand(1); + OpX = Op0; + } else { + CFP = dyn_cast<ConstantFP>(I->getOperand(1)); + if (CFP && CFP->isExactlyValue(0.5)) { + OpY = I->getOperand(0); + OpX = Op0; + } + } + } + } + } + } + } + } + // if pattern detected emit alternate sequence + if (OpX && OpY) { + Log2->setArgOperand(0, OpY); + Value *FMulVal = Builder->CreateFMul(OpX, Log2); + Instruction *FMul = dyn_cast<Instruction>(FMulVal); + assert(FMul && "Must be instruction as Log2 is instruction"); + FMul->copyFastMathFlags(Log2); + Instruction *FSub = BinaryOperator::CreateFSub(FMulVal, OpX); + FSub->copyFastMathFlags(Log2); + return FSub; + } + } + return Changed ? &I : 0; } |