1 //===- PruneEH.cpp - Pass which deletes unused exception handlers ---------===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
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"
37 #define DEBUG_TYPE "prune-eh"
39 STATISTIC(NumRemoved
, "Number of invokes removed");
40 STATISTIC(NumUnreach
, "Number of noreturn calls optimized");
43 struct PruneEH
: public CallGraphSCCPass
{
44 static char ID
; // Pass identification, replacement for typeid
45 PruneEH() : CallGraphSCCPass(ID
) {
46 initializePruneEHPass(*PassRegistry::getPassRegistry());
49 // runOnSCC - Analyze the SCC, performing the transformation if possible.
50 bool runOnSCC(CallGraphSCC
&SCC
) override
;
53 static bool SimplifyFunction(Function
*F
, CallGraphUpdater
&CGU
);
54 static void DeleteBasicBlock(BasicBlock
*BB
, CallGraphUpdater
&CGU
);
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)
63 Pass
*llvm::createPruneEHPass() { return new PruneEH(); }
65 static bool runImpl(CallGraphUpdater
&CGU
, SetVector
<Function
*> &Functions
) {
67 for (auto *F
: Functions
)
68 assert(F
&& "null Function");
70 bool MadeChange
= false;
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
);
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.
84 bool SCCMightUnwind
= false, SCCMightReturn
= false;
85 for (Function
*F
: Functions
) {
86 if (!F
->hasExactDefinition()) {
87 SCCMightUnwind
|= !F
->doesNotThrow();
88 SCCMightReturn
|= !F
->doesNotReturn();
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
);
100 if (!CheckUnwind
&& !CheckReturn
)
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;
111 for (const Instruction
&I
: BB
) {
112 if ((!CheckUnwind
|| SCCMightUnwind
) &&
113 (!CheckReturnViaAsm
|| SCCMightReturn
))
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;
128 SCCMightUnwind
|= InstMightUnwind
;
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;
137 if (SCCMightUnwind
&& SCCMightReturn
)
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
);
150 if (!SCCMightReturn
&& !F
->hasFnAttribute(Attribute::NoReturn
)) {
151 F
->addFnAttr(Attribute::NoReturn
);
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
160 MadeChange
|= SimplifyFunction(F
, CGU
);
166 bool PruneEH::runOnSCC(CallGraphSCC
&SCC
) {
169 SetVector
<Function
*> Functions
;
170 for (auto &N
: SCC
) {
171 if (auto *F
= N
->getFunction())
174 CallGraph
&CG
= getAnalysis
<CallGraphWrapperPass
>().getCallGraph();
175 CallGraphUpdater CGU
;
176 CGU
.initialize(CG
, SCC
);
177 return runImpl(CGU
, Functions
);
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
);
192 // If the unwind block is now dead, nuke it.
193 if (pred_empty(UnwindBlock
))
194 DeleteBasicBlock(UnwindBlock
, CGU
); // Delete the new BB.
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
208 BasicBlock
*New
= BB
->splitBasicBlock(I
);
210 // Remove the uncond branch and add an unreachable.
211 BB
->getInstList().pop_back();
212 new UnreachableInst(BB
->getContext(), &*BB
);
214 DeleteBasicBlock(New
, CGU
); // Delete the new BB.
224 /// DeleteBasicBlock - remove the specified basic block from the program,
225 /// updating the callgraph to reflect any now-obsolete edges due to calls that
227 static void DeleteBasicBlock(BasicBlock
*BB
, CallGraphUpdater
&CGU
) {
228 assert(pred_empty(BB
) && "BB is not dead!");
230 Instruction
*TokenInst
= nullptr;
232 for (BasicBlock::iterator I
= BB
->end(), E
= BB
->begin(); I
!= E
; ) {
235 if (I
->getType()->isTokenTy()) {
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
);
249 I
->replaceAllUsesWith(UndefValue::get(I
->getType()));
253 if (!TokenInst
->isTerminator())
254 changeToUnreachable(TokenInst
->getNextNode());
256 // Get the list of successors of this block.
257 std::vector
<BasicBlock
*> Succs(succ_begin(BB
), succ_end(BB
));
259 for (unsigned i
= 0, e
= Succs
.size(); i
!= e
; ++i
)
260 Succs
[i
]->removePredecessor(BB
);
262 BB
->eraseFromParent();