[llvm-commits] [llvm] r50006 - /llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
Chris Lattner
sabre at nondot.org
Sun Apr 20 15:39:42 PDT 2008
Author: lattner
Date: Sun Apr 20 17:39:42 2008
New Revision: 50006
URL: http://llvm.org/viewvc/llvm-project?rev=50006&view=rev
Log:
finish the first cut of a jump threading pass implementation.
Modified:
llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=50006&r1=50005&r2=50006&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Sun Apr 20 17:39:42 2008
@@ -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 @@
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 @@
///
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 @@
/// 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 @@
// 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;
+}
- DOUT << " Threading BB '" << BB.getNameStart() << "'. Cost is: "
- << JumpThreadCost << "\n";
+/// 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) {
+
+ // 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);
+ }
- return false;
+ // 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);
+ }
+
+ // 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);
+ }
}
More information about the llvm-commits
mailing list