Start threading across blocks with code in them, so long as the code does

not define a value that is used outside of it's block.  This catches many
more simplifications, e.g. 854 in 176.gcc, 137 in vpr, etc.

This implements branch-phi-thread.ll:test3.ll

llvm-svn: 23397
This commit is contained in:
Chris Lattner 2005-09-20 01:48:40 +00:00
parent cb6d8173d2
commit 6c70106053
1 changed files with 64 additions and 15 deletions

View File

@ -896,17 +896,24 @@ static bool BlockIsSimpleEnoughToThreadThrough(BasicBlock *BB) {
BranchInst *BI = cast<BranchInst>(BB->getTerminator());
Value *Cond = BI->getCondition();
unsigned Size = 0;
// If this basic block contains anything other than a PHI (which controls the
// branch) and branch itself, bail out. FIXME: improve this in the future.
for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) {
if (!isa<PHINode>(BBI)) return false;
for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI, ++Size) {
if (Size > 10) return false; // Don't clone large BB's.
if (&*BBI != Cond || !Cond->hasOneUse())
return false;
// We can only support instructions that are do not define values that are
// live outside of the current basic block.
for (Value::use_iterator UI = BBI->use_begin(), E = BBI->use_end();
UI != E; ++UI) {
Instruction *U = cast<Instruction>(*UI);
if (U->getParent() != BB || isa<PHINode>(U)) return false;
}
// Looks ok, continue checking.
}
return true;
}
@ -944,22 +951,64 @@ static bool FoldCondBranchOnPHI(BranchInst *BI) {
BasicBlock *PredBB = PN->getIncomingBlock(i);
BasicBlock *RealDest = BI->getSuccessor(!CB->getValue());
// If there are PHI nodes in the destination block, we have to add an
// entry for PredBB. Instead of being smart about this, just split the
// critical edge, which will eliminate the PHI-ness.
if (isa<PHINode>(RealDest->begin())) {
SplitCriticalEdge(BI, !CB->getValue());
RealDest = BI->getSuccessor(!CB->getValue());
}
assert(!isa<PHINode>(RealDest->begin()) && "Crit edge split failure!");
if (RealDest == BB) continue; // Skip self loops.
// The dest block might have PHI nodes, other predecessors and other
// difficult cases. Instead of being smart about this, just insert a new
// block that jumps to the destination block, effectively splitting
// the edge we are about to create.
BasicBlock *EdgeBB = new BasicBlock(RealDest->getName()+".critedge",
RealDest->getParent(), RealDest);
new BranchInst(RealDest, EdgeBB);
PHINode *PN;
for (BasicBlock::iterator BBI = RealDest->begin();
(PN = dyn_cast<PHINode>(BBI)); ++BBI) {
Value *V = PN->getIncomingValueForBlock(BB);
PN->addIncoming(V, EdgeBB);
}
// BB may have instructions that are being threaded over. Clone these
// instructions into EdgeBB. We know that there will be no uses of the
// cloned instructions outside of EdgeBB.
BasicBlock::iterator InsertPt = EdgeBB->begin();
std::map<Value*, Value*> TranslateMap; // Track translated values.
for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) {
if (PHINode *PN = dyn_cast<PHINode>(BBI)) {
TranslateMap[PN] = PN->getIncomingValueForBlock(PredBB);
} else {
// Clone the instruction.
Instruction *N = BBI->clone();
if (BBI->hasName()) N->setName(BBI->getName()+".c");
// Update operands due to translation.
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
std::map<Value*, Value*>::iterator PI =
TranslateMap.find(N->getOperand(i));
if (PI != TranslateMap.end())
N->setOperand(i, PI->second);
}
// Check for trivial simplification.
if (Constant *C = ConstantFoldInstruction(N)) {
std::cerr << "FOLDED: " << *N;
TranslateMap[BBI] = C;
delete N; // Constant folded away, don't need actual inst
} else {
// Insert the new instruction into its new home.
EdgeBB->getInstList().insert(InsertPt, N);
if (!BBI->use_empty())
TranslateMap[BBI] = N;
}
}
}
// Loop over all of the edges from PredBB to BB, changing them to branch
// to RealDest instead.
// to EdgeBB instead.
TerminatorInst *PredBBTI = PredBB->getTerminator();
for (unsigned i = 0, e = PredBBTI->getNumSuccessors(); i != e; ++i)
if (PredBBTI->getSuccessor(i) == BB) {
BB->removePredecessor(PredBB);
PredBBTI->setSuccessor(i, RealDest);
PredBBTI->setSuccessor(i, EdgeBB);
}
// Recurse, simplifying any other constants.