From f46057be77c39d972a2aacb9743ce265efa60b70 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 10 Sep 2003 20:34:51 +0000 Subject: [PATCH] Expand the pass to unify all of the unwind blocks as well git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8456 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Transforms/Utils/UnifyFunctionExitNodes.h | 25 +++++++------- .../Utils/UnifyFunctionExitNodes.cpp | 34 ++++++++++++++++--- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 01f055e801f..431dd8b9d3f 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/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/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index 71f286c36e5..ddce921d45e 100644 --- a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -18,6 +18,10 @@ static RegisterOpt 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 ReturningBlocks; + std::vector UnwindingBlocks; for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I) if (isa(I->getTerminator())) ReturningBlocks.push_back(I); + else if (isa(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::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; } -- 2.34.1