43 #define DEBUG_TYPE "wasm-cfg-stackify"
47 StringRef getPassName()
const override {
return "WebAssembly CFG Stackify"; }
68 return new WebAssemblyCFGStackify();
84 bool AnyBarrier =
false;
86 bool AllAnalyzable =
true;
89 AnyBarrier |= Term.isBarrier();
91 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch();
93 assert((AnyBarrier || AllAnalyzable) &&
94 "AnalyzeBranch needs to analyze any block with a fallthrough");
101 struct CompareBlockNumbers {
108 struct CompareBlockNumbersBackwards {
118 unsigned NumBlocksLeft;
122 std::vector<MachineBasicBlock *> Deferred;
125 :
Loop(L), NumBlocksLeft(L->getNumBlocks()) {}
160 CompareBlockNumbersBackwards>
173 for (Entry &
E : Loops)
174 if (
E.Loop->contains(
MBB) && --
E.NumBlocksLeft == 0)
175 for (
auto DeferredBlock :
E.Deferred)
176 Ready.push(DeferredBlock);
177 while (!Loops.empty() && Loops.back().NumBlocksLeft == 0)
184 if (SuccL->getHeader() == Succ && SuccL->contains(
MBB))
187 if (--NumPredsLeft[Succ->getNumber()] == 0)
188 Preferred.push(Succ);
193 while (!Preferred.empty()) {
194 Next = Preferred.top();
198 if (!Loops.
empty() &&
200 Loops.
back().Deferred.push_back(Next);
228 if (!Loops.
empty() &&
230 Loops.
back().Deferred.push_back(Next);
241 assert(Loops.
empty() &&
"Active loop list not finished");
252 for (
auto &
MBB : MF) {
256 if (Loop && &
MBB == Loop->getHeader()) {
261 (Pred->getNumber() <
MBB.
getNumber() || Loop->contains(Pred)) &&
262 "Loop header predecessors must be loop predecessors or backedges");
263 assert(OnStack.
insert(Loop) &&
"Loops should be declared at most once.");
268 "Non-loop-header predecessors should be topologically sorted");
270 "Blocks must be nested in their loops");
276 "The function entry block shouldn't actually be a loop header");
278 "Control flow stack pushes and pops should be balanced.");
291 if (MO.isMBB() && MO.getMBB() ==
MBB)
310 bool IsBranchedTo =
false;
313 if (Pred->getNumber() < MBBNumber) {
323 assert(&MBB != &MF.
front() &&
"Header blocks shouldn't have predecessors");
330 if (ScopeTop->getNumber() > Header->
getNumber()) {
347 InsertPos = Header->
begin();
349 InsertPos->getOpcode() == WebAssembly::END_LOOP)
355 while (InsertPos != Header->
begin() &&
357 std::prev(InsertPos)->getOpcode() != WebAssembly::LOOP &&
359 std::prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP)
365 TII.get(WebAssembly::BLOCK))
369 InsertPos = MBB.
begin();
370 while (InsertPos != MBB.
end() &&
371 InsertPos->getOpcode() == WebAssembly::END_LOOP &&
372 LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->
getNumber())
376 BlockTops[
End] = Begin;
380 if (!ScopeTops[Number] ||
381 ScopeTops[Number]->getNumber() > Header->
getNumber())
382 ScopeTops[Number] = Header;
399 if (Iter == MF.
end()) {
410 auto InsertPos = MBB.
begin();
411 while (InsertPos != MBB.
end() &&
412 InsertPos->getOpcode() == WebAssembly::END_LOOP)
415 TII.get(WebAssembly::LOOP))
420 TII.get(WebAssembly::END_LOOP));
421 LoopTops[
End] = Begin;
425 "With block sorting the outermost loop for a block should be first.");
439 assert(Depth < Stack.
size() &&
"Branch destination should be in scope");
475 if (
MI.isPosition() ||
MI.isDebugValue())
478 BlockTops[&
MI]->getOperand(0).setImm(int32_t(retType));
481 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
482 LoopTops[&
MI]->getOperand(0).setImm(int32_t(retType));
509 for (
auto &
MBB : MF) {
521 switch (
MI.getOpcode()) {
522 case WebAssembly::BLOCK:
524 "Block should be balanced");
527 case WebAssembly::LOOP:
528 assert(Stack.
back() == &
MBB &&
"Loop top should be balanced");
534 case WebAssembly::END_LOOP:
538 if (
MI.isTerminator()) {
541 while (
MI.getNumOperands() > 0)
542 MI.RemoveOperand(
MI.getNumOperands() - 1);
543 for (
auto MO : Ops) {
546 MI.addOperand(MF, MO);
553 assert(Stack.
empty() &&
"Control flow should be balanced");
560 bool WebAssemblyCFGStackify::runOnMachineFunction(
MachineFunction &MF) {
561 DEBUG(
dbgs() <<
"********** CFG Stackifying **********\n"
562 "********** Function: "
565 const auto &MLI = getAnalysis<MachineLoopInfo>();
566 auto &MDT = getAnalysis<MachineDominatorTree>();
void push_back(const T &Elt)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_NODISCARD T pop_back_val()
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them...
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
static unsigned GetDepth(const SmallVectorImpl< const MachineBasicBlock * > &Stack, const MachineBasicBlock *MBB)
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void moveAfter(MachineBasicBlock *NewBefore)
static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI, const WebAssemblyInstrInfo &TII, MachineDominatorTree &MDT, WebAssemblyFunctionInfo &MFI)
Insert LOOP and BLOCK markers at appropriate places.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through...
size_type size() const
Determine the number of elements in the SetVector.
BlockT * getHeader() const
iterator_range< succ_iterator > successors()
AnalysisUsage & addRequired()
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator_range< iterator > terminators()
static void FixEndsAtEndOfFunction(MachineFunction &MF, const WebAssemblyFunctionInfo &MFI, DenseMap< const MachineInstr *, MachineInstr * > &BlockTops, DenseMap< const MachineInstr *, MachineInstr * > &LoopTops)
In normal assembly languages, when the end of a function is unreachable, because the function ends in...
ExprType
This is used to indicate block signatures.
void pop_back()
Remove the last element of the SetVector.
LLVM_NODISCARD bool empty() const
static void PlaceBlockMarker(MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl< MachineBasicBlock * > &ScopeTops, DenseMap< const MachineInstr *, MachineInstr * > &BlockTops, DenseMap< const MachineInstr *, MachineInstr * > &LoopTops, const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI, MachineDominatorTree &MDT, WebAssemblyFunctionInfo &MFI)
Insert a BLOCK marker for branches to MBB (if needed).
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
const MachineBasicBlock & front() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
MachineBasicBlock * findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B)
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
iterator_range< block_iterator > blocks() const
This file contains the declaration of the WebAssembly-specific utility functions. ...
MachineLoop * getLoopFor(const MachineBasicBlock *BB) const
Return the innermost loop that BB lives in.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
static const unsigned End
const std::vector< MVT > & getResults() const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
iterator_range< pred_iterator > predecessors()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static void PlaceLoopMarker(MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl< MachineBasicBlock * > &ScopeTops, DenseMap< const MachineInstr *, MachineInstr * > &LoopTops, const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI)
Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
This file declares the WebAssembly-specific subclass of TargetSubtarget.
A SetVector that performs no allocations if smaller than a certain size.
Iterator for intrusive lists based on ilist_node.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineOperand class - Representation of each machine instruction operand.
void updateTerminator()
Update the terminator instructions in block to account for changes to the layout. ...
FunctionPass * createWebAssemblyCFGStackify()
void setPreservesCFG()
This function should be called by the pass, iff they do not:
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Representation of each machine instruction.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Represents a single loop in the control flow graph.
static MachineOperand CreateImm(int64_t Val)
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
This file declares WebAssembly-specific per-machine-function information.
static void MaybeUpdateTerminator(MachineBasicBlock *MBB)
const T & back() const
Return the last element of the SetVector.
static MachineBasicBlock * LoopBottom(const MachineLoop *Loop)
Return the "bottom" block of a loop.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void push_back(MachineBasicBlock *MBB)
static const Function * getParent(const Value *V)
StringRef - Represent a constant reference to a string, i.e.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
unsigned pred_size() const
static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI, const MachineDominatorTree &MDT)
Sort the blocks, taking special care to make sure that loops are not interrupted by blocks not domina...