diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
| commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
| tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | |
| parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp')
| -rw-r--r-- | contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | 114 |
1 files changed, 0 insertions, 114 deletions
diff --git a/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp deleted file mode 100644 index 7f7bdf8a3d6d..000000000000 --- a/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//===- UnifyFunctionExitNodes.cpp - Make all functions have a single exit -===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Type.h" -#include "llvm/Transforms/Utils.h" -using namespace llvm; - -char UnifyFunctionExitNodes::ID = 0; -INITIALIZE_PASS(UnifyFunctionExitNodes, "mergereturn", - "Unify function exit nodes", false, false) - -Pass *llvm::createUnifyFunctionExitNodesPass() { - return new UnifyFunctionExitNodes(); -} - -void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{ - // We preserve the non-critical-edgeness property - AU.addPreservedID(BreakCriticalEdgesID); - // This is a cluster of orthogonal Transforms - AU.addPreservedID(LowerSwitchID); -} - -// 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 Function, a null pointer is returned. -// -bool UnifyFunctionExitNodes::runOnFunction(Function &F) { - // Loop over all of the blocks in a function, tracking all of the blocks that - // return. - // - std::vector<BasicBlock*> ReturningBlocks; - std::vector<BasicBlock*> UnreachableBlocks; - for (BasicBlock &I : F) - if (isa<ReturnInst>(I.getTerminator())) - ReturningBlocks.push_back(&I); - else if (isa<UnreachableInst>(I.getTerminator())) - UnreachableBlocks.push_back(&I); - - // Then unreachable blocks. - if (UnreachableBlocks.empty()) { - UnreachableBlock = nullptr; - } else if (UnreachableBlocks.size() == 1) { - UnreachableBlock = UnreachableBlocks.front(); - } else { - UnreachableBlock = BasicBlock::Create(F.getContext(), - "UnifiedUnreachableBlock", &F); - new UnreachableInst(F.getContext(), UnreachableBlock); - - for (BasicBlock *BB : UnreachableBlocks) { - BB->getInstList().pop_back(); // Remove the unreachable inst. - BranchInst::Create(UnreachableBlock, BB); - } - } - - // Now handle return blocks. - if (ReturningBlocks.empty()) { - ReturnBlock = nullptr; - return false; // No blocks return - } else if (ReturningBlocks.size() == 1) { - ReturnBlock = ReturningBlocks.front(); // Already has a single return block - return false; - } - - // Otherwise, we need to insert a new basic block into the function, add a PHI - // nodes (if the function returns values), and convert all of the return - // instructions into unconditional branches. - // - BasicBlock *NewRetBlock = BasicBlock::Create(F.getContext(), - "UnifiedReturnBlock", &F); - - PHINode *PN = nullptr; - if (F.getReturnType()->isVoidTy()) { - ReturnInst::Create(F.getContext(), nullptr, NewRetBlock); - } else { - // If the function doesn't return void... add a PHI node to the block... - PN = PHINode::Create(F.getReturnType(), ReturningBlocks.size(), - "UnifiedRetVal"); - NewRetBlock->getInstList().push_back(PN); - ReturnInst::Create(F.getContext(), PN, NewRetBlock); - } - - // Loop over all of the blocks, replacing the return instruction with an - // unconditional branch. - // - for (BasicBlock *BB : ReturningBlocks) { - // Add an incoming element to the PHI node for every return instruction that - // is merging into this new block... - if (PN) - PN->addIncoming(BB->getTerminator()->getOperand(0), BB); - - BB->getInstList().pop_back(); // Remove the return insn - BranchInst::Create(NewRetBlock, BB); - } - ReturnBlock = NewRetBlock; - return true; -} |
