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