xref: /src/contrib/llvm-project/llvm/lib/Transforms/Utils/LowerInvoke.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ca98fd9SDimitry Andric //===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This transformation is designed for use by code generators which do not yet
105ca98fd9SDimitry Andric // support stack unwinding.  This pass converts 'invoke' instructions to 'call'
115ca98fd9SDimitry Andric // instructions, so that any exception-handling 'landingpad' blocks become dead
125ca98fd9SDimitry Andric // code (which can be removed by running the '-simplifycfg' pass afterwards).
13009b1c42SEd Schouten //
14009b1c42SEd Schouten //===----------------------------------------------------------------------===//
15009b1c42SEd Schouten 
16b915e9e0SDimitry Andric #include "llvm/Transforms/Utils/LowerInvoke.h"
1766e41e3cSRoman Divacky #include "llvm/ADT/SmallVector.h"
18009b1c42SEd Schouten #include "llvm/ADT/Statistic.h"
194a16efa3SDimitry Andric #include "llvm/IR/Instructions.h"
20706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
214a16efa3SDimitry Andric #include "llvm/Pass.h"
22eb11fae6SDimitry Andric #include "llvm/Transforms/Utils.h"
23009b1c42SEd Schouten using namespace llvm;
24009b1c42SEd Schouten 
25ac9a064cSDimitry Andric #define DEBUG_TYPE "lower-invoke"
26009b1c42SEd Schouten 
275ca98fd9SDimitry Andric STATISTIC(NumInvokes, "Number of invokes replaced");
28009b1c42SEd Schouten 
29009b1c42SEd Schouten namespace {
30b915e9e0SDimitry Andric   class LowerInvokeLegacyPass : public FunctionPass {
31009b1c42SEd Schouten   public:
32009b1c42SEd Schouten     static char ID; // Pass identification, replacement for typeid
LowerInvokeLegacyPass()33b915e9e0SDimitry Andric     explicit LowerInvokeLegacyPass() : FunctionPass(ID) {
34b915e9e0SDimitry Andric       initializeLowerInvokeLegacyPassPass(*PassRegistry::getPassRegistry());
35cf099d11SDimitry Andric     }
365ca98fd9SDimitry Andric     bool runOnFunction(Function &F) override;
37009b1c42SEd Schouten   };
38009b1c42SEd Schouten }
39009b1c42SEd Schouten 
40b915e9e0SDimitry Andric char LowerInvokeLegacyPass::ID = 0;
41b915e9e0SDimitry Andric INITIALIZE_PASS(LowerInvokeLegacyPass, "lowerinvoke",
42d39c594dSDimitry Andric                 "Lower invoke and unwind, for unwindless code generators",
43cf099d11SDimitry Andric                 false, false)
44009b1c42SEd Schouten 
runImpl(Function & F)45b915e9e0SDimitry Andric static bool runImpl(Function &F) {
46009b1c42SEd Schouten   bool Changed = false;
4701095a5dSDimitry Andric   for (BasicBlock &BB : F)
4801095a5dSDimitry Andric     if (InvokeInst *II = dyn_cast<InvokeInst>(BB.getTerminator())) {
49b60736ecSDimitry Andric       SmallVector<Value *, 16> CallArgs(II->args());
50eb11fae6SDimitry Andric       SmallVector<OperandBundleDef, 1> OpBundles;
51eb11fae6SDimitry Andric       II->getOperandBundlesAsDefs(OpBundles);
52009b1c42SEd Schouten       // Insert a normal call instruction...
53b915e9e0SDimitry Andric       CallInst *NewCall =
54cfca06d7SDimitry Andric           CallInst::Create(II->getFunctionType(), II->getCalledOperand(),
55ac9a064cSDimitry Andric                            CallArgs, OpBundles, "", II->getIterator());
56009b1c42SEd Schouten       NewCall->takeName(II);
57009b1c42SEd Schouten       NewCall->setCallingConv(II->getCallingConv());
58009b1c42SEd Schouten       NewCall->setAttributes(II->getAttributes());
59cf099d11SDimitry Andric       NewCall->setDebugLoc(II->getDebugLoc());
60009b1c42SEd Schouten       II->replaceAllUsesWith(NewCall);
61009b1c42SEd Schouten 
62009b1c42SEd Schouten       // Insert an unconditional branch to the normal destination.
63ac9a064cSDimitry Andric       BranchInst::Create(II->getNormalDest(), II->getIterator());
64009b1c42SEd Schouten 
65009b1c42SEd Schouten       // Remove any PHI node entries from the exception destination.
6601095a5dSDimitry Andric       II->getUnwindDest()->removePredecessor(&BB);
67009b1c42SEd Schouten 
68009b1c42SEd Schouten       // Remove the invoke instruction now.
69e3b55780SDimitry Andric       II->eraseFromParent();
70009b1c42SEd Schouten 
71b915e9e0SDimitry Andric       ++NumInvokes;
72b915e9e0SDimitry Andric       Changed = true;
73009b1c42SEd Schouten     }
74009b1c42SEd Schouten   return Changed;
75009b1c42SEd Schouten }
76b915e9e0SDimitry Andric 
runOnFunction(Function & F)77b915e9e0SDimitry Andric bool LowerInvokeLegacyPass::runOnFunction(Function &F) {
78b915e9e0SDimitry Andric   return runImpl(F);
79b915e9e0SDimitry Andric }
80b915e9e0SDimitry Andric 
81b915e9e0SDimitry Andric namespace llvm {
82b915e9e0SDimitry Andric char &LowerInvokePassID = LowerInvokeLegacyPass::ID;
83b915e9e0SDimitry Andric 
84b915e9e0SDimitry Andric // Public Interface To the LowerInvoke pass.
createLowerInvokePass()85b915e9e0SDimitry Andric FunctionPass *createLowerInvokePass() { return new LowerInvokeLegacyPass(); }
86b915e9e0SDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)87b915e9e0SDimitry Andric PreservedAnalyses LowerInvokePass::run(Function &F,
88b915e9e0SDimitry Andric                                        FunctionAnalysisManager &AM) {
89b915e9e0SDimitry Andric   bool Changed = runImpl(F);
90b915e9e0SDimitry Andric   if (!Changed)
91b915e9e0SDimitry Andric     return PreservedAnalyses::all();
92b915e9e0SDimitry Andric 
93b915e9e0SDimitry Andric   return PreservedAnalyses::none();
94b915e9e0SDimitry Andric }
95b915e9e0SDimitry Andric }
96