1 //===- PruneEH.cpp - Pass which deletes unused exception handlers ---------===// 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 file implements a simple interprocedural pass which walks the 10 // call-graph, turning invoke instructions into calls, iff the callee cannot 11 // throw an exception, and marking functions 'nounwind' if they cannot throw. 12 // It implements this as a bottom-up traversal of the call-graph. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/ADT/SetVector.h" 17 #include "llvm/ADT/SmallPtrSet.h" 18 #include "llvm/ADT/Statistic.h" 19 #include "llvm/Analysis/CallGraph.h" 20 #include "llvm/Analysis/CallGraphSCCPass.h" 21 #include "llvm/Analysis/EHPersonalities.h" 22 #include "llvm/IR/CFG.h" 23 #include "llvm/IR/Constants.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/InlineAsm.h" 26 #include "llvm/IR/Instructions.h" 27 #include "llvm/IR/LLVMContext.h" 28 #include "llvm/InitializePasses.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include "llvm/Transforms/IPO.h" 31 #include "llvm/Transforms/Utils/CallGraphUpdater.h" 32 #include "llvm/Transforms/Utils/Local.h" 33 #include <algorithm> 34 35 using namespace llvm; 36 37 #define DEBUG_TYPE "prune-eh" 38 39 STATISTIC(NumRemoved, "Number of invokes removed"); 40 STATISTIC(NumUnreach, "Number of noreturn calls optimized"); 41 42 namespace { 43 struct PruneEH : public CallGraphSCCPass { 44 static char ID; // Pass identification, replacement for typeid 45 PruneEH() : CallGraphSCCPass(ID) { 46 initializePruneEHPass(*PassRegistry::getPassRegistry()); 47 } 48 49 // runOnSCC - Analyze the SCC, performing the transformation if possible. 50 bool runOnSCC(CallGraphSCC &SCC) override; 51 }; 52 } 53 static bool SimplifyFunction(Function *F, CallGraphUpdater &CGU); 54 static void DeleteBasicBlock(BasicBlock *BB, CallGraphUpdater &CGU); 55 56 char PruneEH::ID = 0; 57 INITIALIZE_PASS_BEGIN(PruneEH, "prune-eh", 58 "Remove unused exception handling info", false, false) 59 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) 60 INITIALIZE_PASS_END(PruneEH, "prune-eh", 61 "Remove unused exception handling info", false, false) 62 63 Pass *llvm::createPruneEHPass() { return new PruneEH(); } 64 65 static bool runImpl(CallGraphUpdater &CGU, SetVector<Function *> &Functions) { 66 #ifndef NDEBUG 67 for (auto *F : Functions) 68 assert(F && "null Function"); 69 #endif 70 bool MadeChange = false; 71 72 // First pass, scan all of the functions in the SCC, simplifying them 73 // according to what we know. 74 for (Function *F : Functions) 75 MadeChange |= SimplifyFunction(F, CGU); 76 77 // Next, check to see if any callees might throw or if there are any external 78 // functions in this SCC: if so, we cannot prune any functions in this SCC. 79 // Definitions that are weak and not declared non-throwing might be 80 // overridden at linktime with something that throws, so assume that. 81 // If this SCC includes the unwind instruction, we KNOW it throws, so 82 // obviously the SCC might throw. 83 // 84 bool SCCMightUnwind = false, SCCMightReturn = false; 85 for (Function *F : Functions) { 86 if (!F->hasExactDefinition()) { 87 SCCMightUnwind |= !F->doesNotThrow(); 88 SCCMightReturn |= !F->doesNotReturn(); 89 } else { 90 bool CheckUnwind = !SCCMightUnwind && !F->doesNotThrow(); 91 bool CheckReturn = !SCCMightReturn && !F->doesNotReturn(); 92 // Determine if we should scan for InlineAsm in a naked function as it 93 // is the only way to return without a ReturnInst. Only do this for 94 // no-inline functions as functions which may be inlined cannot 95 // meaningfully return via assembly. 96 bool CheckReturnViaAsm = CheckReturn && 97 F->hasFnAttribute(Attribute::Naked) && 98 F->hasFnAttribute(Attribute::NoInline); 99 100 if (!CheckUnwind && !CheckReturn) 101 continue; 102 103 for (const BasicBlock &BB : *F) { 104 const Instruction *TI = BB.getTerminator(); 105 if (CheckUnwind && TI->mayThrow()) { 106 SCCMightUnwind = true; 107 } else if (CheckReturn && isa<ReturnInst>(TI)) { 108 SCCMightReturn = true; 109 } 110 111 for (const Instruction &I : BB) { 112 if ((!CheckUnwind || SCCMightUnwind) && 113 (!CheckReturnViaAsm || SCCMightReturn)) 114 break; 115 116 // Check to see if this function performs an unwind or calls an 117 // unwinding function. 118 if (CheckUnwind && !SCCMightUnwind && I.mayThrow()) { 119 bool InstMightUnwind = true; 120 if (const auto *CI = dyn_cast<CallInst>(&I)) { 121 if (Function *Callee = CI->getCalledFunction()) { 122 // If the callee is outside our current SCC then we may throw 123 // because it might. If it is inside, do nothing. 124 if (Functions.contains(Callee)) 125 InstMightUnwind = false; 126 } 127 } 128 SCCMightUnwind |= InstMightUnwind; 129 } 130 if (CheckReturnViaAsm && !SCCMightReturn) 131 if (const auto *CB = dyn_cast<CallBase>(&I)) 132 if (const auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) 133 if (IA->hasSideEffects()) 134 SCCMightReturn = true; 135 } 136 } 137 if (SCCMightUnwind && SCCMightReturn) 138 break; 139 } 140 } 141 142 // If the SCC doesn't unwind or doesn't throw, note this fact. 143 if (!SCCMightUnwind || !SCCMightReturn) 144 for (Function *F : Functions) { 145 if (!SCCMightUnwind && !F->hasFnAttribute(Attribute::NoUnwind)) { 146 F->addFnAttr(Attribute::NoUnwind); 147 MadeChange = true; 148 } 149 150 if (!SCCMightReturn && !F->hasFnAttribute(Attribute::NoReturn)) { 151 F->addFnAttr(Attribute::NoReturn); 152 MadeChange = true; 153 } 154 } 155 156 for (Function *F : Functions) { 157 // Convert any invoke instructions to non-throwing functions in this node 158 // into call instructions with a branch. This makes the exception blocks 159 // dead. 160 MadeChange |= SimplifyFunction(F, CGU); 161 } 162 163 return MadeChange; 164 } 165 166 bool PruneEH::runOnSCC(CallGraphSCC &SCC) { 167 if (skipSCC(SCC)) 168 return false; 169 SetVector<Function *> Functions; 170 for (auto &N : SCC) { 171 if (auto *F = N->getFunction()) 172 Functions.insert(F); 173 } 174 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); 175 CallGraphUpdater CGU; 176 CGU.initialize(CG, SCC); 177 return runImpl(CGU, Functions); 178 } 179 180 181 // SimplifyFunction - Given information about callees, simplify the specified 182 // function if we have invokes to non-unwinding functions or code after calls to 183 // no-return functions. 184 static bool SimplifyFunction(Function *F, CallGraphUpdater &CGU) { 185 bool MadeChange = false; 186 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 187 if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) 188 if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(F)) { 189 BasicBlock *UnwindBlock = II->getUnwindDest(); 190 removeUnwindEdge(&*BB); 191 192 // If the unwind block is now dead, nuke it. 193 if (pred_empty(UnwindBlock)) 194 DeleteBasicBlock(UnwindBlock, CGU); // Delete the new BB. 195 196 ++NumRemoved; 197 MadeChange = true; 198 } 199 200 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) 201 if (CallInst *CI = dyn_cast<CallInst>(I++)) 202 if (CI->doesNotReturn() && !CI->isMustTailCall() && 203 !isa<UnreachableInst>(I)) { 204 // This call calls a function that cannot return. Insert an 205 // unreachable instruction after it and simplify the code. Do this 206 // by splitting the BB, adding the unreachable, then deleting the 207 // new BB. 208 BasicBlock *New = BB->splitBasicBlock(I); 209 210 // Remove the uncond branch and add an unreachable. 211 BB->getInstList().pop_back(); 212 new UnreachableInst(BB->getContext(), &*BB); 213 214 DeleteBasicBlock(New, CGU); // Delete the new BB. 215 MadeChange = true; 216 ++NumUnreach; 217 break; 218 } 219 } 220 221 return MadeChange; 222 } 223 224 /// DeleteBasicBlock - remove the specified basic block from the program, 225 /// updating the callgraph to reflect any now-obsolete edges due to calls that 226 /// exist in the BB. 227 static void DeleteBasicBlock(BasicBlock *BB, CallGraphUpdater &CGU) { 228 assert(pred_empty(BB) && "BB is not dead!"); 229 230 Instruction *TokenInst = nullptr; 231 232 for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { 233 --I; 234 235 if (I->getType()->isTokenTy()) { 236 TokenInst = &*I; 237 break; 238 } 239 240 if (auto *Call = dyn_cast<CallBase>(&*I)) { 241 const Function *Callee = Call->getCalledFunction(); 242 if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) 243 CGU.removeCallSite(*Call); 244 else if (!Callee->isIntrinsic()) 245 CGU.removeCallSite(*Call); 246 } 247 248 if (!I->use_empty()) 249 I->replaceAllUsesWith(UndefValue::get(I->getType())); 250 } 251 252 if (TokenInst) { 253 if (!TokenInst->isTerminator()) 254 changeToUnreachable(TokenInst->getNextNode()); 255 } else { 256 // Get the list of successors of this block. 257 std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB)); 258 259 for (unsigned i = 0, e = Succs.size(); i != e; ++i) 260 Succs[i]->removePredecessor(BB); 261 262 BB->eraseFromParent(); 263 } 264 } 265