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 using namespace llvm; 20 21 namespace { 22 23 bool unifyUnreachableBlocks(Function &F) { 24 std::vector<BasicBlock *> UnreachableBlocks; 25 26 for (BasicBlock &I : F) 27 if (isa<UnreachableInst>(I.getTerminator())) 28 UnreachableBlocks.push_back(&I); 29 30 if (UnreachableBlocks.size() <= 1) 31 return false; 32 33 BasicBlock *UnreachableBlock = 34 BasicBlock::Create(F.getContext(), "UnifiedUnreachableBlock", &F); 35 new UnreachableInst(F.getContext(), UnreachableBlock); 36 37 for (BasicBlock *BB : UnreachableBlocks) { 38 BB->back().eraseFromParent(); // Remove the unreachable inst. 39 BranchInst::Create(UnreachableBlock, BB); 40 } 41 42 return true; 43 } 44 45 bool unifyReturnBlocks(Function &F) { 46 std::vector<BasicBlock *> ReturningBlocks; 47 48 for (BasicBlock &I : F) 49 if (isa<ReturnInst>(I.getTerminator())) 50 ReturningBlocks.push_back(&I); 51 52 if (ReturningBlocks.size() <= 1) 53 return false; 54 55 // Insert a new basic block into the function, add PHI nodes (if the function 56 // returns values), and convert all of the return instructions into 57 // unconditional branches. 58 BasicBlock *NewRetBlock = BasicBlock::Create(F.getContext(), 59 "UnifiedReturnBlock", &F); 60 61 PHINode *PN = nullptr; 62 if (F.getReturnType()->isVoidTy()) { 63 ReturnInst::Create(F.getContext(), nullptr, NewRetBlock); 64 } else { 65 // If the function doesn't return void... add a PHI node to the block... 66 PN = PHINode::Create(F.getReturnType(), ReturningBlocks.size(), 67 "UnifiedRetVal"); 68 PN->insertInto(NewRetBlock, NewRetBlock->end()); 69 ReturnInst::Create(F.getContext(), PN, NewRetBlock); 70 } 71 72 // Loop over all of the blocks, replacing the return instruction with an 73 // unconditional branch. 74 for (BasicBlock *BB : ReturningBlocks) { 75 // Add an incoming element to the PHI node for every return instruction that 76 // is merging into this new block... 77 if (PN) 78 PN->addIncoming(BB->getTerminator()->getOperand(0), BB); 79 80 BB->back().eraseFromParent(); // Remove the return insn 81 BranchInst::Create(NewRetBlock, BB); 82 } 83 84 return true; 85 } 86 } // namespace 87 88 PreservedAnalyses UnifyFunctionExitNodesPass::run(Function &F, 89 FunctionAnalysisManager &AM) { 90 bool Changed = false; 91 Changed |= unifyUnreachableBlocks(F); 92 Changed |= unifyReturnBlocks(F); 93 return Changed ? PreservedAnalyses() : PreservedAnalyses::all(); 94 } 95