aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Utils/PromoteMemoryToRegister.cpp73
1 files changed, 32 insertions, 41 deletions
diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index 7afca82..b3eaa13 100644
--- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -63,6 +63,7 @@ namespace {
struct AllocaInfo : private InstVisitor<AllocaInfo, bool> {
SmallVector<BasicBlock *, 32> DefiningBlocks;
SmallVector<BasicBlock *, 32> UsingBlocks;
+ SmallVector<Instruction *, 8> DeadInsts;
Type *AllocaTy;
StoreInst *OnlyStore;
@@ -75,6 +76,7 @@ struct AllocaInfo : private InstVisitor<AllocaInfo, bool> {
void clear() {
DefiningBlocks.clear();
UsingBlocks.clear();
+ DeadInsts.clear();
AllocaTy = 0;
OnlyStore = 0;
OnlyBlock = 0;
@@ -153,13 +155,18 @@ private:
}
bool visitBitCastInst(BitCastInst &BC) {
- enqueueUsers(BC);
+ if (BC.use_empty())
+ DeadInsts.push_back(&BC);
+ else
+ enqueueUsers(BC);
return true;
}
bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
- if (GEPI.use_empty())
+ if (GEPI.use_empty()) {
+ DeadInsts.push_back(&GEPI);
return true;
+ }
enqueueUsers(GEPI);
@@ -168,7 +175,10 @@ private:
// We can promote through debug info intrinsics as they don't alter the
// value stored in memory.
- bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { return true; }
+ bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {
+ DeadInsts.push_back(&I);
+ return true;
+ }
bool visitIntrinsicInst(IntrinsicInst &II) {
switch (II.getIntrinsicID()) {
@@ -180,6 +190,7 @@ private:
// lifetime.
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
+ DeadInsts.push_back(&II);
return true;
}
}
@@ -341,35 +352,15 @@ private:
} // end of anonymous namespace
-static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
- // Knowing that this alloca is promotable, we know that it's safe to kill all
- // instructions except for load and store.
- // FIXME: This function isn't actually specific to lifetime instrinsics. It
- // also is redundant with the actual analysis of the loads and stores and
- // should be folded into that.
-
- SmallVector<Instruction *, 8> Worklist;
- SmallPtrSet<Instruction *, 8> Visited;
- SmallVector<Instruction *, 8> Dead;
- Worklist.push_back(AI);
-
- do {
- Instruction *I = Worklist.pop_back_val();
-
- if (I->use_empty()) {
- Dead.push_back(I);
- continue;
- }
-
- for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
- UI != UE; ++UI)
- if (!isa<LoadInst>(*UI) && !isa<StoreInst>(*UI) &&
- Visited.insert(cast<Instruction>(*UI)))
- Worklist.push_back(cast<Instruction>(*UI));
- } while (!Worklist.empty());
-
- while (!Dead.empty()) {
- Instruction *I = Dead.pop_back_val();
+/// \brief Walk a small vector of dead instructions and recursively remove them
+/// and subsequently dead instructions.
+///
+/// This is only valid to call on dead instructions using an alloca which is
+/// promotable, as we leverage that assumption to delete them faster.
+static void removeDeadInstructions(AllocaInst *AI,
+ SmallVectorImpl<Instruction *> &DeadInsts) {
+ while (!DeadInsts.empty()) {
+ Instruction *I = DeadInsts.pop_back_val();
// Don't delete the alloca itself.
if (I == AI)
@@ -393,7 +384,7 @@ static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
if (!Op->use_empty())
continue;
- Dead.push_back(Op);
+ DeadInsts.push_back(Op);
}
I->eraseFromParent();
}
@@ -600,11 +591,17 @@ void PromoteMem2Reg::run() {
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!");
- removeLifetimeIntrinsicUsers(AI);
+ // Calculate the set of read and write-locations for each alloca. This is
+ // analogous to finding the 'uses' and 'definitions' of each variable.
+ bool Good = Info.analyzeAlloca(*AI);
+ (void)Good;
+ assert(Good && "Cannot promote non-promotable alloca!");
+
+ // Nuke all of the dead instructions.
+ removeDeadInstructions(AI, Info.DeadInsts);
if (AI->use_empty()) {
// If there are no uses of the alloca, just delete it now.
@@ -618,12 +615,6 @@ void PromoteMem2Reg::run() {
continue;
}
- // Calculate the set of read and write-locations for each alloca. This is
- // analogous to finding the 'uses' and 'definitions' of each variable.
- bool Good = Info.analyzeAlloca(*AI);
- (void)Good;
- assert(Good && "Cannot promote non-promotable alloca!");
-
// 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.
if (Info.DefiningBlocks.size() == 1) {