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");
342 for (
auto &
MBB : MF) {
343 assert(
MBB.getNumber() >= 0 &&
"Renumbered blocks should be non-negative.");
344 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
351 for (
auto *Pred :
MBB.predecessors())
354 "Loop header predecessors must be loop predecessors or "
358 for (
auto *Pred :
MBB.predecessors())
359 assert(Pred->getNumber() <
MBB.getNumber() &&
360 "Non-loop-header predecessors should be topologically sorted");
363 "Regions should be declared at most once.");
367 for (
auto *Pred :
MBB.predecessors())
368 assert(Pred->getNumber() <
MBB.getNumber() &&
369 "Non-loop-header predecessors should be topologically sorted");
371 "Blocks must be nested in their regions");
373 while (OnStack.
size() > 1 && &
MBB == SRI.getBottom(OnStack.
back()))
377 "The function entry block shouldn't actually be a region header");
379 "Control flow stack pushes and pops should be balanced.");
385 "********** Function: "
388 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
389 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
390 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")
#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...
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & back() const
Return the last element of the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void pop_back()
Remove the last element of the SetVector.
value_type pop_back_val()
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.
A SetVector that performs no allocations if smaller than a certain size.
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()