xref: /aosp_15_r20/external/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //=- WebAssemblyFixIrreducibleControlFlow.cpp - Fix irreducible control flow -//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief This file implements a pass that transforms irreducible control flow
12*9880d681SAndroid Build Coastguard Worker /// into reducible control flow. Irreducible control flow means multiple-entry
13*9880d681SAndroid Build Coastguard Worker /// loops; they appear as CFG cycles that are not recorded in MachineLoopInfo
14*9880d681SAndroid Build Coastguard Worker /// due to being unnatural.
15*9880d681SAndroid Build Coastguard Worker ///
16*9880d681SAndroid Build Coastguard Worker /// Note that LLVM has a generic pass that lowers irreducible control flow, but
17*9880d681SAndroid Build Coastguard Worker /// it linearizes control flow, turning diamonds into two triangles, which is
18*9880d681SAndroid Build Coastguard Worker /// both unnecessary and undesirable for WebAssembly.
19*9880d681SAndroid Build Coastguard Worker ///
20*9880d681SAndroid Build Coastguard Worker /// TODO: The transformation implemented here handles all irreducible control
21*9880d681SAndroid Build Coastguard Worker /// flow, without exponential code-size expansion, though it does so by creating
22*9880d681SAndroid Build Coastguard Worker /// inefficient code in many cases. Ideally, we should add other
23*9880d681SAndroid Build Coastguard Worker /// transformations, including code-duplicating cases, which can be more
24*9880d681SAndroid Build Coastguard Worker /// efficient in common cases, and they can fall back to this conservative
25*9880d681SAndroid Build Coastguard Worker /// implementation as needed.
26*9880d681SAndroid Build Coastguard Worker ///
27*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker #include "WebAssembly.h"
30*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
31*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMachineFunctionInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "WebAssemblySubtarget.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/PriorityQueue.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SCCIterator.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SetVector.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
44*9880d681SAndroid Build Coastguard Worker using namespace llvm;
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "wasm-fix-irreducible-control-flow"
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker namespace {
49*9880d681SAndroid Build Coastguard Worker class WebAssemblyFixIrreducibleControlFlow final : public MachineFunctionPass {
getPassName() const50*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
51*9880d681SAndroid Build Coastguard Worker     return "WebAssembly Fix Irreducible Control Flow";
52*9880d681SAndroid Build Coastguard Worker   }
53*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const54*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
55*9880d681SAndroid Build Coastguard Worker     AU.setPreservesCFG();
56*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineDominatorTree>();
57*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<MachineDominatorTree>();
58*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineLoopInfo>();
59*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<MachineLoopInfo>();
60*9880d681SAndroid Build Coastguard Worker     MachineFunctionPass::getAnalysisUsage(AU);
61*9880d681SAndroid Build Coastguard Worker   }
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   bool VisitLoop(MachineFunction &MF, MachineLoopInfo &MLI, MachineLoop *Loop);
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker public:
68*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid
WebAssemblyFixIrreducibleControlFlow()69*9880d681SAndroid Build Coastguard Worker   WebAssemblyFixIrreducibleControlFlow() : MachineFunctionPass(ID) {}
70*9880d681SAndroid Build Coastguard Worker };
71*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker char WebAssemblyFixIrreducibleControlFlow::ID = 0;
createWebAssemblyFixIrreducibleControlFlow()74*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createWebAssemblyFixIrreducibleControlFlow() {
75*9880d681SAndroid Build Coastguard Worker   return new WebAssemblyFixIrreducibleControlFlow();
76*9880d681SAndroid Build Coastguard Worker }
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker namespace {
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker /// A utility for walking the blocks of a loop, handling a nested inner
81*9880d681SAndroid Build Coastguard Worker /// loop as a monolithic conceptual block.
82*9880d681SAndroid Build Coastguard Worker class MetaBlock {
83*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *Block;
84*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineBasicBlock *, 2> Preds;
85*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineBasicBlock *, 2> Succs;
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker public:
MetaBlock(MachineBasicBlock * MBB)88*9880d681SAndroid Build Coastguard Worker   explicit MetaBlock(MachineBasicBlock *MBB)
89*9880d681SAndroid Build Coastguard Worker       : Block(MBB), Preds(MBB->pred_begin(), MBB->pred_end()),
90*9880d681SAndroid Build Coastguard Worker         Succs(MBB->succ_begin(), MBB->succ_end()) {}
91*9880d681SAndroid Build Coastguard Worker 
MetaBlock(MachineLoop * Loop)92*9880d681SAndroid Build Coastguard Worker   explicit MetaBlock(MachineLoop *Loop) : Block(Loop->getHeader()) {
93*9880d681SAndroid Build Coastguard Worker     Loop->getExitBlocks(Succs);
94*9880d681SAndroid Build Coastguard Worker     for (MachineBasicBlock *Pred : Block->predecessors())
95*9880d681SAndroid Build Coastguard Worker       if (!Loop->contains(Pred))
96*9880d681SAndroid Build Coastguard Worker         Preds.push_back(Pred);
97*9880d681SAndroid Build Coastguard Worker   }
98*9880d681SAndroid Build Coastguard Worker 
getBlock() const99*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *getBlock() const { return Block; }
100*9880d681SAndroid Build Coastguard Worker 
predecessors() const101*9880d681SAndroid Build Coastguard Worker   const SmallVectorImpl<MachineBasicBlock *> &predecessors() const {
102*9880d681SAndroid Build Coastguard Worker     return Preds;
103*9880d681SAndroid Build Coastguard Worker   }
successors() const104*9880d681SAndroid Build Coastguard Worker   const SmallVectorImpl<MachineBasicBlock *> &successors() const {
105*9880d681SAndroid Build Coastguard Worker     return Succs;
106*9880d681SAndroid Build Coastguard Worker   }
107*9880d681SAndroid Build Coastguard Worker 
operator ==(const MetaBlock & MBB)108*9880d681SAndroid Build Coastguard Worker   bool operator==(const MetaBlock &MBB) { return Block == MBB.Block; }
operator !=(const MetaBlock & MBB)109*9880d681SAndroid Build Coastguard Worker   bool operator!=(const MetaBlock &MBB) { return Block != MBB.Block; }
110*9880d681SAndroid Build Coastguard Worker };
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker class SuccessorList final : public MetaBlock {
113*9880d681SAndroid Build Coastguard Worker   size_t Index;
114*9880d681SAndroid Build Coastguard Worker   size_t Num;
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker public:
SuccessorList(MachineBasicBlock * MBB)117*9880d681SAndroid Build Coastguard Worker   explicit SuccessorList(MachineBasicBlock *MBB)
118*9880d681SAndroid Build Coastguard Worker       : MetaBlock(MBB), Index(0), Num(successors().size()) {}
119*9880d681SAndroid Build Coastguard Worker 
SuccessorList(MachineLoop * Loop)120*9880d681SAndroid Build Coastguard Worker   explicit SuccessorList(MachineLoop *Loop)
121*9880d681SAndroid Build Coastguard Worker       : MetaBlock(Loop), Index(0), Num(successors().size()) {}
122*9880d681SAndroid Build Coastguard Worker 
HasNext() const123*9880d681SAndroid Build Coastguard Worker   bool HasNext() const { return Index != Num; }
124*9880d681SAndroid Build Coastguard Worker 
Next()125*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *Next() {
126*9880d681SAndroid Build Coastguard Worker     assert(HasNext());
127*9880d681SAndroid Build Coastguard Worker     return successors()[Index++];
128*9880d681SAndroid Build Coastguard Worker   }
129*9880d681SAndroid Build Coastguard Worker };
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
132*9880d681SAndroid Build Coastguard Worker 
VisitLoop(MachineFunction & MF,MachineLoopInfo & MLI,MachineLoop * Loop)133*9880d681SAndroid Build Coastguard Worker bool WebAssemblyFixIrreducibleControlFlow::VisitLoop(MachineFunction &MF,
134*9880d681SAndroid Build Coastguard Worker                                                      MachineLoopInfo &MLI,
135*9880d681SAndroid Build Coastguard Worker                                                      MachineLoop *Loop) {
136*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *Header = Loop ? Loop->getHeader() : &*MF.begin();
137*9880d681SAndroid Build Coastguard Worker   SetVector<MachineBasicBlock *> RewriteSuccs;
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker   // DFS through Loop's body, looking for for irreducible control flow. Loop is
140*9880d681SAndroid Build Coastguard Worker   // natural, and we stay in its body, and we treat any nested loops
141*9880d681SAndroid Build Coastguard Worker   // monolithically, so any cycles we encounter indicate irreducibility.
142*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<MachineBasicBlock *, 8> OnStack;
143*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<MachineBasicBlock *, 8> Visited;
144*9880d681SAndroid Build Coastguard Worker   SmallVector<SuccessorList, 4> LoopWorklist;
145*9880d681SAndroid Build Coastguard Worker   LoopWorklist.push_back(SuccessorList(Header));
146*9880d681SAndroid Build Coastguard Worker   OnStack.insert(Header);
147*9880d681SAndroid Build Coastguard Worker   Visited.insert(Header);
148*9880d681SAndroid Build Coastguard Worker   while (!LoopWorklist.empty()) {
149*9880d681SAndroid Build Coastguard Worker     SuccessorList &Top = LoopWorklist.back();
150*9880d681SAndroid Build Coastguard Worker     if (Top.HasNext()) {
151*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *Next = Top.Next();
152*9880d681SAndroid Build Coastguard Worker       if (Next == Header || (Loop && !Loop->contains(Next)))
153*9880d681SAndroid Build Coastguard Worker         continue;
154*9880d681SAndroid Build Coastguard Worker       if (LLVM_LIKELY(OnStack.insert(Next).second)) {
155*9880d681SAndroid Build Coastguard Worker         if (!Visited.insert(Next).second) {
156*9880d681SAndroid Build Coastguard Worker           OnStack.erase(Next);
157*9880d681SAndroid Build Coastguard Worker           continue;
158*9880d681SAndroid Build Coastguard Worker         }
159*9880d681SAndroid Build Coastguard Worker         MachineLoop *InnerLoop = MLI.getLoopFor(Next);
160*9880d681SAndroid Build Coastguard Worker         if (InnerLoop != Loop)
161*9880d681SAndroid Build Coastguard Worker           LoopWorklist.push_back(SuccessorList(InnerLoop));
162*9880d681SAndroid Build Coastguard Worker         else
163*9880d681SAndroid Build Coastguard Worker           LoopWorklist.push_back(SuccessorList(Next));
164*9880d681SAndroid Build Coastguard Worker       } else {
165*9880d681SAndroid Build Coastguard Worker         RewriteSuccs.insert(Top.getBlock());
166*9880d681SAndroid Build Coastguard Worker       }
167*9880d681SAndroid Build Coastguard Worker       continue;
168*9880d681SAndroid Build Coastguard Worker     }
169*9880d681SAndroid Build Coastguard Worker     OnStack.erase(Top.getBlock());
170*9880d681SAndroid Build Coastguard Worker     LoopWorklist.pop_back();
171*9880d681SAndroid Build Coastguard Worker   }
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   // Most likely, we didn't find any irreducible control flow.
174*9880d681SAndroid Build Coastguard Worker   if (LLVM_LIKELY(RewriteSuccs.empty()))
175*9880d681SAndroid Build Coastguard Worker     return false;
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Irreducible control flow detected!\n");
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker   // Ok. We have irreducible control flow! Create a dispatch block which will
180*9880d681SAndroid Build Coastguard Worker   // contains a jump table to any block in the problematic set of blocks.
181*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *Dispatch = MF.CreateMachineBasicBlock();
182*9880d681SAndroid Build Coastguard Worker   MF.insert(MF.end(), Dispatch);
183*9880d681SAndroid Build Coastguard Worker   MLI.changeLoopFor(Dispatch, Loop);
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   // Add the jump table.
186*9880d681SAndroid Build Coastguard Worker   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
187*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB = BuildMI(*Dispatch, Dispatch->end(), DebugLoc(),
188*9880d681SAndroid Build Coastguard Worker                                     TII.get(WebAssembly::BR_TABLE_I32));
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   // Add the register which will be used to tell the jump table which block to
191*9880d681SAndroid Build Coastguard Worker   // jump to.
192*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI = MF.getRegInfo();
193*9880d681SAndroid Build Coastguard Worker   unsigned Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
194*9880d681SAndroid Build Coastguard Worker   MIB.addReg(Reg);
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker   // Collect all the blocks which need to have their successors rewritten,
197*9880d681SAndroid Build Coastguard Worker   // add the successors to the jump table, and remember their index.
198*9880d681SAndroid Build Coastguard Worker   DenseMap<MachineBasicBlock *, unsigned> Indices;
199*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineBasicBlock *, 4> SuccWorklist(RewriteSuccs.begin(),
200*9880d681SAndroid Build Coastguard Worker                                                    RewriteSuccs.end());
201*9880d681SAndroid Build Coastguard Worker   while (!SuccWorklist.empty()) {
202*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = SuccWorklist.pop_back_val();
203*9880d681SAndroid Build Coastguard Worker     auto Pair = Indices.insert(std::make_pair(MBB, 0));
204*9880d681SAndroid Build Coastguard Worker     if (!Pair.second)
205*9880d681SAndroid Build Coastguard Worker       continue;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker     unsigned Index = MIB.getInstr()->getNumExplicitOperands() - 1;
208*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "MBB#" << MBB->getNumber() << " has index " << Index
209*9880d681SAndroid Build Coastguard Worker                  << "\n");
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker     Pair.first->second = Index;
212*9880d681SAndroid Build Coastguard Worker     for (auto Pred : MBB->predecessors())
213*9880d681SAndroid Build Coastguard Worker       RewriteSuccs.insert(Pred);
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker     MIB.addMBB(MBB);
216*9880d681SAndroid Build Coastguard Worker     Dispatch->addSuccessor(MBB);
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker     MetaBlock Meta(MBB);
219*9880d681SAndroid Build Coastguard Worker     for (auto *Succ : Meta.successors())
220*9880d681SAndroid Build Coastguard Worker       if (Succ != Header && (!Loop || Loop->contains(Succ)))
221*9880d681SAndroid Build Coastguard Worker         SuccWorklist.push_back(Succ);
222*9880d681SAndroid Build Coastguard Worker   }
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker   // Rewrite the problematic successors for every block in RewriteSuccs.
225*9880d681SAndroid Build Coastguard Worker   // For simplicity, we just introduce a new block for every edge we need to
226*9880d681SAndroid Build Coastguard Worker   // rewrite. Fancier things are possible.
227*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock *MBB : RewriteSuccs) {
228*9880d681SAndroid Build Coastguard Worker     DenseMap<MachineBasicBlock *, MachineBasicBlock *> Map;
229*9880d681SAndroid Build Coastguard Worker     for (auto *Succ : MBB->successors()) {
230*9880d681SAndroid Build Coastguard Worker       if (!Indices.count(Succ))
231*9880d681SAndroid Build Coastguard Worker         continue;
232*9880d681SAndroid Build Coastguard Worker 
233*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *Split = MF.CreateMachineBasicBlock();
234*9880d681SAndroid Build Coastguard Worker       MF.insert(MBB->isLayoutSuccessor(Succ) ? MachineFunction::iterator(Succ)
235*9880d681SAndroid Build Coastguard Worker                                              : MF.end(),
236*9880d681SAndroid Build Coastguard Worker                 Split);
237*9880d681SAndroid Build Coastguard Worker       MLI.changeLoopFor(Split, Loop);
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker       // Set the jump table's register of the index of the block we wish to
240*9880d681SAndroid Build Coastguard Worker       // jump to, and jump to the jump table.
241*9880d681SAndroid Build Coastguard Worker       BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::CONST_I32),
242*9880d681SAndroid Build Coastguard Worker               Reg)
243*9880d681SAndroid Build Coastguard Worker           .addImm(Indices[Succ]);
244*9880d681SAndroid Build Coastguard Worker       BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::BR))
245*9880d681SAndroid Build Coastguard Worker           .addMBB(Dispatch);
246*9880d681SAndroid Build Coastguard Worker       Split->addSuccessor(Dispatch);
247*9880d681SAndroid Build Coastguard Worker       Map[Succ] = Split;
248*9880d681SAndroid Build Coastguard Worker     }
249*9880d681SAndroid Build Coastguard Worker     // Remap the terminator operands and the successor list.
250*9880d681SAndroid Build Coastguard Worker     for (MachineInstr &Term : MBB->terminators())
251*9880d681SAndroid Build Coastguard Worker       for (auto &Op : Term.explicit_uses())
252*9880d681SAndroid Build Coastguard Worker         if (Op.isMBB() && Indices.count(Op.getMBB()))
253*9880d681SAndroid Build Coastguard Worker           Op.setMBB(Map[Op.getMBB()]);
254*9880d681SAndroid Build Coastguard Worker     for (auto Rewrite : Map)
255*9880d681SAndroid Build Coastguard Worker       MBB->replaceSuccessor(Rewrite.first, Rewrite.second);
256*9880d681SAndroid Build Coastguard Worker   }
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker   // Create a fake default label, because br_table requires one.
259*9880d681SAndroid Build Coastguard Worker   MIB.addMBB(MIB.getInstr()
260*9880d681SAndroid Build Coastguard Worker                  ->getOperand(MIB.getInstr()->getNumExplicitOperands() - 1)
261*9880d681SAndroid Build Coastguard Worker                  .getMBB());
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker   return true;
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)266*9880d681SAndroid Build Coastguard Worker bool WebAssemblyFixIrreducibleControlFlow::runOnMachineFunction(
267*9880d681SAndroid Build Coastguard Worker     MachineFunction &MF) {
268*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "********** Fixing Irreducible Control Flow **********\n"
269*9880d681SAndroid Build Coastguard Worker                   "********** Function: "
270*9880d681SAndroid Build Coastguard Worker                << MF.getName() << '\n');
271*9880d681SAndroid Build Coastguard Worker 
272*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
273*9880d681SAndroid Build Coastguard Worker   auto &MLI = getAnalysis<MachineLoopInfo>();
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker   // Visit the function body, which is identified as a null loop.
276*9880d681SAndroid Build Coastguard Worker   Changed |= VisitLoop(MF, MLI, nullptr);
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   // Visit all the loops.
279*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineLoop *, 8> Worklist(MLI.begin(), MLI.end());
280*9880d681SAndroid Build Coastguard Worker   while (!Worklist.empty()) {
281*9880d681SAndroid Build Coastguard Worker     MachineLoop *CurLoop = Worklist.pop_back_val();
282*9880d681SAndroid Build Coastguard Worker     Worklist.append(CurLoop->begin(), CurLoop->end());
283*9880d681SAndroid Build Coastguard Worker     Changed |= VisitLoop(MF, MLI, CurLoop);
284*9880d681SAndroid Build Coastguard Worker   }
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker   // If we made any changes, completely recompute everything.
287*9880d681SAndroid Build Coastguard Worker   if (LLVM_UNLIKELY(Changed)) {
288*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Recomputing dominators and loops.\n");
289*9880d681SAndroid Build Coastguard Worker     MF.getRegInfo().invalidateLiveness();
290*9880d681SAndroid Build Coastguard Worker     MF.RenumberBlocks();
291*9880d681SAndroid Build Coastguard Worker     getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
292*9880d681SAndroid Build Coastguard Worker     MLI.runOnMachineFunction(MF);
293*9880d681SAndroid Build Coastguard Worker   }
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   return Changed;
296*9880d681SAndroid Build Coastguard Worker }
297