Implement Transforms/InstCombine/hoist_instr.ll

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30234 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2006-09-09 22:02:56 +00:00
parent 4b78a54f38
commit 2a86f3b744

View File

@@ -1330,14 +1330,31 @@ static Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) { Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
PHINode *PN = cast<PHINode>(I.getOperand(0)); PHINode *PN = cast<PHINode>(I.getOperand(0));
unsigned NumPHIValues = PN->getNumIncomingValues(); unsigned NumPHIValues = PN->getNumIncomingValues();
if (!PN->hasOneUse() || NumPHIValues == 0 || if (!PN->hasOneUse() || NumPHIValues == 0) return 0;
!isa<Constant>(PN->getIncomingValue(0))) return 0;
// Check to see if all of the operands of the PHI are constants. If not, we // Check to see if all of the operands of the PHI are constants. If there is
// cannot do the transformation. // one non-constant value, remember the BB it is. If there is more than one
for (unsigned i = 1; i != NumPHIValues; ++i) // bail out.
if (!isa<Constant>(PN->getIncomingValue(i))) BasicBlock *NonConstBB = 0;
return 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. // Okay, we can do the transformation: create the new PHI node.
PHINode *NewPN = new PHINode(I.getType(), I.getName()); PHINode *NewPN = new PHINode(I.getType(), I.getName());
@@ -1349,17 +1366,40 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
if (I.getNumOperands() == 2) { if (I.getNumOperands() == 2) {
Constant *C = cast<Constant>(I.getOperand(1)); Constant *C = cast<Constant>(I.getOperand(1));
for (unsigned i = 0; i != NumPHIValues; ++i) { for (unsigned i = 0; i != NumPHIValues; ++i) {
Constant *InV = cast<Constant>(PN->getIncomingValue(i)); Value *InV;
NewPN->addIncoming(ConstantExpr::get(I.getOpcode(), InV, C), if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i))) {
PN->getIncomingBlock(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 { } else {
assert(isa<CastInst>(I) && "Unary op should be a cast!"); assert(isa<CastInst>(I) && "Unary op should be a cast!");
const Type *RetTy = I.getType(); const Type *RetTy = I.getType();
for (unsigned i = 0; i != NumPHIValues; ++i) { for (unsigned i = 0; i != NumPHIValues; ++i) {
Constant *InV = cast<Constant>(PN->getIncomingValue(i)); Value *InV;
NewPN->addIncoming(ConstantExpr::getCast(InV, RetTy), if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i))) {
PN->getIncomingBlock(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); return ReplaceInstUsesWith(I, NewPN);