[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Sep 9 15:03:10 PDT 2006
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.502 -> 1.503
---
Log message:
Implement Transforms/InstCombine/hoist_instr.ll
---
Diffs of the changes: (+53 -13)
InstructionCombining.cpp | 66 +++++++++++++++++++++++++++++++++++++----------
1 files changed, 53 insertions(+), 13 deletions(-)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.502 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.503
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.502 Sat Sep 9 15:26:32 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Sep 9 17:02:56 2006
@@ -1330,14 +1330,31 @@
Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
PHINode *PN = cast<PHINode>(I.getOperand(0));
unsigned NumPHIValues = PN->getNumIncomingValues();
- if (!PN->hasOneUse() || NumPHIValues == 0 ||
- !isa<Constant>(PN->getIncomingValue(0))) return 0;
+ if (!PN->hasOneUse() || NumPHIValues == 0) return 0;
- // Check to see if all of the operands of the PHI are constants. If not, we
- // cannot do the transformation.
- for (unsigned i = 1; i != NumPHIValues; ++i)
- if (!isa<Constant>(PN->getIncomingValue(i)))
- return 0;
+ // Check to see if all of the operands of the PHI are constants. If there is
+ // one non-constant value, remember the BB it is. If there is more than one
+ // bail out.
+ BasicBlock *NonConstBB = 0;
+ for (unsigned i = 0; i != NumPHIValues; ++i)
+ if (!isa<Constant>(PN->getIncomingValue(i))) {
+ if (NonConstBB) return 0; // More than one non-const value.
+ NonConstBB = PN->getIncomingBlock(i);
+
+ // If the incoming non-constant value is in I's block, we have an infinite
+ // loop.
+ if (NonConstBB == I.getParent())
+ return 0;
+ }
+
+ // If there is exactly one non-constant value, we can insert a copy of the
+ // operation in that block. However, if this is a critical edge, we would be
+ // inserting the computation one some other paths (e.g. inside a loop). Only
+ // do this if the pred block is unconditionally branching into the phi block.
+ if (NonConstBB) {
+ BranchInst *BI = dyn_cast<BranchInst>(NonConstBB->getTerminator());
+ if (!BI || !BI->isUnconditional()) return 0;
+ }
// Okay, we can do the transformation: create the new PHI node.
PHINode *NewPN = new PHINode(I.getType(), I.getName());
@@ -1349,17 +1366,40 @@
if (I.getNumOperands() == 2) {
Constant *C = cast<Constant>(I.getOperand(1));
for (unsigned i = 0; i != NumPHIValues; ++i) {
- Constant *InV = cast<Constant>(PN->getIncomingValue(i));
- NewPN->addIncoming(ConstantExpr::get(I.getOpcode(), InV, C),
- PN->getIncomingBlock(i));
+ Value *InV;
+ if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i))) {
+ InV = ConstantExpr::get(I.getOpcode(), InC, C);
+ } else {
+ assert(PN->getIncomingBlock(i) == NonConstBB);
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I))
+ InV = BinaryOperator::create(BO->getOpcode(),
+ PN->getIncomingValue(i), C, "phitmp",
+ NonConstBB->getTerminator());
+ else if (ShiftInst *SI = dyn_cast<ShiftInst>(&I))
+ InV = new ShiftInst(SI->getOpcode(),
+ PN->getIncomingValue(i), C, "phitmp",
+ NonConstBB->getTerminator());
+ else
+ assert(0 && "Unknown binop!");
+
+ WorkList.push_back(cast<Instruction>(InV));
+ }
+ NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
} else {
assert(isa<CastInst>(I) && "Unary op should be a cast!");
const Type *RetTy = I.getType();
for (unsigned i = 0; i != NumPHIValues; ++i) {
- Constant *InV = cast<Constant>(PN->getIncomingValue(i));
- NewPN->addIncoming(ConstantExpr::getCast(InV, RetTy),
- PN->getIncomingBlock(i));
+ Value *InV;
+ if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i))) {
+ InV = ConstantExpr::getCast(InC, RetTy);
+ } else {
+ assert(PN->getIncomingBlock(i) == NonConstBB);
+ InV = new CastInst(PN->getIncomingValue(i), I.getType(), "phitmp",
+ NonConstBB->getTerminator());
+ WorkList.push_back(cast<Instruction>(InV));
+ }
+ NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
}
return ReplaceInstUsesWith(I, NewPN);
More information about the llvm-commits
mailing list