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
This commit is contained in:
Chris Lattner 2005-01-13 22:52:24 +00:00
parent e9d782b7be
commit 87875dac89

View File

@ -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