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