[llvm] r187296 - Merge the removal of dead instructions and lifetime markers with the

Chandler Carruth chandlerc at gmail.com
Sat Jul 27 02:43:31 PDT 2013


Author: chandlerc
Date: Sat Jul 27 04:43:30 2013
New Revision: 187296

URL: http://llvm.org/viewvc/llvm-project?rev=187296&view=rev
Log:
Merge the removal of dead instructions and lifetime markers with the
analysis of the alloca. We don't need to visit all the users twice for
this. We build up a kill list during the analysis and then just process
it afterward. This recovers the tiny bit of performance lost by moving
to the visitor based analysis system as it removes one entire use-list
walk from mem2reg. In some cases, this is now faster than mem2reg was
previously.

Modified:
    llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp

Modified: llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp?rev=187296&r1=187295&r2=187296&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Sat Jul 27 04:43:30 2013
@@ -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<
   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
       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) {





More information about the llvm-commits mailing list