1c58f2166SChandler Carruth //===- IndirectBrExpandPass.cpp - Expand indirectbr to switch -------------===//
2c58f2166SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c58f2166SChandler Carruth //
7c58f2166SChandler Carruth //===----------------------------------------------------------------------===//
8c58f2166SChandler Carruth /// \file
9c58f2166SChandler Carruth ///
10c58f2166SChandler Carruth /// Implements an expansion pass to turn `indirectbr` instructions in the IR
11c58f2166SChandler Carruth /// into `switch` instructions. This works by enumerating the basic blocks in
12c58f2166SChandler Carruth /// a dense range of integers, replacing each `blockaddr` constant with the
13c58f2166SChandler Carruth /// corresponding integer constant, and then building a switch that maps from
14c58f2166SChandler Carruth /// the integers to the actual blocks. All of the indirectbr instructions in the
15c58f2166SChandler Carruth /// function are redirected to this common switch.
16c58f2166SChandler Carruth ///
17c58f2166SChandler Carruth /// While this is generically useful if a target is unable to codegen
18c58f2166SChandler Carruth /// `indirectbr` natively, it is primarily useful when there is some desire to
19c58f2166SChandler Carruth /// get the builtin non-jump-table lowering of a switch even when the input
20c58f2166SChandler Carruth /// source contained an explicit indirect branch construct.
21c58f2166SChandler Carruth ///
22c58f2166SChandler Carruth /// Note that it doesn't make any sense to enable this pass unless a target also
23c58f2166SChandler Carruth /// disables jump-table lowering of switches. Doing that is likely to pessimize
24c58f2166SChandler Carruth /// the code.
25c58f2166SChandler Carruth ///
26c58f2166SChandler Carruth //===----------------------------------------------------------------------===//
27c58f2166SChandler Carruth 
28c58f2166SChandler Carruth #include "llvm/ADT/STLExtras.h"
29c58f2166SChandler Carruth #include "llvm/ADT/Sequence.h"
30c58f2166SChandler Carruth #include "llvm/ADT/SmallVector.h"
317e88942dSRoman Lebedev #include "llvm/Analysis/DomTreeUpdater.h"
32c58f2166SChandler Carruth #include "llvm/CodeGen/TargetPassConfig.h"
33c58f2166SChandler Carruth #include "llvm/CodeGen/TargetSubtargetInfo.h"
34c58f2166SChandler Carruth #include "llvm/IR/BasicBlock.h"
35*989f1c72Sserge-sans-paille #include "llvm/IR/Constants.h"
367e88942dSRoman Lebedev #include "llvm/IR/Dominators.h"
37c58f2166SChandler Carruth #include "llvm/IR/Function.h"
38c58f2166SChandler Carruth #include "llvm/IR/Instructions.h"
3905da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
40c58f2166SChandler Carruth #include "llvm/Pass.h"
41c58f2166SChandler Carruth #include "llvm/Support/ErrorHandling.h"
42c58f2166SChandler Carruth #include "llvm/Target/TargetMachine.h"
43c58f2166SChandler Carruth 
44c58f2166SChandler Carruth using namespace llvm;
45c58f2166SChandler Carruth 
46c58f2166SChandler Carruth #define DEBUG_TYPE "indirectbr-expand"
47c58f2166SChandler Carruth 
48c58f2166SChandler Carruth namespace {
49c58f2166SChandler Carruth 
50c58f2166SChandler Carruth class IndirectBrExpandPass : public FunctionPass {
51c58f2166SChandler Carruth   const TargetLowering *TLI = nullptr;
52c58f2166SChandler Carruth 
53c58f2166SChandler Carruth public:
54c58f2166SChandler Carruth   static char ID; // Pass identification, replacement for typeid
55c58f2166SChandler Carruth 
IndirectBrExpandPass()56c58f2166SChandler Carruth   IndirectBrExpandPass() : FunctionPass(ID) {
57c58f2166SChandler Carruth     initializeIndirectBrExpandPassPass(*PassRegistry::getPassRegistry());
58c58f2166SChandler Carruth   }
59c58f2166SChandler Carruth 
getAnalysisUsage(AnalysisUsage & AU) const607e88942dSRoman Lebedev   void getAnalysisUsage(AnalysisUsage &AU) const override {
617e88942dSRoman Lebedev     AU.addPreserved<DominatorTreeWrapperPass>();
627e88942dSRoman Lebedev   }
637e88942dSRoman Lebedev 
64c58f2166SChandler Carruth   bool runOnFunction(Function &F) override;
65c58f2166SChandler Carruth };
66c58f2166SChandler Carruth 
67c58f2166SChandler Carruth } // end anonymous namespace
68c58f2166SChandler Carruth 
69c58f2166SChandler Carruth char IndirectBrExpandPass::ID = 0;
70c58f2166SChandler Carruth 
717e88942dSRoman Lebedev INITIALIZE_PASS_BEGIN(IndirectBrExpandPass, DEBUG_TYPE,
727e88942dSRoman Lebedev                       "Expand indirectbr instructions", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)737e88942dSRoman Lebedev INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
747e88942dSRoman Lebedev INITIALIZE_PASS_END(IndirectBrExpandPass, DEBUG_TYPE,
75c58f2166SChandler Carruth                     "Expand indirectbr instructions", false, false)
76c58f2166SChandler Carruth 
77c58f2166SChandler Carruth FunctionPass *llvm::createIndirectBrExpandPass() {
78c58f2166SChandler Carruth   return new IndirectBrExpandPass();
79c58f2166SChandler Carruth }
80c58f2166SChandler Carruth 
runOnFunction(Function & F)81c58f2166SChandler Carruth bool IndirectBrExpandPass::runOnFunction(Function &F) {
82c58f2166SChandler Carruth   auto &DL = F.getParent()->getDataLayout();
83c58f2166SChandler Carruth   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
84c58f2166SChandler Carruth   if (!TPC)
85c58f2166SChandler Carruth     return false;
86c58f2166SChandler Carruth 
87c58f2166SChandler Carruth   auto &TM = TPC->getTM<TargetMachine>();
88c58f2166SChandler Carruth   auto &STI = *TM.getSubtargetImpl(F);
89c58f2166SChandler Carruth   if (!STI.enableIndirectBrExpand())
90c58f2166SChandler Carruth     return false;
91c58f2166SChandler Carruth   TLI = STI.getTargetLowering();
92c58f2166SChandler Carruth 
937e88942dSRoman Lebedev   Optional<DomTreeUpdater> DTU;
947e88942dSRoman Lebedev   if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
957e88942dSRoman Lebedev     DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
967e88942dSRoman Lebedev 
97c58f2166SChandler Carruth   SmallVector<IndirectBrInst *, 1> IndirectBrs;
98c58f2166SChandler Carruth 
99c58f2166SChandler Carruth   // Set of all potential successors for indirectbr instructions.
100c58f2166SChandler Carruth   SmallPtrSet<BasicBlock *, 4> IndirectBrSuccs;
101c58f2166SChandler Carruth 
102c58f2166SChandler Carruth   // Build a list of indirectbrs that we want to rewrite.
103c58f2166SChandler Carruth   for (BasicBlock &BB : F)
104c58f2166SChandler Carruth     if (auto *IBr = dyn_cast<IndirectBrInst>(BB.getTerminator())) {
105c58f2166SChandler Carruth       // Handle the degenerate case of no successors by replacing the indirectbr
106c58f2166SChandler Carruth       // with unreachable as there is no successor available.
107c58f2166SChandler Carruth       if (IBr->getNumSuccessors() == 0) {
108c58f2166SChandler Carruth         (void)new UnreachableInst(F.getContext(), IBr);
109c58f2166SChandler Carruth         IBr->eraseFromParent();
110c58f2166SChandler Carruth         continue;
111c58f2166SChandler Carruth       }
112c58f2166SChandler Carruth 
113c58f2166SChandler Carruth       IndirectBrs.push_back(IBr);
114c58f2166SChandler Carruth       for (BasicBlock *SuccBB : IBr->successors())
115c58f2166SChandler Carruth         IndirectBrSuccs.insert(SuccBB);
116c58f2166SChandler Carruth     }
117c58f2166SChandler Carruth 
118c58f2166SChandler Carruth   if (IndirectBrs.empty())
119c58f2166SChandler Carruth     return false;
120c58f2166SChandler Carruth 
121c58f2166SChandler Carruth   // If we need to replace any indirectbrs we need to establish integer
122c58f2166SChandler Carruth   // constants that will correspond to each of the basic blocks in the function
123c58f2166SChandler Carruth   // whose address escapes. We do that here and rewrite all the blockaddress
124c58f2166SChandler Carruth   // constants to just be those integer constants cast to a pointer type.
125c58f2166SChandler Carruth   SmallVector<BasicBlock *, 4> BBs;
126c58f2166SChandler Carruth 
127c58f2166SChandler Carruth   for (BasicBlock &BB : F) {
128c58f2166SChandler Carruth     // Skip blocks that aren't successors to an indirectbr we're going to
129c58f2166SChandler Carruth     // rewrite.
130c58f2166SChandler Carruth     if (!IndirectBrSuccs.count(&BB))
131c58f2166SChandler Carruth       continue;
132c58f2166SChandler Carruth 
133c58f2166SChandler Carruth     auto IsBlockAddressUse = [&](const Use &U) {
134c58f2166SChandler Carruth       return isa<BlockAddress>(U.getUser());
135c58f2166SChandler Carruth     };
136c58f2166SChandler Carruth     auto BlockAddressUseIt = llvm::find_if(BB.uses(), IsBlockAddressUse);
137c58f2166SChandler Carruth     if (BlockAddressUseIt == BB.use_end())
138c58f2166SChandler Carruth       continue;
139c58f2166SChandler Carruth 
140c58f2166SChandler Carruth     assert(std::find_if(std::next(BlockAddressUseIt), BB.use_end(),
141c58f2166SChandler Carruth                         IsBlockAddressUse) == BB.use_end() &&
142c58f2166SChandler Carruth            "There should only ever be a single blockaddress use because it is "
143c58f2166SChandler Carruth            "a constant and should be uniqued.");
144c58f2166SChandler Carruth 
145c58f2166SChandler Carruth     auto *BA = cast<BlockAddress>(BlockAddressUseIt->getUser());
146c58f2166SChandler Carruth 
147c58f2166SChandler Carruth     // Skip if the constant was formed but ended up not being used (due to DCE
148c58f2166SChandler Carruth     // or whatever).
149c58f2166SChandler Carruth     if (!BA->isConstantUsed())
150c58f2166SChandler Carruth       continue;
151c58f2166SChandler Carruth 
152c58f2166SChandler Carruth     // Compute the index we want to use for this basic block. We can't use zero
153c58f2166SChandler Carruth     // because null can be compared with block addresses.
154c58f2166SChandler Carruth     int BBIndex = BBs.size() + 1;
155c58f2166SChandler Carruth     BBs.push_back(&BB);
156c58f2166SChandler Carruth 
157c58f2166SChandler Carruth     auto *ITy = cast<IntegerType>(DL.getIntPtrType(BA->getType()));
158c58f2166SChandler Carruth     ConstantInt *BBIndexC = ConstantInt::get(ITy, BBIndex);
159c58f2166SChandler Carruth 
160c58f2166SChandler Carruth     // Now rewrite the blockaddress to an integer constant based on the index.
161784929d0SCraig Topper     // FIXME: This part doesn't properly recognize other uses of blockaddress
162784929d0SCraig Topper     // expressions, for instance, where they are used to pass labels to
163784929d0SCraig Topper     // asm-goto. This part of the pass needs a rework.
164c58f2166SChandler Carruth     BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(BBIndexC, BA->getType()));
165c58f2166SChandler Carruth   }
166c58f2166SChandler Carruth 
167c58f2166SChandler Carruth   if (BBs.empty()) {
168c58f2166SChandler Carruth     // There are no blocks whose address is taken, so any indirectbr instruction
169c58f2166SChandler Carruth     // cannot get a valid input and we can replace all of them with unreachable.
1707e88942dSRoman Lebedev     SmallVector<DominatorTree::UpdateType, 8> Updates;
1717e88942dSRoman Lebedev     if (DTU)
1727e88942dSRoman Lebedev       Updates.reserve(IndirectBrSuccs.size());
173c58f2166SChandler Carruth     for (auto *IBr : IndirectBrs) {
1747e88942dSRoman Lebedev       if (DTU) {
1757e88942dSRoman Lebedev         for (BasicBlock *SuccBB : IBr->successors())
1767e88942dSRoman Lebedev           Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
1777e88942dSRoman Lebedev       }
178c58f2166SChandler Carruth       (void)new UnreachableInst(F.getContext(), IBr);
179c58f2166SChandler Carruth       IBr->eraseFromParent();
180c58f2166SChandler Carruth     }
1817e88942dSRoman Lebedev     if (DTU) {
1827e88942dSRoman Lebedev       assert(Updates.size() == IndirectBrSuccs.size() &&
1837e88942dSRoman Lebedev              "Got unexpected update count.");
1847e88942dSRoman Lebedev       DTU->applyUpdates(Updates);
1857e88942dSRoman Lebedev     }
186c58f2166SChandler Carruth     return true;
187c58f2166SChandler Carruth   }
188c58f2166SChandler Carruth 
189c58f2166SChandler Carruth   BasicBlock *SwitchBB;
190c58f2166SChandler Carruth   Value *SwitchValue;
191c58f2166SChandler Carruth 
192c58f2166SChandler Carruth   // Compute a common integer type across all the indirectbr instructions.
193c58f2166SChandler Carruth   IntegerType *CommonITy = nullptr;
194c58f2166SChandler Carruth   for (auto *IBr : IndirectBrs) {
195c58f2166SChandler Carruth     auto *ITy =
196c58f2166SChandler Carruth         cast<IntegerType>(DL.getIntPtrType(IBr->getAddress()->getType()));
197c58f2166SChandler Carruth     if (!CommonITy || ITy->getBitWidth() > CommonITy->getBitWidth())
198c58f2166SChandler Carruth       CommonITy = ITy;
199c58f2166SChandler Carruth   }
200c58f2166SChandler Carruth 
201c58f2166SChandler Carruth   auto GetSwitchValue = [DL, CommonITy](IndirectBrInst *IBr) {
202c58f2166SChandler Carruth     return CastInst::CreatePointerCast(
203c58f2166SChandler Carruth         IBr->getAddress(), CommonITy,
204c58f2166SChandler Carruth         Twine(IBr->getAddress()->getName()) + ".switch_cast", IBr);
205c58f2166SChandler Carruth   };
206c58f2166SChandler Carruth 
2077e88942dSRoman Lebedev   SmallVector<DominatorTree::UpdateType, 8> Updates;
2087e88942dSRoman Lebedev 
209c58f2166SChandler Carruth   if (IndirectBrs.size() == 1) {
210c58f2166SChandler Carruth     // If we only have one indirectbr, we can just directly replace it within
211c58f2166SChandler Carruth     // its block.
2127e88942dSRoman Lebedev     IndirectBrInst *IBr = IndirectBrs[0];
2137e88942dSRoman Lebedev     SwitchBB = IBr->getParent();
2147e88942dSRoman Lebedev     SwitchValue = GetSwitchValue(IBr);
2157e88942dSRoman Lebedev     if (DTU) {
2167e88942dSRoman Lebedev       Updates.reserve(IndirectBrSuccs.size());
2177e88942dSRoman Lebedev       for (BasicBlock *SuccBB : IBr->successors())
2187e88942dSRoman Lebedev         Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
2197e88942dSRoman Lebedev       assert(Updates.size() == IndirectBrSuccs.size() &&
2207e88942dSRoman Lebedev              "Got unexpected update count.");
2217e88942dSRoman Lebedev     }
2227e88942dSRoman Lebedev     IBr->eraseFromParent();
223c58f2166SChandler Carruth   } else {
224c58f2166SChandler Carruth     // Otherwise we need to create a new block to hold the switch across BBs,
225c58f2166SChandler Carruth     // jump to that block instead of each indirectbr, and phi together the
226c58f2166SChandler Carruth     // values for the switch.
227c58f2166SChandler Carruth     SwitchBB = BasicBlock::Create(F.getContext(), "switch_bb", &F);
228c58f2166SChandler Carruth     auto *SwitchPN = PHINode::Create(CommonITy, IndirectBrs.size(),
229c58f2166SChandler Carruth                                      "switch_value_phi", SwitchBB);
230c58f2166SChandler Carruth     SwitchValue = SwitchPN;
231c58f2166SChandler Carruth 
232c58f2166SChandler Carruth     // Now replace the indirectbr instructions with direct branches to the
233c58f2166SChandler Carruth     // switch block and fill out the PHI operands.
2347e88942dSRoman Lebedev     if (DTU)
2357e88942dSRoman Lebedev       Updates.reserve(IndirectBrs.size() + 2 * IndirectBrSuccs.size());
236c58f2166SChandler Carruth     for (auto *IBr : IndirectBrs) {
237c58f2166SChandler Carruth       SwitchPN->addIncoming(GetSwitchValue(IBr), IBr->getParent());
238c58f2166SChandler Carruth       BranchInst::Create(SwitchBB, IBr);
2397e88942dSRoman Lebedev       if (DTU) {
2407e88942dSRoman Lebedev         Updates.push_back({DominatorTree::Insert, IBr->getParent(), SwitchBB});
2417e88942dSRoman Lebedev         for (BasicBlock *SuccBB : IBr->successors())
2427e88942dSRoman Lebedev           Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
2437e88942dSRoman Lebedev       }
244c58f2166SChandler Carruth       IBr->eraseFromParent();
245c58f2166SChandler Carruth     }
246c58f2166SChandler Carruth   }
247c58f2166SChandler Carruth 
248c58f2166SChandler Carruth   // Now build the switch in the block. The block will have no terminator
249c58f2166SChandler Carruth   // already.
250c58f2166SChandler Carruth   auto *SI = SwitchInst::Create(SwitchValue, BBs[0], BBs.size(), SwitchBB);
251c58f2166SChandler Carruth 
252c58f2166SChandler Carruth   // Add a case for each block.
253c58f2166SChandler Carruth   for (int i : llvm::seq<int>(1, BBs.size()))
254c58f2166SChandler Carruth     SI->addCase(ConstantInt::get(CommonITy, i + 1), BBs[i]);
255c58f2166SChandler Carruth 
2567e88942dSRoman Lebedev   if (DTU) {
2577e88942dSRoman Lebedev     // If there were multiple indirectbr's, they may have common successors,
2587e88942dSRoman Lebedev     // but in the dominator tree, we only track unique edges.
259297fb664SBjorn Pettersson     SmallPtrSet<BasicBlock *, 8> UniqueSuccessors;
260297fb664SBjorn Pettersson     Updates.reserve(Updates.size() + BBs.size());
261297fb664SBjorn Pettersson     for (BasicBlock *BB : BBs) {
262297fb664SBjorn Pettersson       if (UniqueSuccessors.insert(BB).second)
2637e88942dSRoman Lebedev         Updates.push_back({DominatorTree::Insert, SwitchBB, BB});
264297fb664SBjorn Pettersson     }
2657e88942dSRoman Lebedev     DTU->applyUpdates(Updates);
2667e88942dSRoman Lebedev   }
2677e88942dSRoman Lebedev 
268c58f2166SChandler Carruth   return true;
269c58f2166SChandler Carruth }
270