summaryrefslogtreecommitdiff
path: root/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
diff options
context:
space:
mode:
authorPedro Artigas <partigas@apple.com>2012-11-30 19:09:41 +0000
committerPedro Artigas <partigas@apple.com>2012-11-30 19:09:41 +0000
commit84030dcb3f532f66b13d54da7bdef9621527c5c5 (patch)
tree7a7be4aace9603cb85f0461996dd3a1ed04653e0 /lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
parentcb4953089bb845afedeaaf5dfd03d8d5639fd656 (diff)
downloadllvm-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.cpp77
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;
}