diff options
author | Chris Lattner <sabre@nondot.org> | 2008-04-20 22:39:42 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-04-20 22:39:42 +0000 |
commit | ee23b836bdc9c6f908fdd1ac57bba053c7280f7d (patch) | |
tree | 6ec52df444b87f07aeb0e6432ce57ef4a8998462 /lib/Transforms | |
parent | fe86ab2635ff138cc9c315c5b19ca433f10ffa35 (diff) | |
download | external_llvm-ee23b836bdc9c6f908fdd1ac57bba053c7280f7d.zip external_llvm-ee23b836bdc9c6f908fdd1ac57bba053c7280f7d.tar.gz external_llvm-ee23b836bdc9c6f908fdd1ac57bba053c7280f7d.tar.bz2 |
finish the first cut of a jump threading pass implementation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50006 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/JumpThreading.cpp | 162 |
1 files changed, 141 insertions, 21 deletions
diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 9f870ab..358b8e2 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -15,13 +15,16 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/IntrinsicInst.h" #include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" using namespace llvm; -//STATISTIC(NumThreads, "Number of jumps threaded"); +STATISTIC(NumThreads, "Number of jumps threaded"); +STATISTIC(NumFolds, "Number of terminators folded"); static cl::opt<unsigned> Threshold("jump-threading-threshold", @@ -51,7 +54,8 @@ namespace { JumpThreading() : FunctionPass((intptr_t)&ID) {} bool runOnFunction(Function &F); - bool ThreadBlock(BasicBlock &BB); + bool ThreadBlock(BasicBlock *BB); + void ThreadEdge(BasicBlock *BB, BasicBlock *PredBB, BasicBlock *SuccBB); }; char JumpThreading::ID = 0; RegisterPass<JumpThreading> X("jump-threading", "Jump Threading"); @@ -64,16 +68,24 @@ FunctionPass *llvm::createJumpThreadingPass() { return new JumpThreading(); } /// bool JumpThreading::runOnFunction(Function &F) { DOUT << "Jump threading on function '" << F.getNameStart() << "'\n"; - bool Changed = false; - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - Changed |= ThreadBlock(*I); - return Changed; + + bool AnotherIteration = true, EverChanged = false; + while (AnotherIteration) { + AnotherIteration = false; + bool Changed = false; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + while (ThreadBlock(I)) + Changed = true; + AnotherIteration = Changed; + EverChanged |= Changed; + } + return EverChanged; } /// getJumpThreadDuplicationCost - Return the cost of duplicating this block to /// thread across it. -static unsigned getJumpThreadDuplicationCost(const BasicBlock &BB) { - BasicBlock::const_iterator I = BB.begin(); +static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) { + BasicBlock::const_iterator I = BB->begin(); /// Ignore PHI nodes, these will be flattened when duplication happens. while (isa<PHINode>(*I)) ++I; @@ -114,31 +126,45 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock &BB) { /// ThreadBlock - If there are any predecessors whose control can be threaded /// through to a successor, transform them now. -bool JumpThreading::ThreadBlock(BasicBlock &BB) { - // If there is only one predecessor or successor, then there is nothing to do. - if (BB.getTerminator()->getNumSuccessors() == 1 || BB.getSinglePredecessor()) - return false; - +bool JumpThreading::ThreadBlock(BasicBlock *BB) { // See if this block ends with a branch of switch. If so, see if the // condition is a phi node. If so, and if an entry of the phi node is a // constant, we can thread the block. Value *Condition; - if (BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator())) + if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) { + // Can't thread an unconditional jump. + if (BI->isUnconditional()) return false; Condition = BI->getCondition(); - else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator())) + } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) Condition = SI->getCondition(); else return false; // Must be an invoke. + + // If the terminator of this block is branching on a constant, simplify the + // terminator to an unconditional branch. This can occur do to threading in + // other blocks. + if (isa<ConstantInt>(Condition)) { + DOUT << " In block '" << BB->getNameStart() + << "' folding terminator: " << *BB->getTerminator(); + ++NumFolds; + ConstantFoldTerminator(BB); + return true; + } + + // If there is only a single predecessor of this block, nothing to fold. + if (BB->getSinglePredecessor()) + return false; // See if this is a phi node in the current block. PHINode *PN = dyn_cast<PHINode>(Condition); - if (!PN || PN->getParent() != &BB) return false; + if (!PN || PN->getParent() != BB) return false; // See if the phi node has any constant values. If so, we can determine where // the corresponding predecessor will branch. unsigned PredNo = ~0U; + ConstantInt *PredCst = 0; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - if (isa<ConstantInt>(PN->getIncomingValue(i))) { + if ((PredCst = dyn_cast<ConstantInt>(PN->getIncomingValue(i)))) { PredNo = i; break; } @@ -152,13 +178,107 @@ bool JumpThreading::ThreadBlock(BasicBlock &BB) { // See if the cost of duplicating this block is low enough. unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB); if (JumpThreadCost > Threshold) { - DOUT << " Not threading BB '" << BB.getNameStart() + DOUT << " Not threading BB '" << BB->getNameStart() << "' - Cost is too high: " << JumpThreadCost << "\n"; return false; } + + // If so, we can actually do this threading. Figure out which predecessor and + // which successor we are threading for. + BasicBlock *PredBB = PN->getIncomingBlock(PredNo); + BasicBlock *SuccBB; + if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) + SuccBB = BI->getSuccessor(PredCst == ConstantInt::getFalse()); + else { + SwitchInst *SI = cast<SwitchInst>(BB->getTerminator()); + SuccBB = SI->getSuccessor(SI->findCaseValue(PredCst)); + } + + // TODO: If there are multiple preds with the same incoming value for the PHI, + // factor them together so we get one thread block for the whole group. This + // is important for things like "phi i1 [true, true, false, true, x]" where + // we only need to clone the block for the true blocks once. + + DOUT << " Threading edge from '" << PredBB->getNameStart() << "' to '" + << SuccBB->getNameStart() << "' with cost: " << JumpThreadCost + << ", across block:\n " + << *BB; + + ThreadEdge(BB, PredBB, SuccBB); + ++NumThreads; + return true; +} + +/// ThreadEdge - We have decided that it is safe and profitable to thread an +/// edge from PredBB to SuccBB across BB. Transform the IR to reflect this +/// change. +void JumpThreading::ThreadEdge(BasicBlock *BB, BasicBlock *PredBB, + BasicBlock *SuccBB) { - DOUT << " Threading BB '" << BB.getNameStart() << "'. Cost is: " - << JumpThreadCost << "\n"; + // Jump Threading can not update SSA properties correctly if the values + // defined in the duplicated block are used outside of the block itself. For + // this reason, we spill all values that are used outside of BB to the stack. + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) + if (I->isUsedOutsideOfBlock(BB)) { + // We found a use of I outside of BB. Create a new stack slot to + // break this inter-block usage pattern. + DemoteRegToStack(*I); + } + + // We are going to have to map operands from the original BB block to the new + // copy of the block 'NewBB'. If there are PHI nodes in BB, evaluate them to + // account for entry from PredBB. + DenseMap<Instruction*, Value*> ValueMapping; + + BasicBlock *NewBB = + BasicBlock::Create(BB->getName()+".thread", BB->getParent(), BB); + NewBB->moveAfter(PredBB); + + BasicBlock::iterator BI = BB->begin(); + for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI) + ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB); + + // Clone the non-phi instructions of BB into NewBB, keeping track of the + // mapping and using it to remap operands in the cloned instructions. + for (; !isa<TerminatorInst>(BI); ++BI) { + Instruction *New = BI->clone(); + New->setName(BI->getNameStart()); + NewBB->getInstList().push_back(New); + ValueMapping[BI] = New; + + // Remap operands to patch up intra-block references. + for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i) + if (Instruction *Inst = dyn_cast<Instruction>(New->getOperand(i))) + if (Value *Remapped = ValueMapping[Inst]) + New->setOperand(i, Remapped); + } + + // We didn't copy the terminator from BB over to NewBB, because there is now + // an unconditional jump to SuccBB. Insert the unconditional jump. + BranchInst::Create(SuccBB, NewBB); + + // Check to see if SuccBB has PHI nodes. If so, we need to add entries to the + // PHI nodes for NewBB now. + for (BasicBlock::iterator PNI = SuccBB->begin(); isa<PHINode>(PNI); ++PNI) { + PHINode *PN = cast<PHINode>(PNI); + // Ok, we have a PHI node. Figure out what the incoming value was for the + // DestBlock. + Value *IV = PN->getIncomingValueForBlock(BB); + + // Remap the value if necessary. + if (Instruction *Inst = dyn_cast<Instruction>(IV)) + if (Value *MappedIV = ValueMapping[Inst]) + IV = MappedIV; + PN->addIncoming(IV, NewBB); + } - return false; + // Finally, NewBB is good to go. Update the terminator of PredBB to jump to + // NewBB instead of BB. This eliminates predecessors from BB, which requires + // us to simplify any PHI nodes in BB. + TerminatorInst *PredTerm = PredBB->getTerminator(); + for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i) + if (PredTerm->getSuccessor(i) == BB) { + BB->removePredecessor(PredBB); + PredTerm->setSuccessor(i, NewBB); + } } |