Expand the pass to unify all of the unwind blocks as well
authorChris Lattner <sabre@nondot.org>
Wed, 10 Sep 2003 20:34:51 +0000 (20:34 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 10 Sep 2003 20:34:51 +0000 (20:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8456 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
lib/Transforms/Utils/UnifyFunctionExitNodes.cpp

index 01f055e801f1d11f9f7f995effb53a6693c1a2e2..431dd8b9d3f449590e4dfd1943ab8dcb17095f78 100644 (file)
@@ -1,9 +1,10 @@
-//===-- UnifyFunctionExitNodes.h - Ensure fn's have one return ---*- C++ -*--=//
+//===-- UnifyFunctionExitNodes.h - Ensure fn's have one return --*- C++ -*-===//
 //
-// This pass is used to ensure that functions have at most one return
-// instruction in them.  Additionally, it keeps track of which node is the new
-// exit node of the CFG.  If there are no exit nodes in the CFG, the getExitNode
-// method will return a null pointer.
+// This pass is used to ensure that functions have at most one return and one
+// unwind instruction in them.  Additionally, it keeps track of which node is
+// the new exit node of the CFG.  If there are no return or unwind instructions
+// in the function, the getReturnBlock/getUnwindBlock methods will return a null
+// pointer.
 //
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Pass.h"
 
 struct UnifyFunctionExitNodes : public FunctionPass {
-  BasicBlock *ExitNode;
+  BasicBlock *ReturnBlock, *UnwindBlock;
 public:
-  UnifyFunctionExitNodes() : ExitNode(0) {}
+  UnifyFunctionExitNodes() : ReturnBlock(0), UnwindBlock(0) {}
 
   // We can preserve non-critical-edgeness when we unify function exit nodes
   virtual void getAnalysisUsage(AnalysisUsage &AU) const;
 
-  // getExitNode - Return the new single (or nonexistant) exit node of the CFG.
+  // getReturn|UnwindBlock - Return the new single (or nonexistant) return or
+  // unwind basic blocks in the CFG.
   //
-  BasicBlock *getExitNode() const { return ExitNode; }
+  BasicBlock *getReturnBlock() const { return ReturnBlock; }
+  BasicBlock *getUnwindBlock() const { return UnwindBlock; }
 
   virtual bool runOnFunction(Function &F);
 };
 
-static inline Pass *createUnifyFunctionExitNodesPass() {
-  return new UnifyFunctionExitNodes();
-}
+Pass *createUnifyFunctionExitNodesPass();
 
 #endif
index 71f286c36e5fe8147ade8c33a10e999dabe2b9b2..ddce921d45e3b867586461296b8d8dbc9145755d 100644 (file)
 static RegisterOpt<UnifyFunctionExitNodes>
 X("mergereturn", "Unify function exit nodes");
 
+Pass *createUnifyFunctionExitNodesPass() {
+  return new UnifyFunctionExitNodes();
+}
+
 void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{
   // We preserve the non-critical-edgeness property
   AU.addPreservedID(BreakCriticalEdgesID);
@@ -34,15 +38,36 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) {
   // return.
   //
   std::vector<BasicBlock*> ReturningBlocks;
+  std::vector<BasicBlock*> UnwindingBlocks;
   for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
     if (isa<ReturnInst>(I->getTerminator()))
       ReturningBlocks.push_back(I);
+    else if (isa<UnwindInst>(I->getTerminator()))
+      UnwindingBlocks.push_back(I);
+
+  // Handle unwinding blocks first...
+  if (UnwindingBlocks.empty()) {
+    UnwindBlock = 0;
+  } else if (UnwindingBlocks.size() == 1) {
+    UnwindBlock = UnwindingBlocks.front();
+  } else {
+    UnwindBlock = new BasicBlock("UnifiedUnwindBlock", &F);
+    UnwindBlock->getInstList().push_back(new UnwindInst());
 
+    for (std::vector<BasicBlock*>::iterator I = UnwindingBlocks.begin(), 
+           E = UnwindingBlocks.end(); I != E; ++I) {
+      BasicBlock *BB = *I;
+      BB->getInstList().pop_back();  // Remove the return insn
+      BB->getInstList().push_back(new BranchInst(UnwindBlock));
+    }
+  }
+
+  // Now handle return blocks...
   if (ReturningBlocks.empty()) {
-    ExitNode = 0;
+    ReturnBlock = 0;
     return false;                          // No blocks return
   } else if (ReturningBlocks.size() == 1) {
-    ExitNode = ReturningBlocks.front();    // Already has a single return block
+    ReturnBlock = ReturningBlocks.front(); // Already has a single return block
     return false;
   }
 
@@ -50,7 +75,7 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) {
   // node (if the function returns a value), and convert all of the return 
   // instructions into unconditional branches.
   //
-  BasicBlock *NewRetBlock = new BasicBlock("UnifiedExitNode", &F);
+  BasicBlock *NewRetBlock = new BasicBlock("UnifiedReturnBlock", &F);
 
   PHINode *PN = 0;
   if (F.getReturnType() != Type::VoidTy) {
@@ -77,7 +102,6 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) {
     BB->getInstList().pop_back();  // Remove the return insn
     BB->getInstList().push_back(new BranchInst(NewRetBlock));
   }
-  ExitNode = NewRetBlock;
-
+  ReturnBlock = NewRetBlock;
   return true;
 }