mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-09 13:41:35 +00:00
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:
parent
e9d782b7be
commit
87875dac89
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user