[llvm-commits] [llvm] r53615 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp

Owen Anderson resistor at mac.com
Tue Jul 15 09:28:06 PDT 2008


Author: resistor
Date: Tue Jul 15 11:28:06 2008
New Revision: 53615

URL: http://llvm.org/viewvc/llvm-project?rev=53615&view=rev
Log:
Have GVN do a pre-pass over the CFG that folds away unconditional branches where possible.  This allows local PRE to be more aggressive.

Modified:
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=53615&r1=53614&r2=53615&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Tue Jul 15 11:28:06 2008
@@ -41,6 +41,7 @@
 STATISTIC(NumGVNInstr, "Number of instructions deleted");
 STATISTIC(NumGVNLoad, "Number of loads deleted");
 STATISTIC(NumGVNPRE, "Number of instructions PRE'd");
+STATISTIC(NumGVNBlocks, "Number of blocks merged");
 
 static cl::opt<bool> EnablePRE("enable-pre",
                                cl::init(false), cl::Hidden);
@@ -749,6 +750,7 @@
     bool isSafeReplacement(PHINode* p, Instruction* inst);
     bool performPRE(Function& F);
     Value* lookupNumber(BasicBlock* BB, uint32_t num);
+    bool mergeBlockIntoPredecessor(BasicBlock* BB);
   };
   
   char GVN::ID = 0;
@@ -1324,12 +1326,71 @@
   return changed;
 }
 
-// GVN::iterateOnFunction - Executes one iteration of GVN
+// mergeBlockIntoPredecessor - If this block is the only successor
+// of its predecessor, and the edge is non-critical, 
+// fold it into that predecessor.
+bool GVN::mergeBlockIntoPredecessor(BasicBlock* BB) {
+  // Can't merge the entry block.
+  if (pred_begin(BB) == pred_end(BB)) return false;
+  // Can't merge if there are multiple preds.
+  if (++pred_begin(BB) != pred_end(BB)) return false;
+  
+  BasicBlock* PredBB = *pred_begin(BB);
+  
+  // Can't merge if the edge is critical.
+  if (PredBB->getTerminator()->getNumSuccessors() != 1) return false;
+  
+  // Begin by getting rid of unneeded PHIs.
+  while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {
+    PN->replaceAllUsesWith(PN->getIncomingValue(0));
+    BB->getInstList().pop_front();  // Delete the phi node...
+  }
+  
+  // Delete the unconditional branch from the predecessor...
+  PredBB->getInstList().pop_back();
+  
+  // Move all definitions in the successor to the predecessor...
+  PredBB->getInstList().splice(PredBB->end(), BB->getInstList());
+  
+  // Make all PHI nodes that referred to BB now refer to Pred as their
+  // source...
+  BB->replaceAllUsesWith(PredBB);
+  
+  // Finally, erase the old block and update dominator info.
+  DominatorTree& DT = getAnalysis<DominatorTree>();
+  DomTreeNode* DTN = DT[BB];
+  DomTreeNode* PredDTN = DT[PredBB];
+  
+  if (DTN) {
+    SmallPtrSet<DomTreeNode*, 8> Children(DTN->begin(), DTN->end());
+    for (SmallPtrSet<DomTreeNode*, 8>::iterator DI = Children.begin(),
+         DE = Children.end(); DI != DE; ++DI)
+      DT.changeImmediateDominator(*DI, PredDTN);
+
+    DT.eraseNode(BB);
+  }
+  
+  BB->eraseFromParent();
+  
+  NumGVNBlocks++;
+  return true;
+}
+
+// iterateOnFunction - Executes one iteration of GVN
 bool GVN::iterateOnFunction(Function &F) {
   // Clean out global sets from any previous functions
   VN.clear();
   phiMap.clear();
   
+  // Merge unconditional branches, allowing PRE to catch more
+  // optimization opportunities.
+  bool mergedBlocks = false;
+  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ) {
+    BasicBlock* BB = FI;
+    ++FI;
+    mergedBlocks |= mergeBlockIntoPredecessor(BB);
+  }
+  
   for (DenseMap<BasicBlock*, ValueNumberScope*>::iterator
        I = localAvail.begin(), E = localAvail.end(); I != E; ++I)
     delete I->second;
@@ -1346,5 +1407,5 @@
   if (EnablePRE)
     changed |= performPRE(F);
   
-  return changed;
+  return changed || mergedBlocks;
 }





More information about the llvm-commits mailing list