47#define DEBUG_TYPE "indirectbr-expand"
70char IndirectBrExpandPass::ID = 0;
73 "Expand indirectbr instructions",
false,
false)
79 return new IndirectBrExpandPass();
82bool IndirectBrExpandPass::runOnFunction(
Function &
F) {
83 auto &
DL =
F.getParent()->getDataLayout();
84 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
89 auto &STI = *
TM.getSubtargetImpl(
F);
90 if (!STI.enableIndirectBrExpand())
92 TLI = STI.getTargetLowering();
94 std::optional<DomTreeUpdater> DTU;
95 if (
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
96 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
105 if (
auto *IBr = dyn_cast<IndirectBrInst>(BB.getTerminator())) {
108 if (IBr->getNumSuccessors() == 0) {
116 IndirectBrSuccs.
insert(SuccBB);
119 if (IndirectBrs.
empty())
131 if (!IndirectBrSuccs.
count(&BB))
134 auto IsBlockAddressUse = [&](
const Use &
U) {
135 return isa<BlockAddress>(
U.getUser());
137 auto BlockAddressUseIt =
llvm::find_if(BB.uses(), IsBlockAddressUse);
138 if (BlockAddressUseIt == BB.use_end())
141 assert(std::find_if(std::next(BlockAddressUseIt), BB.use_end(),
142 IsBlockAddressUse) == BB.use_end() &&
143 "There should only ever be a single blockaddress use because it is "
144 "a constant and should be uniqued.");
146 auto *BA = cast<BlockAddress>(BlockAddressUseIt->getUser());
150 if (!BA->isConstantUsed())
155 int BBIndex = BBs.
size() + 1;
158 auto *ITy = cast<IntegerType>(
DL.getIntPtrType(BA->getType()));
174 for (
auto *IBr : IndirectBrs) {
177 Updates.
push_back({DominatorTree::Delete, IBr->getParent(), SuccBB});
184 "Got unexpected update count.");
185 DTU->applyUpdates(Updates);
195 for (
auto *IBr : IndirectBrs) {
197 cast<IntegerType>(
DL.getIntPtrType(IBr->getAddress()->getType()));
198 if (!CommonITy || ITy->getBitWidth() > CommonITy->
getBitWidth())
204 IBr->getAddress(), CommonITy,
205 Twine(IBr->getAddress()->getName()) +
".switch_cast", IBr);
210 if (IndirectBrs.size() == 1) {
215 SwitchValue = GetSwitchValue(IBr);
221 "Got unexpected update count.");
230 "switch_value_phi", SwitchBB);
231 SwitchValue = SwitchPN;
236 Updates.
reserve(IndirectBrs.size() + 2 * IndirectBrSuccs.
size());
237 for (
auto *IBr : IndirectBrs) {
238 SwitchPN->addIncoming(GetSwitchValue(IBr), IBr->
getParent());
254 for (
int i : llvm::seq<int>(1, BBs.
size()))
263 if (UniqueSuccessors.
insert(BB).second)
264 Updates.
push_back({DominatorTree::Insert, SwitchBB, BB});
266 DTU->applyUpdates(Updates);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Expand indirectbr instructions
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
static CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd)
Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction.
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Legacy analysis pass which computes a DominatorTree.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Indirect Branch Instruction.
iterator_range< succ_op_iterator > successors()
const BasicBlock * getParent() const
SymbolTableList< Instruction >::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="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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, Instruction *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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This function has undefined behavior.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createIndirectBrExpandPass()
void initializeIndirectBrExpandPassPass(PassRegistry &)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.