diff options
author | Chris Lattner <sabre@nondot.org> | 2005-09-20 01:48:40 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-09-20 01:48:40 +0000 |
commit | e9487f0dc8c6d15cb257d5b49fa96ed436d32f5f (patch) | |
tree | e24e65f44abc4867a5432311b23db7d5f4cd6f5f | |
parent | 055135d1c14afa443d29c3dda02881fa76bc9b83 (diff) | |
download | external_llvm-e9487f0dc8c6d15cb257d5b49fa96ed436d32f5f.zip external_llvm-e9487f0dc8c6d15cb257d5b49fa96ed436d32f5f.tar.gz external_llvm-e9487f0dc8c6d15cb257d5b49fa96ed436d32f5f.tar.bz2 |
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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23397 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 69f8853..606678c 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -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. |