[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