1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

finish the first cut of a jump threading pass implementation.

llvm-svn: 50006
This commit is contained in:
Chris Lattner 2008-04-20 22:39:42 +00:00
parent 4037996a0c
commit 56fbe56c25

View File

@ -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;
}
DOUT << " Threading BB '" << BB.getNameStart() << "'. Cost is: "
<< 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) {
// 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);
}
// 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);
}
}