38#define DEBUG_TYPE "wasm-cfg-sort"
45 "WebAssembly: Disable EH pad-first sort order. Testing purpose only."),
51 StringRef getPassName()
const override {
return "WebAssembly CFG Sort"; }
53 void getAnalysisUsage(AnalysisUsage &AU)
const override {
59 AU.
addRequired<WebAssemblyExceptionInfoWrapperPass>();
64 bool runOnMachineFunction(MachineFunction &MF)
override;
68 WebAssemblyCFGSortLegacy() : MachineFunctionPass(ID) {}
72char WebAssemblyCFGSortLegacy::ID = 0;
74 "Reorders blocks in topological order",
false,
false)
77 return new WebAssemblyCFGSortLegacy();
82 bool AnyBarrier =
false;
84 bool AllAnalyzable =
true;
87 AnyBarrier |= Term.isBarrier();
89 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch();
91 assert((AnyBarrier || AllAnalyzable) &&
92 "analyzeBranch needs to analyze any block with a fallthrough");
102 MBB->updateTerminator(OriginalSuccessor);
140struct CompareBlockNumbers {
141 bool operator()(
const MachineBasicBlock *
A,
142 const MachineBasicBlock *
B)
const {
144 if (
A->isEHPad() && !
B->isEHPad())
146 if (!
A->isEHPad() &&
B->isEHPad())
150 return A->getNumber() >
B->getNumber();
154struct CompareBlockNumbersBackwards {
155 bool operator()(
const MachineBasicBlock *
A,
156 const MachineBasicBlock *
B)
const {
158 if (
A->isEHPad() && !
B->isEHPad())
160 if (!
A->isEHPad() &&
B->isEHPad())
164 return A->getNumber() <
B->getNumber();
170 const SortRegion *TheRegion;
171 unsigned NumBlocksLeft;
175 std::vector<MachineBasicBlock *> Deferred;
177 explicit Entry(
const SortRegion *R)
178 : 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>
221 SortRegionInfo SRI(MLI, WEI);
224 const SortRegion *R = SRI.getRegionFor(
MBB);
229 if (R->getHeader() ==
MBB)
234 for (Entry &
E : Entries)
235 if (
E.TheRegion->contains(
MBB) && --
E.NumBlocksLeft == 0)
236 for (
auto *DeferredBlock :
E.Deferred)
237 Ready.push(DeferredBlock);
238 while (!Entries.empty() && Entries.back().NumBlocksLeft == 0)
245 if (SuccL->getHeader() == Succ && SuccL->contains(
MBB))
248 if (--NumPredsLeft[Succ->getNumber()] == 0)
249 Preferred.push(Succ);
254 while (!Preferred.empty()) {
255 Next = Preferred.top();
259 if (!Entries.
empty() &&
261 Entries.
back().Deferred.push_back(
Next);
267 if (
Next->getNumber() <
MBB->getNumber() &&
269 (!R || !R->contains(
Next) ||
270 R->getHeader()->getNumber() <
Next->getNumber())) {
290 if (!Entries.
empty() &&
292 Entries.
back().Deferred.push_back(
Next);
303 assert(Entries.
empty() &&
"Active sort region list not finished");
307 for (
auto &
MBB : MF) {
308 assert(
MBB.getNumber() >= 0 &&
"Renumbered blocks should be non-negative.");
309 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
316 for (
auto *Pred :
MBB.predecessors())
319 "Loop header predecessors must be loop predecessors or "
323 for (
auto *Pred :
MBB.predecessors())
324 assert(Pred->getNumber() <
MBB.getNumber() &&
325 "Non-loop-header predecessors should be topologically sorted");
329 for (
auto *Pred :
MBB.predecessors())
330 assert(Pred->getNumber() <
MBB.getNumber() &&
331 "Non-loop-header predecessors should be topologically sorted");
336 for (
auto &
MBB : MF) {
337 const SortRegion *
Region = SRI.getRegionFor(&
MBB);
344 unsigned RegionIdx = 0;
345 for (
auto *
Region : Regions) {
347 "The function entry block shouldn't actually be a region header");
349 auto *Header =
Region->getHeader();
350 auto *Bottom = SRI.getBottom(
Region);
352 assert(Header &&
"Regions must have a header");
353 assert(Bottom &&
"Regions must have a bottom");
355 std::pair<int, int>
Interval = {Header->getNumber(), Bottom->getNumber()};
357 "Region bottoms must be sorted after region headers");
359 RegionIntervals[RegionIdx++] =
Interval;
364 "All blocks within a region must have numbers within the region's "
369 for (
const auto &IntervalA : RegionIntervals) {
370 for (
const auto &IntervalB : RegionIntervals) {
371 auto AContainsB = IntervalA.first <= IntervalB.first &&
372 IntervalA.second >= IntervalB.second;
373 auto BContainsA = IntervalB.first <= IntervalA.first &&
374 IntervalB.second >= IntervalA.second;
375 auto Disjoint = IntervalA.second < IntervalB.first ||
376 IntervalA.first > IntervalB.second;
377 assert((AContainsB || BContainsA || Disjoint) &&
378 "Regions must be fully contained within their parents and not "
379 "overlap their siblings");
388 "********** Function: "
400bool WebAssemblyCFGSortLegacy::runOnMachineFunction(
MachineFunction &MF) {
401 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
402 WebAssemblyExceptionInfo &WEI =
403 getAnalysis<WebAssemblyExceptionInfoWrapperPass>().getWEI();
404 MachineDominatorTree &MDT =
405 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
406 return sortCFG(MF, MLI, WEI, MDT);
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 bool sortCFG(MachineFunction &MF, MachineLoopInfo &MLI, WebAssemblyExceptionInfo &WEI, MachineDominatorTree &MDT)
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.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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:
Represents analyses that only rely on functions' control flow.
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.
Analysis pass which computes a MachineDominatorTree.
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.
Analysis pass that exposes the MachineLoopInfo for a machine function.
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
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.
Represent a constant reference to a string, i.e.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Pass manager infrastructure for declaring and invalidating analyses.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool sortBlocks(Function &F)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
FunctionPass * createWebAssemblyCFGSortLegacyPass()