diff options
author | Chris Lattner <sabre@nondot.org> | 2005-01-13 22:52:24 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-01-13 22:52:24 +0000 |
commit | 87875dac899f9316b6b02585196cce2f077c08bc (patch) | |
tree | ed1776eeee1e461f4a267a60813a253ac67fe456 /lib/Transforms | |
parent | e9d782b7bea2578ac20a96be2233df4f1fce4ca3 (diff) |
Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
the 'sim' program and probably elsewhere. In sim, it comes up for cases
like this:
#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }
(it uses the round macro a lot). This changes the LLVM code from:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%tmp.4 = add double %X, 5.000000e-01 ; <double> [#uses=1]
%tmp.6 = sub double %X, 5.000000e-01 ; <double> [#uses=1]
%mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
store double %mem_tmp.0, double* %G
to:
%tmp.1 = setgt double %X, 0.000000e+00 ; <bool> [#uses=1]
%mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
%mem_tmp.0 = add double %mem_tmp.0.p, %X
store double %mem_tmp.0, double* %G
ret void
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index bb235ca868..b8ff3d4e7e 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3588,6 +3588,59 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { } } + // Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is legal for + // FP as well. + if (Instruction *TI = dyn_cast<Instruction>(TrueVal)) + if (Instruction *FI = dyn_cast<Instruction>(FalseVal)) + if (TI->hasOneUse() && FI->hasOneUse()) { + bool isInverse = false; + Instruction *AddOp = 0, *SubOp = 0; + + if (TI->getOpcode() == Instruction::Sub && + FI->getOpcode() == Instruction::Add) { + AddOp = FI; SubOp = TI; + } else if (FI->getOpcode() == Instruction::Sub && + TI->getOpcode() == Instruction::Add) { + AddOp = TI; SubOp = FI; + } + + if (AddOp) { + Value *OtherAddOp = 0; + if (SubOp->getOperand(0) == AddOp->getOperand(0)) { + OtherAddOp = AddOp->getOperand(1); + } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) { + OtherAddOp = AddOp->getOperand(0); + } + + if (OtherAddOp) { + // So at this point we know we have: + // select C, (add X, Y), (sub X, ?) + // We can do the transform profitably if either 'Y' = '?' or '?' is + // a constant. + if (SubOp->getOperand(1) == AddOp || + isa<Constant>(SubOp->getOperand(1))) { + Value *NegVal; + if (Constant *C = dyn_cast<Constant>(SubOp->getOperand(1))) { + NegVal = ConstantExpr::getNeg(C); + } else { + NegVal = InsertNewInstBefore( + BinaryOperator::createNeg(SubOp->getOperand(1)), SI); + } + + Value *NewTrueOp = AddOp->getOperand(1); + Value *NewFalseOp = NegVal; + if (AddOp != TI) + std::swap(NewTrueOp, NewFalseOp); + Instruction *NewSel = + new SelectInst(CondVal, NewTrueOp,NewFalseOp,SI.getName()+".p"); + + NewSel = InsertNewInstBefore(NewSel, SI); + return BinaryOperator::createAdd(AddOp->getOperand(0), NewSel); + } + } + } + } + // See if we can fold the select into one of our operands. if (SI.getType()->isInteger()) { // See the comment above GetSelectFoldableOperands for a description of the |