37#define DEBUG_TYPE "wasm-cfg-sort"
44 "WebAssembly: Disable EH pad-first sort order. Testing purpose only."),
50 StringRef getPassName()
const override {
return "WebAssembly CFG Sort"; }
52 void getAnalysisUsage(AnalysisUsage &AU)
const override {
63 bool runOnMachineFunction(MachineFunction &MF)
override;
67 WebAssemblyCFGSort() : MachineFunctionPass(ID) {}
71char WebAssemblyCFGSort::ID = 0;
73 "Reorders blocks in topological order",
false,
false)
76 return new WebAssemblyCFGSort();
81 bool AnyBarrier =
false;
83 bool AllAnalyzable =
true;
86 AnyBarrier |= Term.isBarrier();
88 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch();
90 assert((AnyBarrier || AllAnalyzable) &&
91 "analyzeBranch needs to analyze any block with a fallthrough");
101 MBB->updateTerminator(OriginalSuccessor);
139struct CompareBlockNumbers {
140 bool operator()(
const MachineBasicBlock *
A,
141 const MachineBasicBlock *
B)
const {
143 if (
A->isEHPad() && !
B->isEHPad())
145 if (!
A->isEHPad() &&
B->isEHPad())
149 return A->getNumber() >
B->getNumber();
153struct CompareBlockNumbersBackwards {
154 bool operator()(
const MachineBasicBlock *
A,
155 const MachineBasicBlock *
B)
const {
157 if (
A->isEHPad() && !
B->isEHPad())
159 if (!
A->isEHPad() &&
B->isEHPad())
163 return A->getNumber() <
B->getNumber();
169 const SortRegion *TheRegion;
170 unsigned NumBlocksLeft;
174 std::vector<MachineBasicBlock *> Deferred;
176 explicit Entry(
const SortRegion *R)
177 : TheRegion(
R), NumBlocksLeft(
R->getNumBlocks()) {}
197 unsigned N =
MBB.pred_size();
199 if (L->getHeader() == &
MBB)
201 if (L->contains(Pred))
203 NumPredsLeft[
MBB.getNumber()] =
N;
218 CompareBlockNumbersBackwards>
222 SortRegionInfo SRI(MLI, WEI);
225 const SortRegion *R = SRI.getRegionFor(
MBB);
230 if (R->getHeader() ==
MBB)
235 for (Entry &
E : Entries)
236 if (
E.TheRegion->contains(
MBB) && --
E.NumBlocksLeft == 0)
237 for (
auto *DeferredBlock :
E.Deferred)
238 Ready.push(DeferredBlock);
239 while (!Entries.empty() && Entries.back().NumBlocksLeft == 0)
246 if (SuccL->getHeader() == Succ && SuccL->contains(
MBB))
249 if (--NumPredsLeft[Succ->getNumber()] == 0) {
261 if (EHInfo && EHInfo->hasUnwindSrcs(Succ)) {
263 EHInfo->getUnwindSrcs(Succ);
264 bool IsDeferred =
false;
265 for (Entry &
E : Entries) {
266 if (UnwindSrcs.
count(
E.TheRegion->getHeader())) {
267 E.Deferred.push_back(Succ);
275 Preferred.push(Succ);
281 while (!Preferred.empty()) {
282 Next = Preferred.top();
286 if (!Entries.
empty() &&
288 Entries.
back().Deferred.push_back(
Next);
294 if (
Next->getNumber() <
MBB->getNumber() &&
296 (!R || !R->contains(
Next) ||
297 R->getHeader()->getNumber() <
Next->getNumber())) {
317 if (!Entries.
empty() &&
319 Entries.
back().Deferred.push_back(
Next);
330 assert(Entries.
empty() &&
"Active sort region list not finished");
335 for (
auto &
MBB : MF) {
336 assert(
MBB.getNumber() >= 0 &&
"Renumbered blocks should be non-negative.");
337 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
344 for (
auto *Pred :
MBB.predecessors())
347 "Loop header predecessors must be loop predecessors or "
351 for (
auto *Pred :
MBB.predecessors())
352 assert(Pred->getNumber() <
MBB.getNumber() &&
353 "Non-loop-header predecessors should be topologically sorted");
357 for (
auto *Pred :
MBB.predecessors())
358 assert(Pred->getNumber() <
MBB.getNumber() &&
359 "Non-loop-header predecessors should be topologically sorted");
364 for (
auto &
MBB : MF) {
365 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
372 unsigned RegionIdx = 0;
373 for (
auto *
Region : Regions) {
375 "The function entry block shouldn't actually be a region header");
377 auto *Header =
Region->getHeader();
378 auto *Bottom = SRI.getBottom(
Region);
380 assert(Header &&
"Regions must have a header");
381 assert(Bottom &&
"Regions must have a bottom");
383 std::pair<int, int>
Interval = {Header->getNumber(), Bottom->getNumber()};
385 "Region bottoms must be sorted after region headers");
387 RegionIntervals[RegionIdx++] =
Interval;
392 "All blocks within a region must have numbers within the region's "
397 for (
const auto &IntervalA : RegionIntervals) {
398 for (
const auto &IntervalB : RegionIntervals) {
399 auto AContainsB = IntervalA.first <= IntervalB.first &&
400 IntervalA.second >= IntervalB.second;
401 auto BContainsA = IntervalB.first <= IntervalA.first &&
402 IntervalB.second >= IntervalA.second;
403 auto Disjoint = IntervalA.second < IntervalB.first ||
404 IntervalA.first > IntervalB.second;
405 assert((AContainsB || BContainsA || Disjoint) &&
406 "Regions must be fully contained within their parents and not "
407 "overlap their siblings");
415 "********** Function: "
418 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
419 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
420 auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::pair< uint64_t, uint64_t > Interval
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the PriorityQueue class.
This file implements a set that has insertion order iteration characteristics.
static void maybeUpdateTerminator(MachineBasicBlock *MBB)
static cl::opt< bool > WasmDisableEHPadSort("wasm-disable-ehpad-sort", cl::ReallyHidden, cl::desc("WebAssembly: Disable EH pad-first sort order. Testing purpose only."), cl::init(false))
This file implements WebAssemblyException information analysis.
This file implements regions used in CFGSort and CFGStackify.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
std::enable_if_t< GraphHasNodeNumbers< T * >, void > updateBlockNumbers()
Update dominator tree after renumbering blocks.
FunctionPass class - This class is used to implement most global optimizations.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const WasmEHFuncInfo * getWasmEHFuncInfo() const
getWasmEHFuncInfo - Return information about how the current function uses Wasm exception handling.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
Representation of each machine instruction.
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...
block_range blocks()
Returns a range view of the basic blocks in the region.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool sortBlocks(Function &F)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Next
FunctionPass * createWebAssemblyCFGSort()