From 29aae157f7e4cfaf88ff3a1eb054144ab0fba7d7 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 6 Jul 2001 16:58:36 +0000 Subject: [PATCH] Add method to unify all exit nodes of a method llvm-svn: 143 --- .../Utils/UnifyFunctionExitNodes.cpp | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp diff --git a/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp new file mode 100644 index 000000000000..0217ce0eab7b --- /dev/null +++ b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -0,0 +1,69 @@ +//===- SimplifyCFG.cpp - CFG Simplification Routines -------------*- C++ -*--=// +// +// This file provides several routines that are useful for simplifying CFGs in +// various ways... +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/SimplifyCFG.h" +#include "llvm/BasicBlock.h" +#include "llvm/Method.h" +#include "llvm/iTerminators.h" +#include "llvm/iOther.h" +#include "llvm/Type.h" + +// UnifyAllExitNodes - Unify all exit nodes of the CFG by creating a new +// BasicBlock, and converting all returns to unconditional branches to this +// new basic block. The singular exit node is returned. +// +// If there are no return stmts in the Method, a null pointer is returned. +// +BasicBlock *cfg::UnifyAllExitNodes(Method *M) { + vector ReturningBlocks; + + // Loop over all of the blocks in a method, tracking all of the blocks that + // return. + // + for(Method::iterator I = M->begin(), E = M->end(); I != E; ++I) + if ((*I)->getTerminator()->getInstType() == Instruction::Ret) + ReturningBlocks.push_back(*I); + + if (ReturningBlocks.size() == 0) + return 0; // No blocks return + else if (ReturningBlocks.size() == 1) + return ReturningBlocks.front(); // Already has a single return block + + // Otherwise, we need to insert a new basic block into the method, add a PHI + // node (if the function returns a value), and convert all of the return + // instructions into unconditional branches. + // + BasicBlock *NewRetBlock = new BasicBlock("", M); + + if (M->getReturnType() != Type::VoidTy) { + // If the method doesn't return void... add a PHI node to the block... + PHINode *PN = new PHINode(M->getReturnType()); + NewRetBlock->getInstList().push_back(PN); + + // Add an incoming element to the PHI node for every return instruction that + // is merging into this new block... + for (vector::iterator I = ReturningBlocks.begin(), + E = ReturningBlocks.end(); I != E; ++I) + PN->addIncoming((*I)->getTerminator()->getOperand(0), *I); + + // Add a return instruction to return the result of the PHI node... + NewRetBlock->getInstList().push_back(new ReturnInst(PN)); + } else { + // If it returns void, just add a return void instruction to the block + NewRetBlock->getInstList().push_back(new ReturnInst()); + } + + // Loop over all of the blocks, replacing the return instruction with an + // unconditional branch. + // + for (vector::iterator I = ReturningBlocks.begin(), + E = ReturningBlocks.end(); I != E; ++I) { + delete (*I)->getInstList().pop_back(); // Remove the return insn + (*I)->getInstList().push_back(new BranchInst(NewRetBlock)); + } + return NewRetBlock; +}