Reformat the implementation of mem2reg with clang-format so that my

subsequent changes don't introduce inconsistencies.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186775 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth
2013-07-20 23:20:08 +00:00
parent 360fef5f43
commit 30f23a4782

View File

@@ -62,7 +62,7 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
// Only allow direct and non-volatile loads and stores... // Only allow direct and non-volatile loads and stores...
for (Value::const_use_iterator UI = AI->use_begin(), UE = AI->use_end(); for (Value::const_use_iterator UI = AI->use_begin(), UE = AI->use_end();
UI != UE; ++UI) { // Loop over all of the uses of the alloca UI != UE; ++UI) { // Loop over all of the uses of the alloca
const User *U = *UI; const User *U = *UI;
if (const LoadInst *LI = dyn_cast<LoadInst>(U)) { if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
// Note that atomic loads can be transformed; atomic semantics do // Note that atomic loads can be transformed; atomic semantics do
@@ -71,7 +71,7 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
return false; return false;
} else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) { } else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->getOperand(0) == AI) if (SI->getOperand(0) == AI)
return false; // Don't allow a store OF the AI, only INTO the AI. return false; // Don't allow a store OF the AI, only INTO the AI.
// Note that atomic stores can be transformed; atomic semantics do // Note that atomic stores can be transformed; atomic semantics do
// not have any meaning for a local alloca. // not have any meaning for a local alloca.
if (SI->isVolatile()) if (SI->isVolatile())
@@ -101,239 +101,238 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
} }
namespace { namespace {
struct AllocaInfo;
// Data package used by RenamePass() struct AllocaInfo;
class RenamePassData {
public:
typedef std::vector<Value *> ValVector;
RenamePassData() : BB(NULL), Pred(NULL), Values() {} // Data package used by RenamePass()
RenamePassData(BasicBlock *B, BasicBlock *P, class RenamePassData {
const ValVector &V) : BB(B), Pred(P), Values(V) {} public:
BasicBlock *BB; typedef std::vector<Value *> ValVector;
BasicBlock *Pred;
ValVector Values;
void swap(RenamePassData &RHS) { RenamePassData() : BB(NULL), Pred(NULL), Values() {}
std::swap(BB, RHS.BB); RenamePassData(BasicBlock *B, BasicBlock *P, const ValVector &V)
std::swap(Pred, RHS.Pred); : BB(B), Pred(P), Values(V) {}
Values.swap(RHS.Values); BasicBlock *BB;
} BasicBlock *Pred;
}; ValVector Values;
/// \brief This assigns and keeps a per-bb relative ordering of load/store void swap(RenamePassData &RHS) {
/// instructions in the block that directly load or store an alloca. std::swap(BB, RHS.BB);
std::swap(Pred, RHS.Pred);
Values.swap(RHS.Values);
}
};
/// \brief This assigns and keeps a per-bb relative ordering of load/store
/// instructions in the block that directly load or store an alloca.
///
/// This functionality is important because it avoids scanning large basic
/// blocks multiple times when promoting many allocas in the same block.
class LargeBlockInfo {
/// \brief For each instruction that we track, keep the index of the
/// instruction.
/// ///
/// This functionality is important because it avoids scanning large basic /// The index starts out as the number of the instruction from the start of
/// blocks multiple times when promoting many allocas in the same block. /// the block.
class LargeBlockInfo { DenseMap<const Instruction *, unsigned> InstNumbers;
/// \brief For each instruction that we track, keep the index of the
/// instruction.
///
/// The index starts out as the number of the instruction from the start of
/// the block.
DenseMap<const Instruction *, unsigned> InstNumbers;
public:
/// This code only looks at accesses to allocas. public:
static bool isInterestingInstruction(const Instruction *I) {
return (isa<LoadInst>(I) && isa<AllocaInst>(I->getOperand(0))) ||
(isa<StoreInst>(I) && isa<AllocaInst>(I->getOperand(1)));
}
/// Get or calculate the index of the specified instruction. /// This code only looks at accesses to allocas.
unsigned getInstructionIndex(const Instruction *I) { static bool isInterestingInstruction(const Instruction *I) {
assert(isInterestingInstruction(I) && return (isa<LoadInst>(I) && isa<AllocaInst>(I->getOperand(0))) ||
"Not a load/store to/from an alloca?"); (isa<StoreInst>(I) && isa<AllocaInst>(I->getOperand(1)));
}
// If we already have this instruction number, return it. /// Get or calculate the index of the specified instruction.
DenseMap<const Instruction *, unsigned>::iterator It = InstNumbers.find(I); unsigned getInstructionIndex(const Instruction *I) {
if (It != InstNumbers.end()) return It->second; assert(isInterestingInstruction(I) &&
"Not a load/store to/from an alloca?");
// Scan the whole block to get the instruction. This accumulates // If we already have this instruction number, return it.
// information for every interesting instruction in the block, in order to DenseMap<const Instruction *, unsigned>::iterator It = InstNumbers.find(I);
// avoid gratuitus rescans. if (It != InstNumbers.end())
const BasicBlock *BB = I->getParent();
unsigned InstNo = 0;
for (BasicBlock::const_iterator BBI = BB->begin(), E = BB->end();
BBI != E; ++BBI)
if (isInterestingInstruction(BBI))
InstNumbers[BBI] = InstNo++;
It = InstNumbers.find(I);
assert(It != InstNumbers.end() && "Didn't insert instruction?");
return It->second; return It->second;
}
void deleteValue(const Instruction *I) { // Scan the whole block to get the instruction. This accumulates
InstNumbers.erase(I); // information for every interesting instruction in the block, in order to
} // avoid gratuitus rescans.
const BasicBlock *BB = I->getParent();
unsigned InstNo = 0;
for (BasicBlock::const_iterator BBI = BB->begin(), E = BB->end(); BBI != E;
++BBI)
if (isInterestingInstruction(BBI))
InstNumbers[BBI] = InstNo++;
It = InstNumbers.find(I);
void clear() { assert(It != InstNumbers.end() && "Didn't insert instruction?");
InstNumbers.clear(); return It->second;
} }
};
struct PromoteMem2Reg { void deleteValue(const Instruction *I) { InstNumbers.erase(I); }
/// The alloca instructions being promoted.
std::vector<AllocaInst*> Allocas;
DominatorTree &DT;
DIBuilder *DIB;
/// An AliasSetTracker object to update. If null, don't update it. void clear() { InstNumbers.clear(); }
AliasSetTracker *AST; };
/// Reverse mapping of Allocas. struct PromoteMem2Reg {
DenseMap<AllocaInst*, unsigned> AllocaLookup; /// The alloca instructions being promoted.
std::vector<AllocaInst *> Allocas;
DominatorTree &DT;
DIBuilder *DIB;
/// \brief The PhiNodes we're adding. /// An AliasSetTracker object to update. If null, don't update it.
/// AliasSetTracker *AST;
/// That map is used to simplify some Phi nodes as we iterate over it, so
/// it should have deterministic iterators. We could use a MapVector, but
/// since we already maintain a map from BasicBlock* to a stable numbering
/// (BBNumbers), the DenseMap is more efficient (also supports removal).
DenseMap<std::pair<unsigned, unsigned>, PHINode*> NewPhiNodes;
/// For each PHI node, keep track of which entry in Allocas it corresponds /// Reverse mapping of Allocas.
/// to. DenseMap<AllocaInst *, unsigned> AllocaLookup;
DenseMap<PHINode*, unsigned> PhiToAllocaMap;
/// If we are updating an AliasSetTracker, then for each alloca that is of /// \brief The PhiNodes we're adding.
/// pointer type, we keep track of what to copyValue to the inserted PHI ///
/// nodes here. /// That map is used to simplify some Phi nodes as we iterate over it, so
std::vector<Value*> PointerAllocaValues; /// it should have deterministic iterators. We could use a MapVector, but
/// since we already maintain a map from BasicBlock* to a stable numbering
/// (BBNumbers), the DenseMap is more efficient (also supports removal).
DenseMap<std::pair<unsigned, unsigned>, PHINode *> NewPhiNodes;
/// For each alloca, we keep track of the dbg.declare intrinsic that /// For each PHI node, keep track of which entry in Allocas it corresponds
/// describes it, if any, so that we can convert it to a dbg.value /// to.
/// intrinsic if the alloca gets promoted. DenseMap<PHINode *, unsigned> PhiToAllocaMap;
SmallVector<DbgDeclareInst*, 8> AllocaDbgDeclares;
/// The set of basic blocks the renamer has already visited. /// If we are updating an AliasSetTracker, then for each alloca that is of
/// /// pointer type, we keep track of what to copyValue to the inserted PHI
SmallPtrSet<BasicBlock*, 16> Visited; /// nodes here.
std::vector<Value *> PointerAllocaValues;
/// Contains a stable numbering of basic blocks to avoid non-determinstic /// For each alloca, we keep track of the dbg.declare intrinsic that
/// behavior. /// describes it, if any, so that we can convert it to a dbg.value
DenseMap<BasicBlock*, unsigned> BBNumbers; /// intrinsic if the alloca gets promoted.
SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares;
/// Maps DomTreeNodes to their level in the dominator tree. /// The set of basic blocks the renamer has already visited.
DenseMap<DomTreeNode*, unsigned> DomLevels; ///
SmallPtrSet<BasicBlock *, 16> Visited;
/// Lazily compute the number of predecessors a block has. /// Contains a stable numbering of basic blocks to avoid non-determinstic
DenseMap<const BasicBlock*, unsigned> BBNumPreds; /// behavior.
public: DenseMap<BasicBlock *, unsigned> BBNumbers;
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
AliasSetTracker *ast) /// Maps DomTreeNodes to their level in the dominator tree.
DenseMap<DomTreeNode *, unsigned> DomLevels;
/// Lazily compute the number of predecessors a block has.
DenseMap<const BasicBlock *, unsigned> BBNumPreds;
public:
PromoteMem2Reg(const std::vector<AllocaInst *> &A, DominatorTree &dt,
AliasSetTracker *ast)
: Allocas(A), DT(dt), DIB(0), AST(ast) {} : Allocas(A), DT(dt), DIB(0), AST(ast) {}
~PromoteMem2Reg() { ~PromoteMem2Reg() { delete DIB; }
delete DIB;
}
void run(); void run();
/// Return true if BB1 dominates BB2 using the DominatorTree. /// Return true if BB1 dominates BB2 using the DominatorTree.
bool dominates(BasicBlock *BB1, BasicBlock *BB2) const { bool dominates(BasicBlock *BB1, BasicBlock *BB2) const {
return DT.dominates(BB1, BB2); return DT.dominates(BB1, BB2);
} }
private: private:
void RemoveFromAllocasList(unsigned &AllocaIdx) { void RemoveFromAllocasList(unsigned &AllocaIdx) {
Allocas[AllocaIdx] = Allocas.back(); Allocas[AllocaIdx] = Allocas.back();
Allocas.pop_back(); Allocas.pop_back();
--AllocaIdx; --AllocaIdx;
} }
unsigned getNumPreds(const BasicBlock *BB) { unsigned getNumPreds(const BasicBlock *BB) {
unsigned &NP = BBNumPreds[BB]; unsigned &NP = BBNumPreds[BB];
if (NP == 0) if (NP == 0)
NP = std::distance(pred_begin(BB), pred_end(BB))+1; NP = std::distance(pred_begin(BB), pred_end(BB)) + 1;
return NP-1; return NP - 1;
} }
void DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum, void DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum,
AllocaInfo &Info); AllocaInfo &Info);
void ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info, void ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info,
const SmallPtrSet<BasicBlock*, 32> &DefBlocks, const SmallPtrSet<BasicBlock *, 32> &DefBlocks,
SmallPtrSet<BasicBlock*, 32> &LiveInBlocks); SmallPtrSet<BasicBlock *, 32> &LiveInBlocks);
void RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info, void RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI); LargeBlockInfo &LBI);
void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI); LargeBlockInfo &LBI);
void RenamePass(BasicBlock *BB, BasicBlock *Pred, void RenamePass(BasicBlock *BB, BasicBlock *Pred,
RenamePassData::ValVector &IncVals, RenamePassData::ValVector &IncVals,
std::vector<RenamePassData> &Worklist); std::vector<RenamePassData> &Worklist);
bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version); bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version);
}; };
struct AllocaInfo { struct AllocaInfo {
SmallVector<BasicBlock*, 32> DefiningBlocks; SmallVector<BasicBlock *, 32> DefiningBlocks;
SmallVector<BasicBlock*, 32> UsingBlocks; SmallVector<BasicBlock *, 32> UsingBlocks;
StoreInst *OnlyStore; StoreInst *OnlyStore;
BasicBlock *OnlyBlock; BasicBlock *OnlyBlock;
bool OnlyUsedInOneBlock; bool OnlyUsedInOneBlock;
Value *AllocaPointerVal; Value *AllocaPointerVal;
DbgDeclareInst *DbgDeclare; DbgDeclareInst *DbgDeclare;
void clear() { void clear() {
DefiningBlocks.clear(); DefiningBlocks.clear();
UsingBlocks.clear(); UsingBlocks.clear();
OnlyStore = 0; OnlyStore = 0;
OnlyBlock = 0; OnlyBlock = 0;
OnlyUsedInOneBlock = true; OnlyUsedInOneBlock = true;
AllocaPointerVal = 0; AllocaPointerVal = 0;
DbgDeclare = 0; DbgDeclare = 0;
} }
/// Scan the uses of the specified alloca, filling in the AllocaInfo used /// Scan the uses of the specified alloca, filling in the AllocaInfo used
/// by the rest of the pass to reason about the uses of this alloca. /// by the rest of the pass to reason about the uses of this alloca.
void AnalyzeAlloca(AllocaInst *AI) { void AnalyzeAlloca(AllocaInst *AI) {
clear(); clear();
// As we scan the uses of the alloca instruction, keep track of stores, // As we scan the uses of the alloca instruction, keep track of stores,
// and decide whether all of the loads and stores to the alloca are within // and decide whether all of the loads and stores to the alloca are within
// the same basic block. // the same basic block.
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
UI != E;) { UI != E;) {
Instruction *User = cast<Instruction>(*UI++); Instruction *User = cast<Instruction>(*UI++);
if (StoreInst *SI = dyn_cast<StoreInst>(User)) { if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Remember the basic blocks which define new values for the alloca // Remember the basic blocks which define new values for the alloca
DefiningBlocks.push_back(SI->getParent()); DefiningBlocks.push_back(SI->getParent());
AllocaPointerVal = SI->getOperand(0); AllocaPointerVal = SI->getOperand(0);
OnlyStore = SI; OnlyStore = SI;
} else { } else {
LoadInst *LI = cast<LoadInst>(User); LoadInst *LI = cast<LoadInst>(User);
// Otherwise it must be a load instruction, keep track of variable // Otherwise it must be a load instruction, keep track of variable
// reads. // reads.
UsingBlocks.push_back(LI->getParent()); UsingBlocks.push_back(LI->getParent());
AllocaPointerVal = LI; AllocaPointerVal = LI;
}
if (OnlyUsedInOneBlock) {
if (OnlyBlock == 0)
OnlyBlock = User->getParent();
else if (OnlyBlock != User->getParent())
OnlyUsedInOneBlock = false;
}
} }
DbgDeclare = FindAllocaDbgDeclare(AI); if (OnlyUsedInOneBlock) {
if (OnlyBlock == 0)
OnlyBlock = User->getParent();
else if (OnlyBlock != User->getParent())
OnlyUsedInOneBlock = false;
}
} }
};
typedef std::pair<DomTreeNode*, unsigned> DomTreeNodePair; DbgDeclare = FindAllocaDbgDeclare(AI);
}
};
struct DomTreeNodeCompare { typedef std::pair<DomTreeNode *, unsigned> DomTreeNodePair;
bool operator()(const DomTreeNodePair &LHS, const DomTreeNodePair &RHS) {
return LHS.second < RHS.second; struct DomTreeNodeCompare {
} bool operator()(const DomTreeNodePair &LHS, const DomTreeNodePair &RHS) {
}; return LHS.second < RHS.second;
} // end of anonymous namespace }
};
} // end of anonymous namespace
static void removeLifetimeIntrinsicUsers(AllocaInst *AI) { static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
// Knowing that this alloca is promotable, we know that it's safe to kill all // Knowing that this alloca is promotable, we know that it's safe to kill all
@@ -364,7 +363,8 @@ static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
void PromoteMem2Reg::run() { void PromoteMem2Reg::run() {
Function &F = *DT.getRoot()->getParent(); Function &F = *DT.getRoot()->getParent();
if (AST) PointerAllocaValues.resize(Allocas.size()); if (AST)
PointerAllocaValues.resize(Allocas.size());
AllocaDbgDeclares.resize(Allocas.size()); AllocaDbgDeclares.resize(Allocas.size());
AllocaInfo Info; AllocaInfo Info;
@@ -373,8 +373,7 @@ void PromoteMem2Reg::run() {
for (unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) { for (unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) {
AllocaInst *AI = Allocas[AllocaNum]; AllocaInst *AI = Allocas[AllocaNum];
assert(isAllocaPromotable(AI) && assert(isAllocaPromotable(AI) && "Cannot promote non-promotable alloca!");
"Cannot promote non-promotable alloca!");
assert(AI->getParent()->getParent() == &F && assert(AI->getParent()->getParent() == &F &&
"All allocas should be in the same function, which is same as DF!"); "All allocas should be in the same function, which is same as DF!");
@@ -382,7 +381,8 @@ void PromoteMem2Reg::run() {
if (AI->use_empty()) { if (AI->use_empty()) {
// If there are no uses of the alloca, just delete it now. // If there are no uses of the alloca, just delete it now.
if (AST) AST->deleteValue(AI); if (AST)
AST->deleteValue(AI);
AI->eraseFromParent(); AI->eraseFromParent();
// Remove the alloca from the Allocas list, since it has been processed // Remove the alloca from the Allocas list, since it has been processed
@@ -414,7 +414,8 @@ void PromoteMem2Reg::run() {
Info.OnlyStore->eraseFromParent(); Info.OnlyStore->eraseFromParent();
LBI.deleteValue(Info.OnlyStore); LBI.deleteValue(Info.OnlyStore);
if (AST) AST->deleteValue(AI); if (AST)
AST->deleteValue(AI);
AI->eraseFromParent(); AI->eraseFromParent();
LBI.deleteValue(AI); LBI.deleteValue(AI);
@@ -448,7 +449,8 @@ void PromoteMem2Reg::run() {
LBI.deleteValue(SI); LBI.deleteValue(SI);
} }
if (AST) AST->deleteValue(AI); if (AST)
AST->deleteValue(AI);
AI->eraseFromParent(); AI->eraseFromParent();
LBI.deleteValue(AI); LBI.deleteValue(AI);
@@ -466,7 +468,7 @@ void PromoteMem2Reg::run() {
// If we haven't computed dominator tree levels, do so now. // If we haven't computed dominator tree levels, do so now.
if (DomLevels.empty()) { if (DomLevels.empty()) {
SmallVector<DomTreeNode*, 32> Worklist; SmallVector<DomTreeNode *, 32> Worklist;
DomTreeNode *Root = DT.getRootNode(); DomTreeNode *Root = DT.getRootNode();
DomLevels[Root] = 0; DomLevels[Root] = 0;
@@ -497,7 +499,8 @@ void PromoteMem2Reg::run() {
PointerAllocaValues[AllocaNum] = Info.AllocaPointerVal; PointerAllocaValues[AllocaNum] = Info.AllocaPointerVal;
// Remember the dbg.declare intrinsic describing this alloca, if any. // Remember the dbg.declare intrinsic describing this alloca, if any.
if (Info.DbgDeclare) AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare; if (Info.DbgDeclare)
AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
// Keep the reverse mapping of the 'Allocas' array for the rename pass. // Keep the reverse mapping of the 'Allocas' array for the rename pass.
AllocaLookup[Allocas[AllocaNum]] = AllocaNum; AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
@@ -514,7 +517,6 @@ void PromoteMem2Reg::run() {
LBI.clear(); LBI.clear();
// Set the incoming values for the basic block to be null values for all of // Set the incoming values for the basic block to be null values for all of
// the alloca's. We do this in case there is a load of a value that has not // the alloca's. We do this in case there is a load of a value that has not
// been stored yet. In this case, it will get this null value. // been stored yet. In this case, it will get this null value.
@@ -548,7 +550,8 @@ void PromoteMem2Reg::run() {
// tree. Just delete the users now. // tree. Just delete the users now.
if (!A->use_empty()) if (!A->use_empty())
A->replaceAllUsesWith(UndefValue::get(A->getType())); A->replaceAllUsesWith(UndefValue::get(A->getType()));
if (AST) AST->deleteValue(A); if (AST)
AST->deleteValue(A);
A->eraseFromParent(); A->eraseFromParent();
} }
@@ -569,8 +572,10 @@ void PromoteMem2Reg::run() {
// simplify and RAUW them as we go. If it was not, we could add uses to // simplify and RAUW them as we go. If it was not, we could add uses to
// the values we replace with in a non deterministic order, thus creating // the values we replace with in a non deterministic order, thus creating
// non deterministic def->use chains. // non deterministic def->use chains.
for (DenseMap<std::pair<unsigned, unsigned>, PHINode*>::iterator I = for (DenseMap<std::pair<unsigned, unsigned>, PHINode *>::iterator
NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E;) { I = NewPhiNodes.begin(),
E = NewPhiNodes.end();
I != E;) {
PHINode *PN = I->second; PHINode *PN = I->second;
// If this PHI node merges one value and/or undefs, get the value. // If this PHI node merges one value and/or undefs, get the value.
@@ -593,8 +598,10 @@ void PromoteMem2Reg::run() {
// have incoming values for all predecessors. Loop over all PHI nodes we have // have incoming values for all predecessors. Loop over all PHI nodes we have
// created, inserting undef values if they are missing any incoming values. // created, inserting undef values if they are missing any incoming values.
// //
for (DenseMap<std::pair<unsigned, unsigned>, PHINode*>::iterator I = for (DenseMap<std::pair<unsigned, unsigned>, PHINode *>::iterator
NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E; ++I) { I = NewPhiNodes.begin(),
E = NewPhiNodes.end();
I != E; ++I) {
// We want to do this once per basic block. As such, only process a block // We want to do this once per basic block. As such, only process a block
// when we find the PHI that is the first entry in the block. // when we find the PHI that is the first entry in the block.
PHINode *SomePHI = I->second; PHINode *SomePHI = I->second;
@@ -609,7 +616,7 @@ void PromoteMem2Reg::run() {
continue; continue;
// Get the preds for BB. // Get the preds for BB.
SmallVector<BasicBlock*, 16> Preds(pred_begin(BB), pred_end(BB)); SmallVector<BasicBlock *, 16> Preds(pred_begin(BB), pred_end(BB));
// Ok, now we know that all of the PHI nodes are missing entries for some // Ok, now we know that all of the PHI nodes are missing entries for some
// basic blocks. Start by sorting the incoming predecessors for efficient // basic blocks. Start by sorting the incoming predecessors for efficient
@@ -620,10 +627,9 @@ void PromoteMem2Reg::run() {
// them from the Preds list. // them from the Preds list.
for (unsigned i = 0, e = SomePHI->getNumIncomingValues(); i != e; ++i) { for (unsigned i = 0, e = SomePHI->getNumIncomingValues(); i != e; ++i) {
// Do a log(n) search of the Preds list for the entry we want. // Do a log(n) search of the Preds list for the entry we want.
SmallVectorImpl<BasicBlock *>::iterator EntIt = SmallVectorImpl<BasicBlock *>::iterator EntIt = std::lower_bound(
std::lower_bound(Preds.begin(), Preds.end(), Preds.begin(), Preds.end(), SomePHI->getIncomingBlock(i));
SomePHI->getIncomingBlock(i)); assert(EntIt != Preds.end() && *EntIt == SomePHI->getIncomingBlock(i) &&
assert(EntIt != Preds.end() && *EntIt == SomePHI->getIncomingBlock(i)&&
"PHI node has entry for a block which is not a predecessor!"); "PHI node has entry for a block which is not a predecessor!");
// Remove the entry // Remove the entry
@@ -647,35 +653,36 @@ void PromoteMem2Reg::run() {
NewPhiNodes.clear(); NewPhiNodes.clear();
} }
/// \brief Determine which blocks the value is live in. /// \brief Determine which blocks the value is live in.
/// ///
/// These are blocks which lead to uses. Knowing this allows us to avoid /// These are blocks which lead to uses. Knowing this allows us to avoid
/// inserting PHI nodes into blocks which don't lead to uses (thus, the /// inserting PHI nodes into blocks which don't lead to uses (thus, the
/// inserted phi nodes would be dead). /// inserted phi nodes would be dead).
void PromoteMem2Reg:: void PromoteMem2Reg::ComputeLiveInBlocks(
ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info, AllocaInst *AI, AllocaInfo &Info,
const SmallPtrSet<BasicBlock*, 32> &DefBlocks, const SmallPtrSet<BasicBlock *, 32> &DefBlocks,
SmallPtrSet<BasicBlock*, 32> &LiveInBlocks) { SmallPtrSet<BasicBlock *, 32> &LiveInBlocks) {
// To determine liveness, we must iterate through the predecessors of blocks // To determine liveness, we must iterate through the predecessors of blocks
// where the def is live. Blocks are added to the worklist if we need to // where the def is live. Blocks are added to the worklist if we need to
// check their predecessors. Start with all the using blocks. // check their predecessors. Start with all the using blocks.
SmallVector<BasicBlock*, 64> LiveInBlockWorklist(Info.UsingBlocks.begin(), SmallVector<BasicBlock *, 64> LiveInBlockWorklist(Info.UsingBlocks.begin(),
Info.UsingBlocks.end()); Info.UsingBlocks.end());
// If any of the using blocks is also a definition block, check to see if the // If any of the using blocks is also a definition block, check to see if the
// definition occurs before or after the use. If it happens before the use, // definition occurs before or after the use. If it happens before the use,
// the value isn't really live-in. // the value isn't really live-in.
for (unsigned i = 0, e = LiveInBlockWorklist.size(); i != e; ++i) { for (unsigned i = 0, e = LiveInBlockWorklist.size(); i != e; ++i) {
BasicBlock *BB = LiveInBlockWorklist[i]; BasicBlock *BB = LiveInBlockWorklist[i];
if (!DefBlocks.count(BB)) continue; if (!DefBlocks.count(BB))
continue;
// Okay, this is a block that both uses and defines the value. If the first // Okay, this is a block that both uses and defines the value. If the first
// reference to the alloca is a def (store), then we know it isn't live-in. // reference to the alloca is a def (store), then we know it isn't live-in.
for (BasicBlock::iterator I = BB->begin(); ; ++I) { for (BasicBlock::iterator I = BB->begin();; ++I) {
if (StoreInst *SI = dyn_cast<StoreInst>(I)) { if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
if (SI->getOperand(1) != AI) continue; if (SI->getOperand(1) != AI)
continue;
// We found a store to the alloca before a load. The alloca is not // We found a store to the alloca before a load. The alloca is not
// actually live-in here. // actually live-in here.
@@ -686,7 +693,8 @@ ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info,
} }
if (LoadInst *LI = dyn_cast<LoadInst>(I)) { if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
if (LI->getOperand(0) != AI) continue; if (LI->getOperand(0) != AI)
continue;
// Okay, we found a load before a store to the alloca. It is actually // Okay, we found a load before a store to the alloca. It is actually
// live into this block. // live into this block.
@@ -728,29 +736,31 @@ ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info,
void PromoteMem2Reg::DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum, void PromoteMem2Reg::DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum,
AllocaInfo &Info) { AllocaInfo &Info) {
// Unique the set of defining blocks for efficient lookup. // Unique the set of defining blocks for efficient lookup.
SmallPtrSet<BasicBlock*, 32> DefBlocks; SmallPtrSet<BasicBlock *, 32> DefBlocks;
DefBlocks.insert(Info.DefiningBlocks.begin(), Info.DefiningBlocks.end()); DefBlocks.insert(Info.DefiningBlocks.begin(), Info.DefiningBlocks.end());
// Determine which blocks the value is live in. These are blocks which lead // Determine which blocks the value is live in. These are blocks which lead
// to uses. // to uses.
SmallPtrSet<BasicBlock*, 32> LiveInBlocks; SmallPtrSet<BasicBlock *, 32> LiveInBlocks;
ComputeLiveInBlocks(AI, Info, DefBlocks, LiveInBlocks); ComputeLiveInBlocks(AI, Info, DefBlocks, LiveInBlocks);
// Use a priority queue keyed on dominator tree level so that inserted nodes // Use a priority queue keyed on dominator tree level so that inserted nodes
// are handled from the bottom of the dominator tree upwards. // are handled from the bottom of the dominator tree upwards.
typedef std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>, typedef std::priority_queue<DomTreeNodePair,
SmallVector<DomTreeNodePair, 32>,
DomTreeNodeCompare> IDFPriorityQueue; DomTreeNodeCompare> IDFPriorityQueue;
IDFPriorityQueue PQ; IDFPriorityQueue PQ;
for (SmallPtrSet<BasicBlock*, 32>::const_iterator I = DefBlocks.begin(), for (SmallPtrSet<BasicBlock *, 32>::const_iterator I = DefBlocks.begin(),
E = DefBlocks.end(); I != E; ++I) { E = DefBlocks.end();
I != E; ++I) {
if (DomTreeNode *Node = DT.getNode(*I)) if (DomTreeNode *Node = DT.getNode(*I))
PQ.push(std::make_pair(Node, DomLevels[Node])); PQ.push(std::make_pair(Node, DomLevels[Node]));
} }
SmallVector<std::pair<unsigned, BasicBlock*>, 32> DFBlocks; SmallVector<std::pair<unsigned, BasicBlock *>, 32> DFBlocks;
SmallPtrSet<DomTreeNode*, 32> Visited; SmallPtrSet<DomTreeNode *, 32> Visited;
SmallVector<DomTreeNode*, 32> Worklist; SmallVector<DomTreeNode *, 32> Worklist;
while (!PQ.empty()) { while (!PQ.empty()) {
DomTreeNodePair RootPair = PQ.top(); DomTreeNodePair RootPair = PQ.top();
PQ.pop(); PQ.pop();
@@ -812,8 +822,7 @@ void PromoteMem2Reg::DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum,
/// If there is only a single store to this value, replace any loads of it that /// If there is only a single store to this value, replace any loads of it that
/// are directly dominated by the definition with the value stored. /// are directly dominated by the definition with the value stored.
void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI, void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
AllocaInfo &Info,
LargeBlockInfo &LBI) { LargeBlockInfo &LBI) {
StoreInst *OnlyStore = Info.OnlyStore; StoreInst *OnlyStore = Info.OnlyStore;
bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0)); bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0));
@@ -823,7 +832,7 @@ void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI,
// Clear out UsingBlocks. We will reconstruct it here if needed. // Clear out UsingBlocks. We will reconstruct it here if needed.
Info.UsingBlocks.clear(); Info.UsingBlocks.clear();
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E; ) { for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) {
Instruction *UserInst = cast<Instruction>(*UI++); Instruction *UserInst = cast<Instruction>(*UI++);
if (!isa<LoadInst>(UserInst)) { if (!isa<LoadInst>(UserInst)) {
assert(UserInst == OnlyStore && "Should only have load/stores"); assert(UserInst == OnlyStore && "Should only have load/stores");
@@ -835,7 +844,7 @@ void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI,
// only value stored to the alloca. We can do this if the value is // only value stored to the alloca. We can do this if the value is
// dominated by the store. If not, we use the rest of the mem2reg machinery // dominated by the store. If not, we use the rest of the mem2reg machinery
// to insert the phi nodes as needed. // to insert the phi nodes as needed.
if (!StoringGlobalVal) { // Non-instructions are always dominated. if (!StoringGlobalVal) { // Non-instructions are always dominated.
if (LI->getParent() == StoreBB) { if (LI->getParent() == StoreBB) {
// If we have a use that is in the same block as the store, compare the // If we have a use that is in the same block as the store, compare the
// indices of the two instructions to see which one came first. If the // indices of the two instructions to see which one came first. If the
@@ -874,15 +883,13 @@ void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI,
} }
namespace { namespace {
/// This is a helper predicate used to search by the first element of a pair. /// This is a helper predicate used to search by the first element of a pair.
struct StoreIndexSearchPredicate { struct StoreIndexSearchPredicate {
bool operator()(const std::pair<unsigned, StoreInst*> &LHS, bool operator()(const std::pair<unsigned, StoreInst *> &LHS,
const std::pair<unsigned, StoreInst*> &RHS) { const std::pair<unsigned, StoreInst *> &RHS) {
return LHS.first < RHS.first; return LHS.first < RHS.first;
} }
}; };
} }
/// Many allocas are only used within a single basic block. If this is the /// Many allocas are only used within a single basic block. If this is the
@@ -909,11 +916,11 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
Info.UsingBlocks.clear(); Info.UsingBlocks.clear();
// Walk the use-def list of the alloca, getting the locations of all stores. // Walk the use-def list of the alloca, getting the locations of all stores.
typedef SmallVector<std::pair<unsigned, StoreInst*>, 64> StoresByIndexTy; typedef SmallVector<std::pair<unsigned, StoreInst *>, 64> StoresByIndexTy;
StoresByIndexTy StoresByIndex; StoresByIndexTy StoresByIndex;
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;
UI != E; ++UI) ++UI)
if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) if (StoreInst *SI = dyn_cast<StoreInst>(*UI))
StoresByIndex.push_back(std::make_pair(LBI.getInstructionIndex(SI), SI)); StoresByIndex.push_back(std::make_pair(LBI.getInstructionIndex(SI), SI));
@@ -938,15 +945,16 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
// store above them, if any. // store above them, if any.
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) { for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) {
LoadInst *LI = dyn_cast<LoadInst>(*UI++); LoadInst *LI = dyn_cast<LoadInst>(*UI++);
if (!LI) continue; if (!LI)
continue;
unsigned LoadIdx = LBI.getInstructionIndex(LI); unsigned LoadIdx = LBI.getInstructionIndex(LI);
// Find the nearest store that has a lower than this load. // Find the nearest store that has a lower than this load.
StoresByIndexTy::iterator I = StoresByIndexTy::iterator I = std::lower_bound(
std::lower_bound(StoresByIndex.begin(), StoresByIndex.end(), StoresByIndex.begin(), StoresByIndex.end(),
std::pair<unsigned, StoreInst*>(LoadIdx, static_cast<StoreInst*>(0)), std::pair<unsigned, StoreInst *>(LoadIdx, static_cast<StoreInst *>(0)),
StoreIndexSearchPredicate()); StoreIndexSearchPredicate());
// If there is no store before this load, then we can't promote this load. // If there is no store before this load, then we can't promote this load.
if (I == StoresByIndex.begin()) { if (I == StoresByIndex.begin()) {
@@ -974,7 +982,8 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo,
PHINode *&PN = NewPhiNodes[std::make_pair(BBNumbers[BB], AllocaNo)]; PHINode *&PN = NewPhiNodes[std::make_pair(BBNumbers[BB], AllocaNo)];
// If the BB already has a phi node added for the i'th alloca then we're done! // If the BB already has a phi node added for the i'th alloca then we're done!
if (PN) return false; if (PN)
return false;
// Create a PhiNode using the dereferenced type... and add the phi-node to the // Create a PhiNode using the dereferenced type... and add the phi-node to the
// BasicBlock. // BasicBlock.
@@ -1034,7 +1043,8 @@ NextIteration:
// Get the next phi node. // Get the next phi node.
++PNI; ++PNI;
APN = dyn_cast<PHINode>(PNI); APN = dyn_cast<PHINode>(PNI);
if (APN == 0) break; if (APN == 0)
break;
// Verify that it is missing entries. If not, it is not being inserted // Verify that it is missing entries. If not, it is not being inserted
// by this mem2reg invocation so we want to ignore it. // by this mem2reg invocation so we want to ignore it.
@@ -1043,17 +1053,20 @@ NextIteration:
} }
// Don't revisit blocks. // Don't revisit blocks.
if (!Visited.insert(BB)) return; if (!Visited.insert(BB))
return;
for (BasicBlock::iterator II = BB->begin(); !isa<TerminatorInst>(II); ) { for (BasicBlock::iterator II = BB->begin(); !isa<TerminatorInst>(II);) {
Instruction *I = II++; // get the instruction, increment iterator Instruction *I = II++; // get the instruction, increment iterator
if (LoadInst *LI = dyn_cast<LoadInst>(I)) { if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
AllocaInst *Src = dyn_cast<AllocaInst>(LI->getPointerOperand()); AllocaInst *Src = dyn_cast<AllocaInst>(LI->getPointerOperand());
if (!Src) continue; if (!Src)
continue;
DenseMap<AllocaInst*, unsigned>::iterator AI = AllocaLookup.find(Src); DenseMap<AllocaInst *, unsigned>::iterator AI = AllocaLookup.find(Src);
if (AI == AllocaLookup.end()) continue; if (AI == AllocaLookup.end())
continue;
Value *V = IncomingVals[AI->second]; Value *V = IncomingVals[AI->second];
@@ -1066,7 +1079,8 @@ NextIteration:
// Delete this instruction and mark the name as the current holder of the // Delete this instruction and mark the name as the current holder of the
// value // value
AllocaInst *Dest = dyn_cast<AllocaInst>(SI->getPointerOperand()); AllocaInst *Dest = dyn_cast<AllocaInst>(SI->getPointerOperand());
if (!Dest) continue; if (!Dest)
continue;
DenseMap<AllocaInst *, unsigned>::iterator ai = AllocaLookup.find(Dest); DenseMap<AllocaInst *, unsigned>::iterator ai = AllocaLookup.find(Dest);
if (ai == AllocaLookup.end()) if (ai == AllocaLookup.end())
@@ -1086,10 +1100,11 @@ NextIteration:
// 'Recurse' to our successors. // 'Recurse' to our successors.
succ_iterator I = succ_begin(BB), E = succ_end(BB); succ_iterator I = succ_begin(BB), E = succ_end(BB);
if (I == E) return; if (I == E)
return;
// Keep track of the successors so we don't visit the same successor twice // Keep track of the successors so we don't visit the same successor twice
SmallPtrSet<BasicBlock*, 8> VisitedSuccs; SmallPtrSet<BasicBlock *, 8> VisitedSuccs;
// Handle the first successor without using the worklist. // Handle the first successor without using the worklist.
VisitedSuccs.insert(*I); VisitedSuccs.insert(*I);
@@ -1104,10 +1119,11 @@ NextIteration:
goto NextIteration; goto NextIteration;
} }
void llvm::PromoteMemToReg(const std::vector<AllocaInst*> &Allocas, void llvm::PromoteMemToReg(const std::vector<AllocaInst *> &Allocas,
DominatorTree &DT, AliasSetTracker *AST) { DominatorTree &DT, AliasSetTracker *AST) {
// If there is nothing to do, bail out... // If there is nothing to do, bail out...
if (Allocas.empty()) return; if (Allocas.empty())
return;
PromoteMem2Reg(Allocas, DT, AST).run(); PromoteMem2Reg(Allocas, DT, AST).run();
} }