LLVM 23.0.0git
IndirectBrExpandPass.cpp
Go to the documentation of this file.
1//===- IndirectBrExpandPass.cpp - Expand indirectbr to switch -------------===//
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/// \file
9///
10/// Implements an expansion pass to turn `indirectbr` instructions in the IR
11/// into `switch` instructions. This works by enumerating the basic blocks in
12/// a dense range of integers, replacing each `blockaddr` constant with the
13/// corresponding integer constant, and then building a switch that maps from
14/// the integers to the actual blocks. All of the indirectbr instructions in the
15/// function are redirected to this common switch.
16///
17/// While this is generically useful if a target is unable to codegen
18/// `indirectbr` natively, it is primarily useful when there is some desire to
19/// get the builtin non-jump-table lowering of a switch even when the input
20/// source contained an explicit indirect branch construct.
21///
22/// Note that it doesn't make any sense to enable this pass unless a target also
23/// disables jump-table lowering of switches. Doing that is likely to pessimize
24/// the code.
25///
26//===----------------------------------------------------------------------===//
27
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/Sequence.h"
35#include "llvm/IR/BasicBlock.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/Dominators.h"
38#include "llvm/IR/Function.h"
41#include "llvm/Pass.h"
44#include <optional>
45
46using namespace llvm;
47
48#define DEBUG_TYPE "indirectbr-expand"
49
50namespace {
51
52class IndirectBrExpandLegacyPass : public FunctionPass {
53public:
54 static char ID; // Pass identification, replacement for typeid
55
56 IndirectBrExpandLegacyPass() : FunctionPass(ID) {}
57
58 void getAnalysisUsage(AnalysisUsage &AU) const override {
60 }
61
62 bool runOnFunction(Function &F) override;
63};
64
65} // end anonymous namespace
66
67static bool runImpl(Function &F, const TargetLowering *TLI,
68 DomTreeUpdater *DTU);
69
72 auto *STI = TM->getSubtargetImpl(F);
73 if (!STI->enableIndirectBrExpand())
75
76 auto *TLI = STI->getTargetLowering();
77 auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
78 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
79
80 bool Changed = runImpl(F, TLI, DT ? &DTU : nullptr);
81 if (!Changed)
85 return PA;
86}
87
88char IndirectBrExpandLegacyPass::ID = 0;
89
90INITIALIZE_PASS_BEGIN(IndirectBrExpandLegacyPass, DEBUG_TYPE,
91 "Expand indirectbr instructions", false, false)
93INITIALIZE_PASS_END(IndirectBrExpandLegacyPass, DEBUG_TYPE,
94 "Expand indirectbr instructions", false, false)
95
97 return new IndirectBrExpandLegacyPass();
98}
99
101 auto &DL = F.getDataLayout();
102
104
105 // Set of all potential successors for indirectbr instructions.
106 SmallPtrSet<BasicBlock *, 4> IndirectBrSuccs;
107
108 // Build a list of indirectbrs that we want to rewrite.
109 for (BasicBlock &BB : F)
110 if (auto *IBr = dyn_cast<IndirectBrInst>(BB.getTerminator())) {
111 // Handle the degenerate case of no successors by replacing the indirectbr
112 // with unreachable as there is no successor available.
113 if (IBr->getNumSuccessors() == 0) {
114 (void)new UnreachableInst(F.getContext(), IBr->getIterator());
115 IBr->eraseFromParent();
116 continue;
117 }
118
119 IndirectBrs.push_back(IBr);
120 IndirectBrSuccs.insert_range(IBr->successors());
121 }
122
123 if (IndirectBrs.empty())
124 return false;
125
126 // If we need to replace any indirectbrs we need to establish integer
127 // constants that will correspond to each of the basic blocks in the function
128 // whose address escapes. We do that here and rewrite all the blockaddress
129 // constants to just be those integer constants cast to a pointer type.
131
132 for (BasicBlock &BB : F) {
133 // Skip blocks that aren't successors to an indirectbr we're going to
134 // rewrite.
135 if (!IndirectBrSuccs.count(&BB))
136 continue;
137
138 auto IsBlockAddressUse = [&](const Use &U) {
139 return isa<BlockAddress>(U.getUser());
140 };
141 auto BlockAddressUseIt = llvm::find_if(BB.uses(), IsBlockAddressUse);
142 if (BlockAddressUseIt == BB.use_end())
143 continue;
144
145 assert(std::none_of(std::next(BlockAddressUseIt), BB.use_end(),
146 IsBlockAddressUse) &&
147 "There should only ever be a single blockaddress use because it is "
148 "a constant and should be uniqued.");
149
150 auto *BA = cast<BlockAddress>(BlockAddressUseIt->getUser());
151
152 // Skip if the constant was formed but ended up not being used (due to DCE
153 // or whatever).
154 if (!BA->isConstantUsed())
155 continue;
156
157 // Compute the index we want to use for this basic block. We can't use zero
158 // because null can be compared with block addresses.
159 int BBIndex = BBs.size() + 1;
160 BBs.push_back(&BB);
161
162 auto *ITy = cast<IntegerType>(DL.getIntPtrType(BA->getType()));
163 ConstantInt *BBIndexC = ConstantInt::get(ITy, BBIndex);
164
165 // Now rewrite the blockaddress to an integer constant based on the index.
166 // FIXME: This part doesn't properly recognize other uses of blockaddress
167 // expressions, for instance, where they are used to pass labels to
168 // asm-goto. This part of the pass needs a rework.
169 BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(BBIndexC, BA->getType()));
170 }
171
172 if (BBs.empty()) {
173 // There are no blocks whose address is taken, so any indirectbr instruction
174 // cannot get a valid input and we can replace all of them with unreachable.
176 if (DTU)
177 Updates.reserve(IndirectBrSuccs.size());
178 for (auto *IBr : IndirectBrs) {
179 if (DTU) {
180 for (BasicBlock *SuccBB : IBr->successors())
181 Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
182 }
183 (void)new UnreachableInst(F.getContext(), IBr->getIterator());
184 IBr->eraseFromParent();
185 }
186 if (DTU) {
187 assert(Updates.size() == IndirectBrSuccs.size() &&
188 "Got unexpected update count.");
189 DTU->applyUpdates(Updates);
190 }
191 return true;
192 }
193
194 BasicBlock *SwitchBB;
195 Value *SwitchValue;
196
197 // Compute a common integer type across all the indirectbr instructions.
198 IntegerType *CommonITy = nullptr;
199 for (auto *IBr : IndirectBrs) {
200 auto *ITy =
201 cast<IntegerType>(DL.getIntPtrType(IBr->getAddress()->getType()));
202 if (!CommonITy || ITy->getBitWidth() > CommonITy->getBitWidth())
203 CommonITy = ITy;
204 }
205
206 auto GetSwitchValue = [CommonITy](IndirectBrInst *IBr) {
207 return CastInst::CreatePointerCast(IBr->getAddress(), CommonITy,
208 Twine(IBr->getAddress()->getName()) +
209 ".switch_cast",
210 IBr->getIterator());
211 };
212
214
215 if (IndirectBrs.size() == 1) {
216 // If we only have one indirectbr, we can just directly replace it within
217 // its block.
218 IndirectBrInst *IBr = IndirectBrs[0];
219 SwitchBB = IBr->getParent();
220 SwitchValue = GetSwitchValue(IBr);
221 if (DTU) {
222 Updates.reserve(IndirectBrSuccs.size());
223 for (BasicBlock *SuccBB : IBr->successors())
224 Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
225 assert(Updates.size() == IndirectBrSuccs.size() &&
226 "Got unexpected update count.");
227 }
228 IBr->eraseFromParent();
229 } else {
230 // Otherwise we need to create a new block to hold the switch across BBs,
231 // jump to that block instead of each indirectbr, and phi together the
232 // values for the switch.
233 SwitchBB = BasicBlock::Create(F.getContext(), "switch_bb", &F);
234 auto *SwitchPN = PHINode::Create(CommonITy, IndirectBrs.size(),
235 "switch_value_phi", SwitchBB);
236 SwitchValue = SwitchPN;
237
238 // Now replace the indirectbr instructions with direct branches to the
239 // switch block and fill out the PHI operands.
240 if (DTU)
241 Updates.reserve(IndirectBrs.size() + 2 * IndirectBrSuccs.size());
242 for (auto *IBr : IndirectBrs) {
243 SwitchPN->addIncoming(GetSwitchValue(IBr), IBr->getParent());
244 BranchInst::Create(SwitchBB, IBr->getIterator());
245 if (DTU) {
246 Updates.push_back({DominatorTree::Insert, IBr->getParent(), SwitchBB});
247 for (BasicBlock *SuccBB : IBr->successors())
248 Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
249 }
250 IBr->eraseFromParent();
251 }
252 }
253
254 // Now build the switch in the block. The block will have no terminator
255 // already.
256 auto *SI = SwitchInst::Create(SwitchValue, BBs[0], BBs.size(), SwitchBB);
257
258 // Add a case for each block.
259 for (int i : llvm::seq<int>(1, BBs.size()))
260 SI->addCase(ConstantInt::get(CommonITy, i + 1), BBs[i]);
261
262 if (DTU) {
263 // If there were multiple indirectbr's, they may have common successors,
264 // but in the dominator tree, we only track unique edges.
265 SmallPtrSet<BasicBlock *, 8> UniqueSuccessors;
266 Updates.reserve(Updates.size() + BBs.size());
267 for (BasicBlock *BB : BBs) {
268 if (UniqueSuccessors.insert(BB).second)
269 Updates.push_back({DominatorTree::Insert, SwitchBB, BB});
270 }
271 DTU->applyUpdates(Updates);
272 }
273
274 return true;
275}
276
277bool IndirectBrExpandLegacyPass::runOnFunction(Function &F) {
278 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
279 if (!TPC)
280 return false;
281
282 auto &TM = TPC->getTM<TargetMachine>();
283 auto &STI = *TM.getSubtargetImpl(F);
284 if (!STI.enableIndirectBrExpand())
285 return false;
286 auto *TLI = STI.getTargetLowering();
287
288 std::optional<DomTreeUpdater> DTU;
289 if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
290 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
291
292 return runImpl(F, TLI, DTU ? &*DTU : nullptr);
293}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
#define DEBUG_TYPE
static bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU)
#define F(x, y, z)
Definition MD5.cpp:54
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallVector class.
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
Analysis pass which computes a DominatorTree.
Definition Dominators.h:283
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:321
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Indirect Branch Instruction.
iterator_range< succ_op_iterator > successors()
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
size_type size() const
Definition SmallPtrSet.h:99
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static SwitchInst * Create(Value *Value, BasicBlock *Default, unsigned NumCases, InsertPosition InsertBefore=nullptr)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This function has undefined behavior.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
LLVM_ABI FunctionPass * createIndirectBrExpandPass()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1770
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:305
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.