LLVM: lib/CodeGen/CallBrPrepare.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
52
53using namespace llvm;
54
55#define DEBUG_TYPE "callbr-prepare"
56
63
64namespace {
65
67public:
71 static char ID;
72};
73
74}
75
78 bool Changed = false;
80
83
85
88
89 if (!Changed)
93 return PA;
94}
95
96char CallBrPrepare::ID = 0;
98 false)
102
104
105void CallBrPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
107}
108
112 if (auto *CBR = dyn_cast(BB.getTerminator()))
113 if (!CBR->getType()->isVoidTy() && !CBR->use_empty())
115 return CBRs;
116}
117
119 bool Changed = false;
121 Options.setMergeIdenticalEdges();
122
123
124
125
126
127
128
129
130
132 for (unsigned i = 1, e = CBR->getNumSuccessors(); i != e; ++i)
133 if (CBR->getSuccessor(i) == CBR->getSuccessor(0) ||
134 isCriticalEdge(CBR, i, true))
136 Changed = true;
137 return Changed;
138}
139
141 bool Changed = false;
143 IRBuilder<> Builder(CBRs[0]->getContext());
145 if (!CBR->getNumIndirectDests())
146 continue;
147
149 SSAUpdate.Initialize(CBR->getType(), CBR->getName());
152
153 for (BasicBlock *IndDest : CBR->getIndirectDests()) {
154 if (!Visited.insert(IndDest).second)
155 continue;
158 CBR->getType(), Intrinsic::callbr_landingpad, {CBR});
160 UpdateSSA(DT, CBR, Intrinsic, SSAUpdate);
161 Changed = true;
162 }
163 }
164 return Changed;
165}
166
168 const auto *I = dyn_cast(U.getUser());
169 return I && I->getParent() == BB;
170}
171
172#ifndef NDEBUG
174 const BasicBlock *BB, bool IsDefaultDest) {
175 if (!isa(U.getUser()))
176 return;
177 LLVM_DEBUG(dbgs() << "Use: " << *U.getUser() << ", in block "
178 << cast(U.getUser())->getParent()->getName()
179 << ", is " << (DT.dominates(BB, U) ? "" : "NOT ")
180 << "dominated by " << BB->getName() << " ("
181 << (IsDefaultDest ? "in" : "") << "direct)\n");
182}
183#endif
184
187
190 BasicBlock *LandingPad = Intrinsic->getParent();
191
194 if (!Visited.insert(U).second)
195 continue;
196
197#ifndef NDEBUG
200#endif
201
202
203 if (const auto *II = dyn_cast(U->getUser()))
204 if (II->getIntrinsicID() == Intrinsic::callbr_landingpad)
205 continue;
206
207
208
210 U->set(Intrinsic);
211 continue;
212 }
213
214
215 if (DT.dominates(DefaultDest, *U))
216 continue;
217
219 }
220}
221
222bool CallBrPrepare::runOnFunction(Function &Fn) {
223 bool Changed = false;
225
226 if (CBRs.empty())
227 return Changed;
228
229
230
231
232
233
234
235
237 std::optional LazilyComputedDomTree;
238 if (auto *DTWP = getAnalysisIfAvailable())
239 DT = &DTWP->getDomTree();
240 else {
241 LazilyComputedDomTree.emplace(Fn);
242 DT = &*LazilyComputedDomTree;
243 }
244
246 Changed = true;
247
249 Changed = true;
250
251 return Changed;
252}
static bool InsertIntrinsicCalls(ArrayRef< CallBrInst * > CBRs, DominatorTree &DT)
static bool SplitCriticalEdges(ArrayRef< CallBrInst * > CBRs, DominatorTree &DT)
static bool IsInSameBasicBlock(const Use &U, const BasicBlock *BB)
static void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, SSAUpdater &SSAUpdate)
static void PrintDebugDomInfo(const DominatorTree &DT, const Use &U, const BasicBlock *BB, bool IsDefaultDest)
static SmallVector< CallBrInst *, 2 > FindCallBrs(Function &Fn)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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
PreservedAnalyses run(Function &Fn, FunctionAnalysisManager &FAM)
This class represents a function call, abstracting a target machine's calling convention.
Analysis pass which computes a DominatorTree.
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.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
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...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
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.
FunctionPass * createCallBrPass()
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)
Option class for critical edge splitting.