1 //===- UnifyFunctionExitNodes.cpp - Make all functions have a single exit -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass is used to ensure that functions have at most one return and one 10 // unreachable instruction in them. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" 15 #include "llvm/IR/BasicBlock.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Instructions.h" 18 #include "llvm/IR/Type.h" 19 #include "llvm/InitializePasses.h" 20 #include "llvm/Transforms/Utils.h" 21 using namespace llvm; 22 23 char UnifyFunctionExitNodes::ID = 0; 24 25 UnifyFunctionExitNodes::UnifyFunctionExitNodes() : FunctionPass(ID) { 26 initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry()); 27 } 28 29 INITIALIZE_PASS(UnifyFunctionExitNodes, "mergereturn", 30 "Unify function exit nodes", false, false) 31 32 Pass *llvm::createUnifyFunctionExitNodesPass() { 33 return new UnifyFunctionExitNodes(); 34 } 35 36 void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{ 37 // We preserve the non-critical-edgeness property 38 AU.addPreservedID(BreakCriticalEdgesID); 39 // This is a cluster of orthogonal Transforms 40 AU.addPreservedID(LowerSwitchID); 41 } 42 43 // UnifyAllExitNodes - Unify all exit nodes of the CFG by creating a new 44 // BasicBlock, and converting all returns to unconditional branches to this 45 // new basic block. The singular exit node is returned. 46 // 47 // If there are no return stmts in the Function, a null pointer is returned. 48 // 49 bool UnifyFunctionExitNodes::runOnFunction(Function &F) { 50 // Loop over all of the blocks in a function, tracking all of the blocks that 51 // return. 52 // 53 std::vector<BasicBlock*> ReturningBlocks; 54 std::vector<BasicBlock*> UnreachableBlocks; 55 for (BasicBlock &I : F) 56 if (isa<ReturnInst>(I.getTerminator())) 57 ReturningBlocks.push_back(&I); 58 else if (isa<UnreachableInst>(I.getTerminator())) 59 UnreachableBlocks.push_back(&I); 60 61 // Then unreachable blocks. 62 if (UnreachableBlocks.size() > 1) { 63 BasicBlock *UnreachableBlock = BasicBlock::Create(F.getContext(), 64 "UnifiedUnreachableBlock", &F); 65 new UnreachableInst(F.getContext(), UnreachableBlock); 66 67 for (BasicBlock *BB : UnreachableBlocks) { 68 BB->getInstList().pop_back(); // Remove the unreachable inst. 69 BranchInst::Create(UnreachableBlock, BB); 70 } 71 } 72 73 // There is nothing more to do if we do not have multiple return blocks. 74 if (ReturningBlocks.size() <= 1) 75 return false; 76 77 // Otherwise, we need to insert a new basic block into the function, add a PHI 78 // nodes (if the function returns values), and convert all of the return 79 // instructions into unconditional branches. 80 // 81 BasicBlock *NewRetBlock = BasicBlock::Create(F.getContext(), 82 "UnifiedReturnBlock", &F); 83 84 PHINode *PN = nullptr; 85 if (F.getReturnType()->isVoidTy()) { 86 ReturnInst::Create(F.getContext(), nullptr, NewRetBlock); 87 } else { 88 // If the function doesn't return void... add a PHI node to the block... 89 PN = PHINode::Create(F.getReturnType(), ReturningBlocks.size(), 90 "UnifiedRetVal"); 91 NewRetBlock->getInstList().push_back(PN); 92 ReturnInst::Create(F.getContext(), PN, NewRetBlock); 93 } 94 95 // Loop over all of the blocks, replacing the return instruction with an 96 // unconditional branch. 97 // 98 for (BasicBlock *BB : ReturningBlocks) { 99 // Add an incoming element to the PHI node for every return instruction that 100 // is merging into this new block... 101 if (PN) 102 PN->addIncoming(BB->getTerminator()->getOperand(0), BB); 103 104 BB->getInstList().pop_back(); // Remove the return insn 105 BranchInst::Create(NewRetBlock, BB); 106 } 107 return true; 108 } 109