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 | d8795040de089617862f5145f16adb3194344a53 (patch) | |
tree | 65d94f4add24828278d05671de06f917fb5c8143 | |
parent | a204f7223710403664b0412bb34ea29c328332d1 (diff) | |
download | bcm5719-llvm-d8795040de089617862f5145f16adb3194344a53.tar.gz bcm5719-llvm-d8795040de089617862f5145f16adb3194344a53.zip |
Add fast math inst combine X*log2(Y*0.5)-->X*log2(Y)-X
reviewed by Michael Ilseman <milseman@apple.com>
llvm-svn: 169025
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index cefe45ec862..dc41e16469e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/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; } |