aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp68
1 files changed, 54 insertions, 14 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 21f1b2bfe6..0e6c1b1f2d 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -1330,14 +1330,31 @@ static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
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;
-
- // 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;
+ if (!PN->hasOneUse() || NumPHIValues == 0) 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 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
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);