[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Fri Apr 9 18:46:01 PDT 2004
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.184 -> 1.185
---
Log message:
Implement select.ll:test12*
This transforms code like this:
%C = or %A, %B
%D = select %cond, %C, %A
into:
%C = select %cond, %B, 0
%D = or %A, %C
Since B is often a constant, the select can often be eliminated. In any case,
this reduces the usage count of A, allowing subsequent optimizations to happen.
This xform applies when the operator is any of:
add, sub, mul, or, xor, and, shl, shr
---
Diffs of the changes: (+108 -0)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.184 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.185
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.184 Fri Apr 9 14:05:30 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Fri Apr 9 18:46:01 2004
@@ -2091,6 +2091,54 @@
return 0;
}
+/// GetSelectFoldableOperands - We want to turn code that looks like this:
+/// %C = or %A, %B
+/// %D = select %cond, %C, %A
+/// into:
+/// %C = select %cond, %B, 0
+/// %D = or %A, %C
+///
+/// Assuming that the specified instruction is an operand to the select, return
+/// a bitmask indicating which operands of this instruction are foldable if they
+/// equal the other incoming value of the select.
+///
+static unsigned GetSelectFoldableOperands(Instruction *I) {
+ switch (I->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Mul:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
+ return 3; // Can fold through either operand.
+ case Instruction::Sub: // Can only fold on the amount subtracted.
+ case Instruction::Shl: // Can only fold on the shift amount.
+ case Instruction::Shr:
+ return 1;
+ default:
+ return 0; // Cannot fold
+ }
+}
+
+/// GetSelectFoldableConstant - For the same transformation as the previous
+/// function, return the identity constant that goes into the select.
+static Constant *GetSelectFoldableConstant(Instruction *I) {
+ switch (I->getOpcode()) {
+ default: assert(0 && "This cannot happen!"); abort();
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Or:
+ case Instruction::Xor:
+ return Constant::getNullValue(I->getType());
+ case Instruction::Shl:
+ case Instruction::Shr:
+ return Constant::getNullValue(Type::UByteTy);
+ case Instruction::And:
+ return ConstantInt::getAllOnesValue(I->getType());
+ case Instruction::Mul:
+ return ConstantInt::get(I->getType(), 1);
+ }
+}
+
Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
Value *CondVal = SI.getCondition();
Value *TrueVal = SI.getTrueValue();
@@ -2150,6 +2198,66 @@
}
}
+ // 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
+ // transformation we are doing here.
+ if (Instruction *TVI = dyn_cast<Instruction>(TrueVal))
+ if (TVI->hasOneUse() && TVI->getNumOperands() == 2 &&
+ !isa<Constant>(FalseVal))
+ if (unsigned SFO = GetSelectFoldableOperands(TVI)) {
+ unsigned OpToFold = 0;
+ if ((SFO & 1) && FalseVal == TVI->getOperand(0)) {
+ OpToFold = 1;
+ } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) {
+ OpToFold = 2;
+ }
+
+ if (OpToFold) {
+ Constant *C = GetSelectFoldableConstant(TVI);
+ std::string Name = TVI->getName(); TVI->setName("");
+ Instruction *NewSel =
+ new SelectInst(SI.getCondition(), TVI->getOperand(2-OpToFold), C,
+ Name);
+ InsertNewInstBefore(NewSel, SI);
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TVI))
+ return BinaryOperator::create(BO->getOpcode(), FalseVal, NewSel);
+ else if (ShiftInst *SI = dyn_cast<ShiftInst>(TVI))
+ return new ShiftInst(SI->getOpcode(), FalseVal, NewSel);
+ else {
+ assert(0 && "Unknown instruction!!");
+ }
+ }
+ }
+
+ if (Instruction *FVI = dyn_cast<Instruction>(FalseVal))
+ if (FVI->hasOneUse() && FVI->getNumOperands() == 2 &&
+ !isa<Constant>(TrueVal))
+ if (unsigned SFO = GetSelectFoldableOperands(FVI)) {
+ unsigned OpToFold = 0;
+ if ((SFO & 1) && TrueVal == FVI->getOperand(0)) {
+ OpToFold = 1;
+ } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) {
+ OpToFold = 2;
+ }
+
+ if (OpToFold) {
+ Constant *C = GetSelectFoldableConstant(FVI);
+ std::string Name = FVI->getName(); FVI->setName("");
+ Instruction *NewSel =
+ new SelectInst(SI.getCondition(), C, FVI->getOperand(2-OpToFold),
+ Name);
+ InsertNewInstBefore(NewSel, SI);
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(FVI))
+ return BinaryOperator::create(BO->getOpcode(), TrueVal, NewSel);
+ else if (ShiftInst *SI = dyn_cast<ShiftInst>(FVI))
+ return new ShiftInst(SI->getOpcode(), TrueVal, NewSel);
+ else {
+ assert(0 && "Unknown instruction!!");
+ }
+ }
+ }
+ }
return 0;
}
More information about the llvm-commits
mailing list