54#define DEBUG_TYPE "callbrprepare"
74char CallBrPrepare::ID = 0;
81void CallBrPrepare::getAnalysisUsage(
AnalysisUsage &AU)
const {
88 if (
auto *CBR = dyn_cast<CallBrInst>(BB.getTerminator()))
89 if (!CBR->getType()->isVoidTy() && !CBR->use_empty())
98 Options.setMergeIdenticalEdges();
109 for (
unsigned i = 1, e = CBR->getNumSuccessors(); i != e; ++i)
110 if (CBR->getSuccessor(i) == CBR->getSuccessor(0) ||
119 bool Changed =
false;
123 if (!CBR->getNumIndirectDests())
127 SSAUpdate.
Initialize(CBR->getType(), CBR->getName());
131 for (
BasicBlock *IndDest : CBR->getIndirectDests()) {
132 if (!Visited.
insert(IndDest).second)
134 Builder.SetInsertPoint(&*IndDest->begin());
136 CBR->getType(), Intrinsic::callbr_landingpad, {CBR});
138 UpdateSSA(DT, CBR, Intrinsic, SSAUpdate);
146 const auto *
I = dyn_cast<Instruction>(U.getUser());
147 return I &&
I->getParent() == BB;
153 if (!isa<Instruction>(U.getUser()))
156 << cast<Instruction>(U.getUser())->getParent()->getName()
157 <<
", is " << (DT.
dominates(BB, U) ?
"" :
"NOT ")
158 <<
"dominated by " << BB->
getName() <<
" ("
159 << (IsDefaultDest ?
"in" :
"") <<
"direct)\n");
173 if (!Visited.
insert(U).second)
182 if (
const auto *II = dyn_cast<IntrinsicInst>(
U->getUser()))
183 if (II->getIntrinsicID() == Intrinsic::callbr_landingpad)
201bool CallBrPrepare::runOnFunction(
Function &Fn) {
202 bool Changed =
false;
216 std::optional<DominatorTree> LazilyComputedDomTree;
217 if (
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
218 DT = &DTWP->getDomTree();
220 LazilyComputedDomTree.emplace(Fn);
221 DT = &*LazilyComputedDomTree;
224 if (SplitCriticalEdges(CBRs, *DT))
227 if (InsertIntrinsicCalls(CBRs, *DT))
static SmallVector< CallBrInst *, 2 > FindCallBrs(Function &Fn)
static bool IsInSameBasicBlock(const Use &U, const BasicBlock *BB)
static void PrintDebugDomInfo(const DominatorTree &DT, const Use &U, const BasicBlock *BB, bool IsDefaultDest)
Rewrite Partial Register Uses
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
CallBr instruction, tracking function calls that may not return control but instead transfer it to a ...
BasicBlock * getDefaultDest() const
This class represents a function call, abstracting a target machine's calling convention.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Helper class for SSA formation on a set of values defined in multiple blocks.
void RewriteUse(Use &U)
Rewrite a use of the symbolic value.
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
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 push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
BasicBlock * SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If it is known that an edge is critical, SplitKnownCriticalEdge can be called directly,...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
FunctionPass * createCallBrPass()
Option class for critical edge splitting.