35#define DEBUG_TYPE "wasm-cfg-sort"
42 "WebAssembly: Disable EH pad-first sort order. Testing purpose only."),
48 StringRef getPassName()
const override {
return "WebAssembly CFG Sort"; }
50 void getAnalysisUsage(AnalysisUsage &AU)
const override {
61 bool runOnMachineFunction(MachineFunction &MF)
override;
65 WebAssemblyCFGSort() : MachineFunctionPass(ID) {}
69char WebAssemblyCFGSort::ID = 0;
71 "Reorders blocks in topological order",
false,
false)
74 return new WebAssemblyCFGSort();
79 bool AnyBarrier =
false;
81 bool AllAnalyzable =
true;
84 AnyBarrier |= Term.isBarrier();
86 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch();
88 assert((AnyBarrier || AllAnalyzable) &&
89 "analyzeBranch needs to analyze any block with a fallthrough");
99 MBB->updateTerminator(OriginalSuccessor);
137struct CompareBlockNumbers {
138 bool operator()(
const MachineBasicBlock *
A,
139 const MachineBasicBlock *
B)
const {
141 if (
A->isEHPad() && !
B->isEHPad())
143 if (!
A->isEHPad() &&
B->isEHPad())
147 return A->getNumber() >
B->getNumber();
151struct CompareBlockNumbersBackwards {
152 bool operator()(
const MachineBasicBlock *
A,
153 const MachineBasicBlock *
B)
const {
155 if (
A->isEHPad() && !
B->isEHPad())
157 if (!
A->isEHPad() &&
B->isEHPad())
161 return A->getNumber() <
B->getNumber();
167 const SortRegion *TheRegion;
168 unsigned NumBlocksLeft;
172 std::vector<MachineBasicBlock *> Deferred;
174 explicit Entry(
const SortRegion *R)
175 : TheRegion(
R), NumBlocksLeft(
R->getNumBlocks()) {}
194 unsigned N =
MBB.pred_size();
196 if (L->getHeader() == &
MBB)
198 if (L->contains(Pred))
200 NumPredsLeft[
MBB.getNumber()] =
N;
215 CompareBlockNumbersBackwards>
218 SortRegionInfo SRI(MLI, WEI);
221 const SortRegion *R = SRI.getRegionFor(
MBB);
226 if (R->getHeader() ==
MBB)
231 for (Entry &
E : Entries)
232 if (
E.TheRegion->contains(
MBB) && --
E.NumBlocksLeft == 0)
233 for (
auto *DeferredBlock :
E.Deferred)
234 Ready.push(DeferredBlock);
235 while (!Entries.empty() && Entries.back().NumBlocksLeft == 0)
242 if (SuccL->getHeader() == Succ && SuccL->contains(
MBB))
245 if (--NumPredsLeft[Succ->getNumber()] == 0)
246 Preferred.push(Succ);
251 while (!Preferred.empty()) {
252 Next = Preferred.top();
256 if (!Entries.
empty() &&
258 Entries.
back().Deferred.push_back(
Next);
264 if (
Next->getNumber() <
MBB->getNumber() &&
266 (!R || !R->contains(
Next) ||
267 R->getHeader()->getNumber() <
Next->getNumber())) {
287 if (!Entries.
empty() &&
289 Entries.
back().Deferred.push_back(
Next);
300 assert(Entries.
empty() &&
"Active sort region list not finished");
304 for (
auto &
MBB : MF) {
305 assert(
MBB.getNumber() >= 0 &&
"Renumbered blocks should be non-negative.");
306 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
313 for (
auto *Pred :
MBB.predecessors())
316 "Loop header predecessors must be loop predecessors or "
320 for (
auto *Pred :
MBB.predecessors())
321 assert(Pred->getNumber() <
MBB.getNumber() &&
322 "Non-loop-header predecessors should be topologically sorted");
326 for (
auto *Pred :
MBB.predecessors())
327 assert(Pred->getNumber() <
MBB.getNumber() &&
328 "Non-loop-header predecessors should be topologically sorted");
333 for (
auto &
MBB : MF) {
334 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
341 unsigned RegionIdx = 0;
342 for (
auto *
Region : Regions) {
344 "The function entry block shouldn't actually be a region header");
346 auto *Header =
Region->getHeader();
347 auto *Bottom = SRI.getBottom(
Region);
349 assert(Header &&
"Regions must have a header");
350 assert(Bottom &&
"Regions must have a bottom");
352 std::pair<int, int>
Interval = {Header->getNumber(), Bottom->getNumber()};
354 "Region bottoms must be sorted after region headers");
356 RegionIntervals[RegionIdx++] =
Interval;
361 "All blocks within a region must have numbers within the region's "
366 for (
const auto &IntervalA : RegionIntervals) {
367 for (
const auto &IntervalB : RegionIntervals) {
368 auto AContainsB = IntervalA.first <= IntervalB.first &&
369 IntervalA.second >= IntervalB.second;
370 auto BContainsA = IntervalB.first <= IntervalA.first &&
371 IntervalB.second >= IntervalA.second;
372 auto Disjoint = IntervalA.second < IntervalB.first ||
373 IntervalA.first > IntervalB.second;
374 assert((AContainsB || BContainsA || Disjoint) &&
375 "Regions must be fully contained within their parents and not "
376 "overlap their siblings");
384 "********** Function: "
387 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
388 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
389 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.
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:
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.
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.
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()