diff options
| author | Chris Lattner <sabre@nondot.org> | 2003-09-10 20:34:51 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2003-09-10 20:34:51 +0000 | 
| commit | f941396ccee01198f9245167ef7c530e0797abb2 (patch) | |
| tree | e164948189294c71bfa82f043bef88b6eeb42c99 | |
| parent | e7980ae2ee9df6f26af8d7cfe752097051761ace (diff) | |
| download | bcm5719-llvm-f941396ccee01198f9245167ef7c530e0797abb2.tar.gz bcm5719-llvm-f941396ccee01198f9245167ef7c530e0797abb2.zip  | |
Expand the pass to unify all of the unwind blocks as well
llvm-svn: 8456
| -rw-r--r-- | llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h | 25 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | 34 | 
2 files changed, 42 insertions, 17 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 01f055e801f..431dd8b9d3f 100644 --- a/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -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.  //  //===----------------------------------------------------------------------===// @@ -13,22 +14,22 @@  #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 diff --git a/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index 71f286c36e5..ddce921d45e 100644 --- a/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -18,6 +18,10 @@  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;  }  | 

