PromoteMemoryToRegister.cpp [plain text]
#define DEBUG_TYPE "mem2reg"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Metadata.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CFG.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumLocalPromoted, "Number of alloca's promoted within one block");
STATISTIC(NumSingleStore, "Number of alloca's promoted with a single store");
STATISTIC(NumDeadAlloca, "Number of dead alloca's removed");
STATISTIC(NumPHIInsert, "Number of PHI nodes inserted");
namespace llvm {
template<>
struct DenseMapInfo<std::pair<BasicBlock*, unsigned> > {
typedef std::pair<BasicBlock*, unsigned> EltTy;
static inline EltTy getEmptyKey() {
return EltTy(reinterpret_cast<BasicBlock*>(-1), ~0U);
}
static inline EltTy getTombstoneKey() {
return EltTy(reinterpret_cast<BasicBlock*>(-2), 0U);
}
static unsigned getHashValue(const std::pair<BasicBlock*, unsigned> &Val) {
return DenseMapInfo<void*>::getHashValue(Val.first) + Val.second*2;
}
static bool isEqual(const EltTy &LHS, const EltTy &RHS) {
return LHS == RHS;
}
};
}
bool llvm::isAllocaPromotable(const AllocaInst *AI) {
for (Value::const_use_iterator UI = AI->use_begin(), UE = AI->use_end();
UI != UE; ++UI) { const User *U = *UI;
if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
if (LI->isVolatile())
return false;
} else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->getOperand(0) == AI)
return false; if (SI->isVolatile())
return false;
} else {
return false;
}
}
return true;
}
static DbgDeclareInst *FindAllocaDbgDeclare(Value *V) {
if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), &V, 1))
for (Value::use_iterator UI = DebugNode->use_begin(),
E = DebugNode->use_end(); UI != E; ++UI)
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(*UI))
return DDI;
return 0;
}
namespace {
struct AllocaInfo;
class RenamePassData {
public:
typedef std::vector<Value *> ValVector;
RenamePassData() : BB(NULL), Pred(NULL), Values() {}
RenamePassData(BasicBlock *B, BasicBlock *P,
const ValVector &V) : BB(B), Pred(P), Values(V) {}
BasicBlock *BB;
BasicBlock *Pred;
ValVector Values;
void swap(RenamePassData &RHS) {
std::swap(BB, RHS.BB);
std::swap(Pred, RHS.Pred);
Values.swap(RHS.Values);
}
};
class LargeBlockInfo {
DenseMap<const Instruction *, unsigned> InstNumbers;
public:
static bool isInterestingInstruction(const Instruction *I) {
return (isa<LoadInst>(I) && isa<AllocaInst>(I->getOperand(0))) ||
(isa<StoreInst>(I) && isa<AllocaInst>(I->getOperand(1)));
}
unsigned getInstructionIndex(const Instruction *I) {
assert(isInterestingInstruction(I) &&
"Not a load/store to/from an alloca?");
DenseMap<const Instruction *, unsigned>::iterator It = InstNumbers.find(I);
if (It != InstNumbers.end()) return It->second;
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;
}
void deleteValue(const Instruction *I) {
InstNumbers.erase(I);
}
void clear() {
InstNumbers.clear();
}
};
struct PromoteMem2Reg {
std::vector<AllocaInst*> Allocas;
DominatorTree &DT;
DominanceFrontier &DF;
DIFactory *DIF;
AliasSetTracker *AST;
std::map<AllocaInst*, unsigned> AllocaLookup;
DenseMap<std::pair<BasicBlock*, unsigned>, PHINode*> NewPhiNodes;
DenseMap<PHINode*, unsigned> PhiToAllocaMap;
std::vector<Value*> PointerAllocaValues;
SmallVector<DbgDeclareInst*, 8> AllocaDbgDeclares;
SmallPtrSet<BasicBlock*, 16> Visited;
DenseMap<BasicBlock*, unsigned> BBNumbers;
DenseMap<const BasicBlock*, unsigned> BBNumPreds;
public:
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
DominanceFrontier &df, AliasSetTracker *ast)
: Allocas(A), DT(dt), DF(df), DIF(0), AST(ast) {}
~PromoteMem2Reg() {
delete DIF;
}
void run();
bool dominates(BasicBlock *BB1, BasicBlock *BB2) const {
return DT.dominates(BB1, BB2);
}
private:
void RemoveFromAllocasList(unsigned &AllocaIdx) {
Allocas[AllocaIdx] = Allocas.back();
Allocas.pop_back();
--AllocaIdx;
}
unsigned getNumPreds(const BasicBlock *BB) {
unsigned &NP = BBNumPreds[BB];
if (NP == 0)
NP = std::distance(pred_begin(BB), pred_end(BB))+1;
return NP-1;
}
void DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum,
AllocaInfo &Info);
void ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info,
const SmallPtrSet<BasicBlock*, 32> &DefBlocks,
SmallPtrSet<BasicBlock*, 32> &LiveInBlocks);
void RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI);
void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI);
void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst *SI);
void RenamePass(BasicBlock *BB, BasicBlock *Pred,
RenamePassData::ValVector &IncVals,
std::vector<RenamePassData> &Worklist);
bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version,
SmallPtrSet<PHINode*, 16> &InsertedPHINodes);
};
struct AllocaInfo {
std::vector<BasicBlock*> DefiningBlocks;
std::vector<BasicBlock*> UsingBlocks;
StoreInst *OnlyStore;
BasicBlock *OnlyBlock;
bool OnlyUsedInOneBlock;
Value *AllocaPointerVal;
DbgDeclareInst *DbgDeclare;
void clear() {
DefiningBlocks.clear();
UsingBlocks.clear();
OnlyStore = 0;
OnlyBlock = 0;
OnlyUsedInOneBlock = true;
AllocaPointerVal = 0;
DbgDeclare = 0;
}
void AnalyzeAlloca(AllocaInst *AI) {
clear();
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
UI != E;) {
Instruction *User = cast<Instruction>(*UI++);
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
DefiningBlocks.push_back(SI->getParent());
AllocaPointerVal = SI->getOperand(0);
OnlyStore = SI;
} else {
LoadInst *LI = cast<LoadInst>(User);
UsingBlocks.push_back(LI->getParent());
AllocaPointerVal = LI;
}
if (OnlyUsedInOneBlock) {
if (OnlyBlock == 0)
OnlyBlock = User->getParent();
else if (OnlyBlock != User->getParent())
OnlyUsedInOneBlock = false;
}
}
DbgDeclare = FindAllocaDbgDeclare(AI);
}
};
}
void PromoteMem2Reg::run() {
Function &F = *DF.getRoot()->getParent();
if (AST) PointerAllocaValues.resize(Allocas.size());
AllocaDbgDeclares.resize(Allocas.size());
AllocaInfo Info;
LargeBlockInfo LBI;
for (unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) {
AllocaInst *AI = Allocas[AllocaNum];
assert(isAllocaPromotable(AI) &&
"Cannot promote non-promotable alloca!");
assert(AI->getParent()->getParent() == &F &&
"All allocas should be in the same function, which is same as DF!");
if (AI->use_empty()) {
if (AST) AST->deleteValue(AI);
AI->eraseFromParent();
RemoveFromAllocasList(AllocaNum);
++NumDeadAlloca;
continue;
}
Info.AnalyzeAlloca(AI);
if (Info.DefiningBlocks.size() == 1) {
RewriteSingleStoreAlloca(AI, Info, LBI);
if (Info.UsingBlocks.empty()) {
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore);
DDI->eraseFromParent();
}
Info.OnlyStore->eraseFromParent();
LBI.deleteValue(Info.OnlyStore);
if (AST) AST->deleteValue(AI);
AI->eraseFromParent();
LBI.deleteValue(AI);
RemoveFromAllocasList(AllocaNum);
++NumSingleStore;
continue;
}
}
if (Info.OnlyUsedInOneBlock) {
PromoteSingleBlockAlloca(AI, Info, LBI);
if (Info.UsingBlocks.empty()) {
while (!AI->use_empty()) {
StoreInst *SI = cast<StoreInst>(AI->use_back());
if (DbgDeclareInst *DDI = Info.DbgDeclare)
ConvertDebugDeclareToDebugValue(DDI, SI);
SI->eraseFromParent();
LBI.deleteValue(SI);
}
if (AST) AST->deleteValue(AI);
AI->eraseFromParent();
LBI.deleteValue(AI);
RemoveFromAllocasList(AllocaNum);
if (DbgDeclareInst *DDI = Info.DbgDeclare)
DDI->eraseFromParent();
++NumLocalPromoted;
continue;
}
}
if (BBNumbers.empty()) {
unsigned ID = 0;
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
BBNumbers[I] = ID++;
}
if (AST)
PointerAllocaValues[AllocaNum] = Info.AllocaPointerVal;
if (Info.DbgDeclare) AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
DetermineInsertionPoint(AI, AllocaNum, Info);
}
if (Allocas.empty())
return;
LBI.clear();
RenamePassData::ValVector Values(Allocas.size());
for (unsigned i = 0, e = Allocas.size(); i != e; ++i)
Values[i] = UndefValue::get(Allocas[i]->getAllocatedType());
std::vector<RenamePassData> RenamePassWorkList;
RenamePassWorkList.push_back(RenamePassData(F.begin(), 0, Values));
do {
RenamePassData RPD;
RPD.swap(RenamePassWorkList.back());
RenamePassWorkList.pop_back();
RenamePass(RPD.BB, RPD.Pred, RPD.Values, RenamePassWorkList);
} while (!RenamePassWorkList.empty());
Visited.clear();
for (unsigned i = 0, e = Allocas.size(); i != e; ++i) {
Instruction *A = Allocas[i];
if (!A->use_empty())
A->replaceAllUsesWith(UndefValue::get(A->getType()));
if (AST) AST->deleteValue(A);
A->eraseFromParent();
}
for (unsigned i = 0, e = AllocaDbgDeclares.size(); i != e; ++i)
if (DbgDeclareInst *DDI = AllocaDbgDeclares[i])
DDI->eraseFromParent();
bool EliminatedAPHI = true;
while (EliminatedAPHI) {
EliminatedAPHI = false;
for (DenseMap<std::pair<BasicBlock*, unsigned>, PHINode*>::iterator I =
NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E;) {
PHINode *PN = I->second;
if (Value *V = PN->hasConstantValue(&DT)) {
if (AST && PN->getType()->isPointerTy())
AST->deleteValue(PN);
PN->replaceAllUsesWith(V);
PN->eraseFromParent();
NewPhiNodes.erase(I++);
EliminatedAPHI = true;
continue;
}
++I;
}
}
for (DenseMap<std::pair<BasicBlock*, unsigned>, PHINode*>::iterator I =
NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E; ++I) {
PHINode *SomePHI = I->second;
BasicBlock *BB = SomePHI->getParent();
if (&BB->front() != SomePHI)
continue;
if (SomePHI->getNumIncomingValues() == getNumPreds(BB))
continue;
SmallVector<BasicBlock*, 16> Preds(pred_begin(BB), pred_end(BB));
std::sort(Preds.begin(), Preds.end());
for (unsigned i = 0, e = SomePHI->getNumIncomingValues(); i != e; ++i) {
SmallVector<BasicBlock*, 16>::iterator EntIt =
std::lower_bound(Preds.begin(), Preds.end(),
SomePHI->getIncomingBlock(i));
assert(EntIt != Preds.end() && *EntIt == SomePHI->getIncomingBlock(i)&&
"PHI node has entry for a block which is not a predecessor!");
Preds.erase(EntIt);
}
unsigned NumBadPreds = SomePHI->getNumIncomingValues();
BasicBlock::iterator BBI = BB->begin();
while ((SomePHI = dyn_cast<PHINode>(BBI++)) &&
SomePHI->getNumIncomingValues() == NumBadPreds) {
Value *UndefVal = UndefValue::get(SomePHI->getType());
for (unsigned pred = 0, e = Preds.size(); pred != e; ++pred)
SomePHI->addIncoming(UndefVal, Preds[pred]);
}
}
NewPhiNodes.clear();
}
void PromoteMem2Reg::
ComputeLiveInBlocks(AllocaInst *AI, AllocaInfo &Info,
const SmallPtrSet<BasicBlock*, 32> &DefBlocks,
SmallPtrSet<BasicBlock*, 32> &LiveInBlocks) {
SmallVector<BasicBlock*, 64> LiveInBlockWorklist(Info.UsingBlocks.begin(),
Info.UsingBlocks.end());
for (unsigned i = 0, e = LiveInBlockWorklist.size(); i != e; ++i) {
BasicBlock *BB = LiveInBlockWorklist[i];
if (!DefBlocks.count(BB)) continue;
for (BasicBlock::iterator I = BB->begin(); ; ++I) {
if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
if (SI->getOperand(1) != AI) continue;
LiveInBlockWorklist[i] = LiveInBlockWorklist.back();
LiveInBlockWorklist.pop_back();
--i, --e;
break;
}
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
if (LI->getOperand(0) != AI) continue;
break;
}
}
}
while (!LiveInBlockWorklist.empty()) {
BasicBlock *BB = LiveInBlockWorklist.pop_back_val();
if (!LiveInBlocks.insert(BB))
continue;
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
BasicBlock *P = *PI;
if (DefBlocks.count(P))
continue;
LiveInBlockWorklist.push_back(P);
}
}
}
void PromoteMem2Reg::DetermineInsertionPoint(AllocaInst *AI, unsigned AllocaNum,
AllocaInfo &Info) {
SmallPtrSet<BasicBlock*, 32> DefBlocks;
DefBlocks.insert(Info.DefiningBlocks.begin(), Info.DefiningBlocks.end());
SmallPtrSet<BasicBlock*, 32> LiveInBlocks;
ComputeLiveInBlocks(AI, Info, DefBlocks, LiveInBlocks);
unsigned CurrentVersion = 0;
SmallPtrSet<PHINode*, 16> InsertedPHINodes;
std::vector<std::pair<unsigned, BasicBlock*> > DFBlocks;
while (!Info.DefiningBlocks.empty()) {
BasicBlock *BB = Info.DefiningBlocks.back();
Info.DefiningBlocks.pop_back();
DominanceFrontier::const_iterator it = DF.find(BB);
if (it == DF.end()) continue;
const DominanceFrontier::DomSetType &S = it->second;
for (DominanceFrontier::DomSetType::const_iterator P = S.begin(),
PE = S.end(); P != PE; ++P) {
if (!LiveInBlocks.count(*P))
continue;
DFBlocks.push_back(std::make_pair(BBNumbers[*P], *P));
}
if (DFBlocks.size() > 1)
std::sort(DFBlocks.begin(), DFBlocks.end());
for (unsigned i = 0, e = DFBlocks.size(); i != e; ++i) {
BasicBlock *BB = DFBlocks[i].second;
if (QueuePhiNode(BB, AllocaNum, CurrentVersion, InsertedPHINodes))
Info.DefiningBlocks.push_back(BB);
}
DFBlocks.clear();
}
}
void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI,
AllocaInfo &Info,
LargeBlockInfo &LBI) {
StoreInst *OnlyStore = Info.OnlyStore;
bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0));
BasicBlock *StoreBB = OnlyStore->getParent();
int StoreIndex = -1;
Info.UsingBlocks.clear();
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E; ) {
Instruction *UserInst = cast<Instruction>(*UI++);
if (!isa<LoadInst>(UserInst)) {
assert(UserInst == OnlyStore && "Should only have load/stores");
continue;
}
LoadInst *LI = cast<LoadInst>(UserInst);
if (!StoringGlobalVal) { if (LI->getParent() == StoreBB) {
if (StoreIndex == -1)
StoreIndex = LBI.getInstructionIndex(OnlyStore);
if (unsigned(StoreIndex) > LBI.getInstructionIndex(LI)) {
Info.UsingBlocks.push_back(StoreBB);
continue;
}
} else if (LI->getParent() != StoreBB &&
!dominates(StoreBB, LI->getParent())) {
Info.UsingBlocks.push_back(LI->getParent());
continue;
}
}
Value *ReplVal = OnlyStore->getOperand(0);
if (ReplVal == LI)
ReplVal = UndefValue::get(LI->getType());
LI->replaceAllUsesWith(ReplVal);
if (AST && LI->getType()->isPointerTy())
AST->deleteValue(LI);
LI->eraseFromParent();
LBI.deleteValue(LI);
}
}
namespace {
struct StoreIndexSearchPredicate {
bool operator()(const std::pair<unsigned, StoreInst*> &LHS,
const std::pair<unsigned, StoreInst*> &RHS) {
return LHS.first < RHS.first;
}
};
}
void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info,
LargeBlockInfo &LBI) {
Info.UsingBlocks.clear();
typedef SmallVector<std::pair<unsigned, StoreInst*>, 64> StoresByIndexTy;
StoresByIndexTy StoresByIndex;
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
UI != E; ++UI)
if (StoreInst *SI = dyn_cast<StoreInst>(*UI))
StoresByIndex.push_back(std::make_pair(LBI.getInstructionIndex(SI), SI));
if (StoresByIndex.empty()) {
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;)
if (LoadInst *LI = dyn_cast<LoadInst>(*UI++)) {
LI->replaceAllUsesWith(UndefValue::get(LI->getType()));
if (AST && LI->getType()->isPointerTy())
AST->deleteValue(LI);
LBI.deleteValue(LI);
LI->eraseFromParent();
}
return;
}
std::sort(StoresByIndex.begin(), StoresByIndex.end());
for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) {
LoadInst *LI = dyn_cast<LoadInst>(*UI++);
if (!LI) continue;
unsigned LoadIdx = LBI.getInstructionIndex(LI);
StoresByIndexTy::iterator I =
std::lower_bound(StoresByIndex.begin(), StoresByIndex.end(),
std::pair<unsigned, StoreInst*>(LoadIdx, static_cast<StoreInst*>(0)),
StoreIndexSearchPredicate());
if (I == StoresByIndex.begin()) {
Info.UsingBlocks.push_back(LI->getParent());
continue;
}
--I;
LI->replaceAllUsesWith(I->second->getOperand(0));
if (AST && LI->getType()->isPointerTy())
AST->deleteValue(LI);
LI->eraseFromParent();
LBI.deleteValue(LI);
}
}
void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
StoreInst *SI) {
DIVariable DIVar(DDI->getVariable());
if (!DIVar.Verify())
return;
if (!DIF)
DIF = new DIFactory(*SI->getParent()->getParent()->getParent());
Instruction *DbgVal = DIF->InsertDbgValueIntrinsic(SI->getOperand(0), 0,
DIVar, SI);
DebugLoc SIDL = SI->getDebugLoc();
if (!SIDL.isUnknown())
DbgVal->setDebugLoc(SIDL);
else
DbgVal->setDebugLoc(DDI->getDebugLoc());
}
bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo,
unsigned &Version,
SmallPtrSet<PHINode*, 16> &InsertedPHINodes) {
PHINode *&PN = NewPhiNodes[std::make_pair(BB, AllocaNo)];
if (PN) return false;
PN = PHINode::Create(Allocas[AllocaNo]->getAllocatedType(),
Allocas[AllocaNo]->getName() + "." + Twine(Version++),
BB->begin());
++NumPHIInsert;
PhiToAllocaMap[PN] = AllocaNo;
PN->reserveOperandSpace(getNumPreds(BB));
InsertedPHINodes.insert(PN);
if (AST && PN->getType()->isPointerTy())
AST->copyValue(PointerAllocaValues[AllocaNo], PN);
return true;
}
void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred,
RenamePassData::ValVector &IncomingVals,
std::vector<RenamePassData> &Worklist) {
NextIteration:
if (PHINode *APN = dyn_cast<PHINode>(BB->begin())) {
if (PhiToAllocaMap.count(APN)) {
unsigned NewPHINumOperands = APN->getNumOperands();
unsigned NumEdges = 0;
for (succ_iterator I = succ_begin(Pred), E = succ_end(Pred); I != E; ++I)
if (*I == BB)
++NumEdges;
assert(NumEdges && "Must be at least one edge from Pred to BB!");
BasicBlock::iterator PNI = BB->begin();
do {
unsigned AllocaNo = PhiToAllocaMap[APN];
for (unsigned i = 0; i != NumEdges; ++i)
APN->addIncoming(IncomingVals[AllocaNo], Pred);
IncomingVals[AllocaNo] = APN;
++PNI;
APN = dyn_cast<PHINode>(PNI);
if (APN == 0) break;
} while (APN->getNumOperands() == NewPHINumOperands);
}
}
if (!Visited.insert(BB)) return;
for (BasicBlock::iterator II = BB->begin(); !isa<TerminatorInst>(II); ) {
Instruction *I = II++;
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
AllocaInst *Src = dyn_cast<AllocaInst>(LI->getPointerOperand());
if (!Src) continue;
std::map<AllocaInst*, unsigned>::iterator AI = AllocaLookup.find(Src);
if (AI == AllocaLookup.end()) continue;
Value *V = IncomingVals[AI->second];
LI->replaceAllUsesWith(V);
if (AST && LI->getType()->isPointerTy())
AST->deleteValue(LI);
BB->getInstList().erase(LI);
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
AllocaInst *Dest = dyn_cast<AllocaInst>(SI->getPointerOperand());
if (!Dest) continue;
std::map<AllocaInst *, unsigned>::iterator ai = AllocaLookup.find(Dest);
if (ai == AllocaLookup.end())
continue;
IncomingVals[ai->second] = SI->getOperand(0);
if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second])
ConvertDebugDeclareToDebugValue(DDI, SI);
BB->getInstList().erase(SI);
}
}
succ_iterator I = succ_begin(BB), E = succ_end(BB);
if (I == E) return;
SmallPtrSet<BasicBlock*, 8> VisitedSuccs;
VisitedSuccs.insert(*I);
Pred = BB;
BB = *I;
++I;
for (; I != E; ++I)
if (VisitedSuccs.insert(*I))
Worklist.push_back(RenamePassData(*I, Pred, IncomingVals));
goto NextIteration;
}
void llvm::PromoteMemToReg(const std::vector<AllocaInst*> &Allocas,
DominatorTree &DT, DominanceFrontier &DF,
AliasSetTracker *AST) {
if (Allocas.empty()) return;
PromoteMem2Reg(Allocas, DT, DF, AST).run();
}