[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Jan 19 13:50:31 PST 2005
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.307 -> 1.308
---
Log message:
Add two optimizations. The first folds (X+Y)-X -> Y
The second folds operations into selects, e.g. (select C, (X+Y), (Y+Z))
-> (Y+(select C, X, Z)
This occurs a few times across spec, e.g.
select add/sub
mesa: 83 0
povray: 5 2
gcc 4 2
parser 0 22
perlbmk 13 30
twolf 0 3
---
Diffs of the changes: (+89 -2)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.307 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.308
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.307 Sun Jan 16 23:10:15 2005
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Jan 19 15:50:18 2005
@@ -120,6 +120,8 @@
Instruction::BinaryOps Cond, Instruction &I);
Instruction *visitShiftInst(ShiftInst &I);
Instruction *visitCastInst(CastInst &CI);
+ Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI,
+ Instruction *FI);
Instruction *visitSelectInst(SelectInst &CI);
Instruction *visitCallInst(CallInst &CI);
Instruction *visitInvokeInst(InvokeInst &II);
@@ -833,6 +835,14 @@
}
}
+ if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
+ if (Op0I->getOpcode() == Instruction::Add)
+ if (!Op0->getType()->isFloatingPoint()) {
+ if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
+ return ReplaceInstUsesWith(I, Op0I->getOperand(1));
+ else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
+ return ReplaceInstUsesWith(I, Op0I->getOperand(0));
+ }
ConstantInt *C1;
if (Value *X = dyn_castFoldableMul(Op0, C1)) {
@@ -3496,6 +3506,78 @@
}
}
+/// FoldSelectOpOp - Here we have (select c, TI, FI), and we know that TI and FI
+/// have the same opcode and only one use each. Try to simplify this.
+Instruction *InstCombiner::FoldSelectOpOp(SelectInst &SI, Instruction *TI,
+ Instruction *FI) {
+ if (TI->getNumOperands() == 1) {
+ // If this is a non-volatile load or a cast from the same type,
+ // merge.
+ if (TI->getOpcode() == Instruction::Cast) {
+ if (TI->getOperand(0)->getType() != FI->getOperand(0)->getType())
+ return 0;
+ } else {
+ return 0; // unknown unary op.
+ }
+
+ // Fold this by inserting a select from the input values.
+ SelectInst *NewSI = new SelectInst(SI.getCondition(), TI->getOperand(0),
+ FI->getOperand(0), SI.getName()+".v");
+ InsertNewInstBefore(NewSI, SI);
+ return new CastInst(NewSI, TI->getType());
+ }
+
+ // Only handle binary operators here.
+ if (!isa<ShiftInst>(TI) && !isa<BinaryOperator>(TI))
+ return 0;
+
+ // Figure out if the operations have any operands in common.
+ Value *MatchOp, *OtherOpT, *OtherOpF;
+ bool MatchIsOpZero;
+ if (TI->getOperand(0) == FI->getOperand(0)) {
+ MatchOp = TI->getOperand(0);
+ OtherOpT = TI->getOperand(1);
+ OtherOpF = FI->getOperand(1);
+ MatchIsOpZero = true;
+ } else if (TI->getOperand(1) == FI->getOperand(1)) {
+ MatchOp = TI->getOperand(1);
+ OtherOpT = TI->getOperand(0);
+ OtherOpF = FI->getOperand(0);
+ MatchIsOpZero = false;
+ } else if (!TI->isCommutative()) {
+ return 0;
+ } else if (TI->getOperand(0) == FI->getOperand(1)) {
+ MatchOp = TI->getOperand(0);
+ OtherOpT = TI->getOperand(1);
+ OtherOpF = FI->getOperand(0);
+ MatchIsOpZero = true;
+ } else if (TI->getOperand(1) == FI->getOperand(0)) {
+ MatchOp = TI->getOperand(1);
+ OtherOpT = TI->getOperand(0);
+ OtherOpF = FI->getOperand(1);
+ MatchIsOpZero = true;
+ } else {
+ return 0;
+ }
+
+ // If we reach here, they do have operations in common.
+ SelectInst *NewSI = new SelectInst(SI.getCondition(), OtherOpT,
+ OtherOpF, SI.getName()+".v");
+ InsertNewInstBefore(NewSI, SI);
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TI)) {
+ if (MatchIsOpZero)
+ return BinaryOperator::create(BO->getOpcode(), MatchOp, NewSI);
+ else
+ return BinaryOperator::create(BO->getOpcode(), NewSI, MatchOp);
+ } else {
+ if (MatchIsOpZero)
+ return new ShiftInst(cast<ShiftInst>(TI)->getOpcode(), MatchOp, NewSI);
+ else
+ return new ShiftInst(cast<ShiftInst>(TI)->getOpcode(), NewSI, MatchOp);
+ }
+}
+
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
Value *CondVal = SI.getCondition();
Value *TrueVal = SI.getTrueValue();
@@ -3616,14 +3698,19 @@
}
}
- // 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;
+ // Turn (select C, (op X, Y), (op X, Z)) -> (op X, (select C, Y, Z))
+ if (TI->getOpcode() == FI->getOpcode())
+ if (Instruction *IV = FoldSelectOpOp(SI, TI, FI))
+ return IV;
+
+ // Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is
+ // even legal for FP.
if (TI->getOpcode() == Instruction::Sub &&
FI->getOpcode() == Instruction::Add) {
AddOp = FI; SubOp = TI;
More information about the llvm-commits
mailing list