aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/Reassociate.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erikjv@me.com>2014-08-21 10:45:30 +0000
committerErik Verbruggen <erikjv@me.com>2014-08-21 10:45:30 +0000
commit0edc5e839156ce1b8af863a01398c190634e99f0 (patch)
treeb3d9feea26edce176cf3ae8cf63d91abeba7936d /lib/Transforms/Scalar/Reassociate.cpp
parentf11ac42d01b99970f5335a78dd4277184c3a3c1f (diff)
Reassociate x + -0.1234 * y into x - 0.1234 * y
This does not require -ffast-math, and it gives CSE/GVN more options to eliminate duplicate expressions in, e.g.: return ((x + 0.1234 * y) * (x - 0.1234 * y)); Differential Revision: http://reviews.llvm.org/D4904 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216169 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/Reassociate.cpp')
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp51
1 files changed, 49 insertions, 2 deletions
diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp
index b11567cc9df..d0cd48a3a26 100644
--- a/lib/Transforms/Scalar/Reassociate.cpp
+++ b/lib/Transforms/Scalar/Reassociate.cpp
@@ -193,6 +193,8 @@ namespace {
Value *OptimizeMul(BinaryOperator *I, SmallVectorImpl<ValueEntry> &Ops);
Value *RemoveFactorFromExpression(Value *V, Value *Factor);
void EraseInst(Instruction *I);
+ void optimizeFAddNegExpr(ConstantFP *ConstOperand, Instruction *I,
+ int OperandNr);
void OptimizeInst(Instruction *I);
};
}
@@ -1914,6 +1916,33 @@ void Reassociate::EraseInst(Instruction *I) {
}
}
+void Reassociate::optimizeFAddNegExpr(ConstantFP *ConstOperand, Instruction *I,
+ int OperandNr) {
+ // Change the sign of the constant.
+ APFloat Val = ConstOperand->getValueAPF();
+ Val.changeSign();
+ I->setOperand(0, ConstantFP::get(ConstOperand->getContext(), Val));
+
+ assert(I->hasOneUse() && "Only a single use can be replaced.");
+ Instruction *Parent = I->user_back();
+
+ Value *OtherOperand = Parent->getOperand(1 - OperandNr);
+
+ unsigned Opcode = Parent->getOpcode();
+ assert(Opcode == Instruction::FAdd ||
+ (Opcode == Instruction::FSub && Parent->getOperand(1) == I));
+
+ BinaryOperator *NI = Opcode == Instruction::FAdd
+ ? BinaryOperator::CreateFSub(OtherOperand, I)
+ : BinaryOperator::CreateFAdd(OtherOperand, I);
+ NI->setFastMathFlags(cast<FPMathOperator>(Parent)->getFastMathFlags());
+ NI->insertBefore(Parent);
+ NI->setName(Parent->getName() + ".repl");
+ Parent->replaceAllUsesWith(NI);
+ NI->setDebugLoc(I->getDebugLoc());
+ MadeChange = true;
+}
+
/// OptimizeInst - Inspect and optimize the given instruction. Note that erasing
/// instructions is not allowed.
void Reassociate::OptimizeInst(Instruction *I) {
@@ -1940,8 +1969,8 @@ void Reassociate::OptimizeInst(Instruction *I) {
if (I->getType()->isFloatingPointTy() || I->getType()->isVectorTy()) {
// FAdd and FMul can be commuted.
- if (I->getOpcode() == Instruction::FMul ||
- I->getOpcode() == Instruction::FAdd) {
+ unsigned Opcode = I->getOpcode();
+ if (Opcode == Instruction::FMul || Opcode == Instruction::FAdd) {
Value *LHS = I->getOperand(0);
Value *RHS = I->getOperand(1);
unsigned LHSRank = getRank(LHS);
@@ -1954,6 +1983,24 @@ void Reassociate::OptimizeInst(Instruction *I) {
}
}
+ // Reassociate: x + -ConstantFP * y -> x - ConstantFP * y
+ // The FMul can also be an FDiv, and FAdd can be a FSub.
+ if (Opcode == Instruction::FMul || Opcode == Instruction::FDiv) {
+ if (ConstantFP *LHSConst = dyn_cast<ConstantFP>(I->getOperand(0))) {
+ if (LHSConst->isNegative() && I->hasOneUse()) {
+ Instruction *Parent = I->user_back();
+ if (Parent->getOpcode() == Instruction::FAdd) {
+ if (Parent->getOperand(0) == I)
+ optimizeFAddNegExpr(LHSConst, I, 0);
+ else if (Parent->getOperand(1) == I)
+ optimizeFAddNegExpr(LHSConst, I, 1);
+ } else if (Parent->getOpcode() == Instruction::FSub)
+ if (Parent->getOperand(1) == I)
+ optimizeFAddNegExpr(LHSConst, I, 1);
+ }
+ }
+ }
+
// FIXME: We should commute vector instructions as well. However, this
// requires further analysis to determine the effect on later passes.