13ca95b02SDimitry Andric //=- WebAssemblyFixIrreducibleControlFlow.cpp - Fix irreducible control flow -//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric // The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric ///
103ca95b02SDimitry Andric /// \file
11*b5893f02SDimitry Andric /// This file implements a pass that transforms irreducible control flow into
12*b5893f02SDimitry Andric /// reducible control flow. Irreducible control flow means multiple-entry
133ca95b02SDimitry Andric /// loops; they appear as CFG cycles that are not recorded in MachineLoopInfo
143ca95b02SDimitry Andric /// due to being unnatural.
153ca95b02SDimitry Andric ///
163ca95b02SDimitry Andric /// Note that LLVM has a generic pass that lowers irreducible control flow, but
173ca95b02SDimitry Andric /// it linearizes control flow, turning diamonds into two triangles, which is
183ca95b02SDimitry Andric /// both unnecessary and undesirable for WebAssembly.
193ca95b02SDimitry Andric ///
20*b5893f02SDimitry Andric /// The big picture: Ignoring natural loops (seeing them monolithically), we
21*b5893f02SDimitry Andric /// find all the blocks which can return to themselves ("loopers"). Loopers
22*b5893f02SDimitry Andric /// reachable from the non-loopers are loop entries: if there are 2 or more,
23*b5893f02SDimitry Andric /// then we have irreducible control flow. We fix that as follows: a new block
24*b5893f02SDimitry Andric /// is created that can dispatch to each of the loop entries, based on the
25*b5893f02SDimitry Andric /// value of a label "helper" variable, and we replace direct branches to the
26*b5893f02SDimitry Andric /// entries with assignments to the label variable and a branch to the dispatch
27*b5893f02SDimitry Andric /// block. Then the dispatch block is the single entry in a new natural loop.
28*b5893f02SDimitry Andric ///
29*b5893f02SDimitry Andric /// This is similar to what the Relooper [1] does, both identify looping code
30*b5893f02SDimitry Andric /// that requires multiple entries, and resolve it in a similar way. In
31*b5893f02SDimitry Andric /// Relooper terminology, we implement a Multiple shape in a Loop shape. Note
32*b5893f02SDimitry Andric /// also that like the Relooper, we implement a "minimal" intervention: we only
33*b5893f02SDimitry Andric /// use the "label" helper for the blocks we absolutely must and no others. We
34*b5893f02SDimitry Andric /// also prioritize code size and do not perform node splitting (i.e. we don't
35*b5893f02SDimitry Andric /// duplicate code in order to resolve irreducibility).
36*b5893f02SDimitry Andric ///
37*b5893f02SDimitry Andric /// The difference between this code and the Relooper is that the Relooper also
38*b5893f02SDimitry Andric /// generates ifs and loops and works in a recursive manner, knowing at each
39*b5893f02SDimitry Andric /// point what the entries are, and recursively breaks down the problem. Here
40*b5893f02SDimitry Andric /// we just want to resolve irreducible control flow, and we also want to use
41*b5893f02SDimitry Andric /// as much LLVM infrastructure as possible. So we use the MachineLoopInfo to
42*b5893f02SDimitry Andric /// identify natural loops, etc., and we start with the whole CFG and must
43*b5893f02SDimitry Andric /// identify both the looping code and its entries.
44*b5893f02SDimitry Andric ///
45*b5893f02SDimitry Andric /// [1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In
46*b5893f02SDimitry Andric /// Proceedings of the ACM international conference companion on Object oriented
47*b5893f02SDimitry Andric /// programming systems languages and applications companion (SPLASH '11). ACM,
48*b5893f02SDimitry Andric /// New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224
49*b5893f02SDimitry Andric /// http://doi.acm.org/10.1145/2048147.2048224
503ca95b02SDimitry Andric ///
513ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
523ca95b02SDimitry Andric
533ca95b02SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
54db17bf38SDimitry Andric #include "WebAssembly.h"
553ca95b02SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
563ca95b02SDimitry Andric #include "WebAssemblySubtarget.h"
573ca95b02SDimitry Andric #include "llvm/ADT/PriorityQueue.h"
583ca95b02SDimitry Andric #include "llvm/ADT/SCCIterator.h"
593ca95b02SDimitry Andric #include "llvm/ADT/SetVector.h"
603ca95b02SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
613ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
623ca95b02SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
633ca95b02SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
643ca95b02SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
653ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h"
663ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
673ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
683ca95b02SDimitry Andric using namespace llvm;
693ca95b02SDimitry Andric
703ca95b02SDimitry Andric #define DEBUG_TYPE "wasm-fix-irreducible-control-flow"
713ca95b02SDimitry Andric
723ca95b02SDimitry Andric namespace {
733ca95b02SDimitry Andric
74*b5893f02SDimitry Andric class LoopFixer {
753ca95b02SDimitry Andric public:
LoopFixer(MachineFunction & MF,MachineLoopInfo & MLI,MachineLoop * Loop)76*b5893f02SDimitry Andric LoopFixer(MachineFunction &MF, MachineLoopInfo &MLI, MachineLoop *Loop)
77*b5893f02SDimitry Andric : MF(MF), MLI(MLI), Loop(Loop) {}
783ca95b02SDimitry Andric
79*b5893f02SDimitry Andric // Run the fixer on the given inputs. Returns whether changes were made.
80*b5893f02SDimitry Andric bool run();
814ba319b5SDimitry Andric
82*b5893f02SDimitry Andric private:
83*b5893f02SDimitry Andric MachineFunction &MF;
84*b5893f02SDimitry Andric MachineLoopInfo &MLI;
85*b5893f02SDimitry Andric MachineLoop *Loop;
863ca95b02SDimitry Andric
87*b5893f02SDimitry Andric MachineBasicBlock *Header;
88*b5893f02SDimitry Andric SmallPtrSet<MachineBasicBlock *, 4> LoopBlocks;
893ca95b02SDimitry Andric
90*b5893f02SDimitry Andric using BlockSet = SmallPtrSet<MachineBasicBlock *, 4>;
91*b5893f02SDimitry Andric DenseMap<MachineBasicBlock *, BlockSet> Reachable;
923ca95b02SDimitry Andric
93*b5893f02SDimitry Andric // The worklist contains pairs of recent additions, (a, b), where we just
94*b5893f02SDimitry Andric // added a link a => b.
95*b5893f02SDimitry Andric using BlockPair = std::pair<MachineBasicBlock *, MachineBasicBlock *>;
96*b5893f02SDimitry Andric SmallVector<BlockPair, 4> WorkList;
973ca95b02SDimitry Andric
98*b5893f02SDimitry Andric // Get a canonical block to represent a block or a loop: the block, or if in
99*b5893f02SDimitry Andric // an inner loop, the loop header, of it in an outer loop scope, we can
100*b5893f02SDimitry Andric // ignore it. We need to call this on all blocks we work on.
canonicalize(MachineBasicBlock * MBB)101*b5893f02SDimitry Andric MachineBasicBlock *canonicalize(MachineBasicBlock *MBB) {
102*b5893f02SDimitry Andric MachineLoop *InnerLoop = MLI.getLoopFor(MBB);
103*b5893f02SDimitry Andric if (InnerLoop == Loop) {
104*b5893f02SDimitry Andric return MBB;
1053ca95b02SDimitry Andric } else {
106*b5893f02SDimitry Andric // This is either in an outer or an inner loop, and not in ours.
107*b5893f02SDimitry Andric if (!LoopBlocks.count(MBB)) {
108*b5893f02SDimitry Andric // It's in outer code, ignore it.
109*b5893f02SDimitry Andric return nullptr;
1103ca95b02SDimitry Andric }
111*b5893f02SDimitry Andric assert(InnerLoop);
112*b5893f02SDimitry Andric // It's in an inner loop, canonicalize it to the header of that loop.
113*b5893f02SDimitry Andric return InnerLoop->getHeader();
1143ca95b02SDimitry Andric }
1153ca95b02SDimitry Andric }
1163ca95b02SDimitry Andric
117*b5893f02SDimitry Andric // For a successor we can additionally ignore it if it's a branch back to a
118*b5893f02SDimitry Andric // natural loop top, as when we are in the scope of a loop, we just care
119*b5893f02SDimitry Andric // about internal irreducibility, and can ignore the loop we are in. We need
120*b5893f02SDimitry Andric // to call this on all blocks in a context where they are a successor.
canonicalizeSuccessor(MachineBasicBlock * MBB)121*b5893f02SDimitry Andric MachineBasicBlock *canonicalizeSuccessor(MachineBasicBlock *MBB) {
122*b5893f02SDimitry Andric if (Loop && MBB == Loop->getHeader()) {
123*b5893f02SDimitry Andric // Ignore branches going to the loop's natural header.
124*b5893f02SDimitry Andric return nullptr;
125*b5893f02SDimitry Andric }
126*b5893f02SDimitry Andric return canonicalize(MBB);
127*b5893f02SDimitry Andric }
128*b5893f02SDimitry Andric
129*b5893f02SDimitry Andric // Potentially insert a new reachable edge, and if so, note it as further
130*b5893f02SDimitry Andric // work.
maybeInsert(MachineBasicBlock * MBB,MachineBasicBlock * Succ)131*b5893f02SDimitry Andric void maybeInsert(MachineBasicBlock *MBB, MachineBasicBlock *Succ) {
132*b5893f02SDimitry Andric assert(MBB == canonicalize(MBB));
133*b5893f02SDimitry Andric assert(Succ);
134*b5893f02SDimitry Andric // Succ may not be interesting as a sucessor.
135*b5893f02SDimitry Andric Succ = canonicalizeSuccessor(Succ);
136*b5893f02SDimitry Andric if (!Succ)
137*b5893f02SDimitry Andric return;
138*b5893f02SDimitry Andric if (Reachable[MBB].insert(Succ).second) {
139*b5893f02SDimitry Andric // For there to be further work, it means that we have
140*b5893f02SDimitry Andric // X => MBB => Succ
141*b5893f02SDimitry Andric // for some other X, and in that case X => Succ would be a new edge for
142*b5893f02SDimitry Andric // us to discover later. However, if we don't care about MBB as a
143*b5893f02SDimitry Andric // successor, then we don't care about that anyhow.
144*b5893f02SDimitry Andric if (canonicalizeSuccessor(MBB)) {
145*b5893f02SDimitry Andric WorkList.emplace_back(MBB, Succ);
146*b5893f02SDimitry Andric }
147*b5893f02SDimitry Andric }
148*b5893f02SDimitry Andric }
149*b5893f02SDimitry Andric };
150*b5893f02SDimitry Andric
run()151*b5893f02SDimitry Andric bool LoopFixer::run() {
152*b5893f02SDimitry Andric Header = Loop ? Loop->getHeader() : &*MF.begin();
153*b5893f02SDimitry Andric
154*b5893f02SDimitry Andric // Identify all the blocks in this loop scope.
155*b5893f02SDimitry Andric if (Loop) {
156*b5893f02SDimitry Andric for (auto *MBB : Loop->getBlocks()) {
157*b5893f02SDimitry Andric LoopBlocks.insert(MBB);
158*b5893f02SDimitry Andric }
159*b5893f02SDimitry Andric } else {
160*b5893f02SDimitry Andric for (auto &MBB : MF) {
161*b5893f02SDimitry Andric LoopBlocks.insert(&MBB);
162*b5893f02SDimitry Andric }
163*b5893f02SDimitry Andric }
164*b5893f02SDimitry Andric
165*b5893f02SDimitry Andric // Compute which (canonicalized) blocks each block can reach.
166*b5893f02SDimitry Andric
167*b5893f02SDimitry Andric // Add all the initial work.
168*b5893f02SDimitry Andric for (auto *MBB : LoopBlocks) {
169*b5893f02SDimitry Andric MachineLoop *InnerLoop = MLI.getLoopFor(MBB);
170*b5893f02SDimitry Andric
171*b5893f02SDimitry Andric if (InnerLoop == Loop) {
172*b5893f02SDimitry Andric for (auto *Succ : MBB->successors()) {
173*b5893f02SDimitry Andric maybeInsert(MBB, Succ);
174*b5893f02SDimitry Andric }
175*b5893f02SDimitry Andric } else {
176*b5893f02SDimitry Andric // It can't be in an outer loop - we loop on LoopBlocks - and so it must
177*b5893f02SDimitry Andric // be an inner loop.
178*b5893f02SDimitry Andric assert(InnerLoop);
179*b5893f02SDimitry Andric // Check if we are the canonical block for this loop.
180*b5893f02SDimitry Andric if (canonicalize(MBB) != MBB) {
181*b5893f02SDimitry Andric continue;
182*b5893f02SDimitry Andric }
183*b5893f02SDimitry Andric // The successors are those of the loop.
184*b5893f02SDimitry Andric SmallVector<MachineBasicBlock *, 2> ExitBlocks;
185*b5893f02SDimitry Andric InnerLoop->getExitBlocks(ExitBlocks);
186*b5893f02SDimitry Andric for (auto *Succ : ExitBlocks) {
187*b5893f02SDimitry Andric maybeInsert(MBB, Succ);
188*b5893f02SDimitry Andric }
189*b5893f02SDimitry Andric }
190*b5893f02SDimitry Andric }
191*b5893f02SDimitry Andric
192*b5893f02SDimitry Andric // Do work until we are all done.
193*b5893f02SDimitry Andric while (!WorkList.empty()) {
194*b5893f02SDimitry Andric MachineBasicBlock *MBB;
195*b5893f02SDimitry Andric MachineBasicBlock *Succ;
196*b5893f02SDimitry Andric std::tie(MBB, Succ) = WorkList.pop_back_val();
197*b5893f02SDimitry Andric // The worklist item is an edge we just added, so it must have valid blocks
198*b5893f02SDimitry Andric // (and not something canonicalized to nullptr).
199*b5893f02SDimitry Andric assert(MBB);
200*b5893f02SDimitry Andric assert(Succ);
201*b5893f02SDimitry Andric // The successor in that pair must also be a valid successor.
202*b5893f02SDimitry Andric assert(MBB == canonicalizeSuccessor(MBB));
203*b5893f02SDimitry Andric // We recently added MBB => Succ, and that means we may have enabled
204*b5893f02SDimitry Andric // Pred => MBB => Succ. Check all the predecessors. Note that our loop here
205*b5893f02SDimitry Andric // is correct for both a block and a block representing a loop, as the loop
206*b5893f02SDimitry Andric // is natural and so the predecessors are all predecessors of the loop
207*b5893f02SDimitry Andric // header, which is the block we have here.
208*b5893f02SDimitry Andric for (auto *Pred : MBB->predecessors()) {
209*b5893f02SDimitry Andric // Canonicalize, make sure it's relevant, and check it's not the same
210*b5893f02SDimitry Andric // block (an update to the block itself doesn't help compute that same
211*b5893f02SDimitry Andric // block).
212*b5893f02SDimitry Andric Pred = canonicalize(Pred);
213*b5893f02SDimitry Andric if (Pred && Pred != MBB) {
214*b5893f02SDimitry Andric maybeInsert(Pred, Succ);
215*b5893f02SDimitry Andric }
216*b5893f02SDimitry Andric }
217*b5893f02SDimitry Andric }
218*b5893f02SDimitry Andric
219*b5893f02SDimitry Andric // It's now trivial to identify the loopers.
220*b5893f02SDimitry Andric SmallPtrSet<MachineBasicBlock *, 4> Loopers;
221*b5893f02SDimitry Andric for (auto MBB : LoopBlocks) {
222*b5893f02SDimitry Andric if (Reachable[MBB].count(MBB)) {
223*b5893f02SDimitry Andric Loopers.insert(MBB);
224*b5893f02SDimitry Andric }
225*b5893f02SDimitry Andric }
226*b5893f02SDimitry Andric // The header cannot be a looper. At the toplevel, LLVM does not allow the
227*b5893f02SDimitry Andric // entry to be in a loop, and in a natural loop we should ignore the header.
228*b5893f02SDimitry Andric assert(Loopers.count(Header) == 0);
229*b5893f02SDimitry Andric
230*b5893f02SDimitry Andric // Find the entries, loopers reachable from non-loopers.
231*b5893f02SDimitry Andric SmallPtrSet<MachineBasicBlock *, 4> Entries;
232*b5893f02SDimitry Andric SmallVector<MachineBasicBlock *, 4> SortedEntries;
233*b5893f02SDimitry Andric for (auto *Looper : Loopers) {
234*b5893f02SDimitry Andric for (auto *Pred : Looper->predecessors()) {
235*b5893f02SDimitry Andric Pred = canonicalize(Pred);
236*b5893f02SDimitry Andric if (Pred && !Loopers.count(Pred)) {
237*b5893f02SDimitry Andric Entries.insert(Looper);
238*b5893f02SDimitry Andric SortedEntries.push_back(Looper);
239*b5893f02SDimitry Andric break;
240*b5893f02SDimitry Andric }
241*b5893f02SDimitry Andric }
242*b5893f02SDimitry Andric }
243*b5893f02SDimitry Andric
244*b5893f02SDimitry Andric // Check if we found irreducible control flow.
245*b5893f02SDimitry Andric if (LLVM_LIKELY(Entries.size() <= 1))
2463ca95b02SDimitry Andric return false;
2473ca95b02SDimitry Andric
248*b5893f02SDimitry Andric // Sort the entries to ensure a deterministic build.
249*b5893f02SDimitry Andric llvm::sort(SortedEntries,
250*b5893f02SDimitry Andric [&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
251*b5893f02SDimitry Andric auto ANum = A->getNumber();
252*b5893f02SDimitry Andric auto BNum = B->getNumber();
253*b5893f02SDimitry Andric return ANum < BNum;
254*b5893f02SDimitry Andric });
2553ca95b02SDimitry Andric
256*b5893f02SDimitry Andric #ifndef NDEBUG
257*b5893f02SDimitry Andric for (auto Block : SortedEntries)
258*b5893f02SDimitry Andric assert(Block->getNumber() != -1);
259*b5893f02SDimitry Andric if (SortedEntries.size() > 1) {
260*b5893f02SDimitry Andric for (auto I = SortedEntries.begin(), E = SortedEntries.end() - 1;
261*b5893f02SDimitry Andric I != E; ++I) {
262*b5893f02SDimitry Andric auto ANum = (*I)->getNumber();
263*b5893f02SDimitry Andric auto BNum = (*(std::next(I)))->getNumber();
264*b5893f02SDimitry Andric assert(ANum != BNum);
265*b5893f02SDimitry Andric }
266*b5893f02SDimitry Andric }
267*b5893f02SDimitry Andric #endif
268*b5893f02SDimitry Andric
269*b5893f02SDimitry Andric // Create a dispatch block which will contain a jump table to the entries.
2703ca95b02SDimitry Andric MachineBasicBlock *Dispatch = MF.CreateMachineBasicBlock();
2713ca95b02SDimitry Andric MF.insert(MF.end(), Dispatch);
2723ca95b02SDimitry Andric MLI.changeLoopFor(Dispatch, Loop);
2733ca95b02SDimitry Andric
2743ca95b02SDimitry Andric // Add the jump table.
2753ca95b02SDimitry Andric const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2763ca95b02SDimitry Andric MachineInstrBuilder MIB = BuildMI(*Dispatch, Dispatch->end(), DebugLoc(),
2773ca95b02SDimitry Andric TII.get(WebAssembly::BR_TABLE_I32));
2783ca95b02SDimitry Andric
2793ca95b02SDimitry Andric // Add the register which will be used to tell the jump table which block to
2803ca95b02SDimitry Andric // jump to.
2813ca95b02SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
2823ca95b02SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
2833ca95b02SDimitry Andric MIB.addReg(Reg);
2843ca95b02SDimitry Andric
285*b5893f02SDimitry Andric // Compute the indices in the superheader, one for each bad block, and
286*b5893f02SDimitry Andric // add them as successors.
2873ca95b02SDimitry Andric DenseMap<MachineBasicBlock *, unsigned> Indices;
288*b5893f02SDimitry Andric for (auto *MBB : SortedEntries) {
2893ca95b02SDimitry Andric auto Pair = Indices.insert(std::make_pair(MBB, 0));
290*b5893f02SDimitry Andric if (!Pair.second) {
2913ca95b02SDimitry Andric continue;
292*b5893f02SDimitry Andric }
2933ca95b02SDimitry Andric
2943ca95b02SDimitry Andric unsigned Index = MIB.getInstr()->getNumExplicitOperands() - 1;
2953ca95b02SDimitry Andric Pair.first->second = Index;
2963ca95b02SDimitry Andric
2973ca95b02SDimitry Andric MIB.addMBB(MBB);
2983ca95b02SDimitry Andric Dispatch->addSuccessor(MBB);
2993ca95b02SDimitry Andric }
3003ca95b02SDimitry Andric
301*b5893f02SDimitry Andric // Rewrite the problematic successors for every block that wants to reach the
302*b5893f02SDimitry Andric // bad blocks. For simplicity, we just introduce a new block for every edge
303*b5893f02SDimitry Andric // we need to rewrite. (Fancier things are possible.)
304*b5893f02SDimitry Andric
305*b5893f02SDimitry Andric SmallVector<MachineBasicBlock *, 4> AllPreds;
306*b5893f02SDimitry Andric for (auto *MBB : SortedEntries) {
307*b5893f02SDimitry Andric for (auto *Pred : MBB->predecessors()) {
308*b5893f02SDimitry Andric if (Pred != Dispatch) {
309*b5893f02SDimitry Andric AllPreds.push_back(Pred);
310*b5893f02SDimitry Andric }
311*b5893f02SDimitry Andric }
312*b5893f02SDimitry Andric }
313*b5893f02SDimitry Andric
314*b5893f02SDimitry Andric for (MachineBasicBlock *MBB : AllPreds) {
3153ca95b02SDimitry Andric DenseMap<MachineBasicBlock *, MachineBasicBlock *> Map;
3163ca95b02SDimitry Andric for (auto *Succ : MBB->successors()) {
317*b5893f02SDimitry Andric if (!Entries.count(Succ)) {
3183ca95b02SDimitry Andric continue;
319*b5893f02SDimitry Andric }
3203ca95b02SDimitry Andric
321*b5893f02SDimitry Andric // This is a successor we need to rewrite.
3223ca95b02SDimitry Andric MachineBasicBlock *Split = MF.CreateMachineBasicBlock();
3233ca95b02SDimitry Andric MF.insert(MBB->isLayoutSuccessor(Succ) ? MachineFunction::iterator(Succ)
3243ca95b02SDimitry Andric : MF.end(),
3253ca95b02SDimitry Andric Split);
3263ca95b02SDimitry Andric MLI.changeLoopFor(Split, Loop);
3273ca95b02SDimitry Andric
3283ca95b02SDimitry Andric // Set the jump table's register of the index of the block we wish to
3293ca95b02SDimitry Andric // jump to, and jump to the jump table.
3303ca95b02SDimitry Andric BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::CONST_I32),
3313ca95b02SDimitry Andric Reg)
3323ca95b02SDimitry Andric .addImm(Indices[Succ]);
3333ca95b02SDimitry Andric BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::BR))
3343ca95b02SDimitry Andric .addMBB(Dispatch);
3353ca95b02SDimitry Andric Split->addSuccessor(Dispatch);
3363ca95b02SDimitry Andric Map[Succ] = Split;
3373ca95b02SDimitry Andric }
3383ca95b02SDimitry Andric // Remap the terminator operands and the successor list.
3393ca95b02SDimitry Andric for (MachineInstr &Term : MBB->terminators())
3403ca95b02SDimitry Andric for (auto &Op : Term.explicit_uses())
3413ca95b02SDimitry Andric if (Op.isMBB() && Indices.count(Op.getMBB()))
3423ca95b02SDimitry Andric Op.setMBB(Map[Op.getMBB()]);
3433ca95b02SDimitry Andric for (auto Rewrite : Map)
3443ca95b02SDimitry Andric MBB->replaceSuccessor(Rewrite.first, Rewrite.second);
3453ca95b02SDimitry Andric }
3463ca95b02SDimitry Andric
3473ca95b02SDimitry Andric // Create a fake default label, because br_table requires one.
3483ca95b02SDimitry Andric MIB.addMBB(MIB.getInstr()
3493ca95b02SDimitry Andric ->getOperand(MIB.getInstr()->getNumExplicitOperands() - 1)
3503ca95b02SDimitry Andric .getMBB());
3513ca95b02SDimitry Andric
3523ca95b02SDimitry Andric return true;
3533ca95b02SDimitry Andric }
3543ca95b02SDimitry Andric
355*b5893f02SDimitry Andric class WebAssemblyFixIrreducibleControlFlow final : public MachineFunctionPass {
getPassName() const356*b5893f02SDimitry Andric StringRef getPassName() const override {
357*b5893f02SDimitry Andric return "WebAssembly Fix Irreducible Control Flow";
358*b5893f02SDimitry Andric }
359*b5893f02SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const360*b5893f02SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
361*b5893f02SDimitry Andric AU.setPreservesCFG();
362*b5893f02SDimitry Andric AU.addRequired<MachineDominatorTree>();
363*b5893f02SDimitry Andric AU.addPreserved<MachineDominatorTree>();
364*b5893f02SDimitry Andric AU.addRequired<MachineLoopInfo>();
365*b5893f02SDimitry Andric AU.addPreserved<MachineLoopInfo>();
366*b5893f02SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
367*b5893f02SDimitry Andric }
368*b5893f02SDimitry Andric
369*b5893f02SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
370*b5893f02SDimitry Andric
runIteration(MachineFunction & MF,MachineLoopInfo & MLI)371*b5893f02SDimitry Andric bool runIteration(MachineFunction &MF, MachineLoopInfo &MLI) {
372*b5893f02SDimitry Andric // Visit the function body, which is identified as a null loop.
373*b5893f02SDimitry Andric if (LoopFixer(MF, MLI, nullptr).run()) {
374*b5893f02SDimitry Andric return true;
375*b5893f02SDimitry Andric }
376*b5893f02SDimitry Andric
377*b5893f02SDimitry Andric // Visit all the loops.
378*b5893f02SDimitry Andric SmallVector<MachineLoop *, 8> Worklist(MLI.begin(), MLI.end());
379*b5893f02SDimitry Andric while (!Worklist.empty()) {
380*b5893f02SDimitry Andric MachineLoop *Loop = Worklist.pop_back_val();
381*b5893f02SDimitry Andric Worklist.append(Loop->begin(), Loop->end());
382*b5893f02SDimitry Andric if (LoopFixer(MF, MLI, Loop).run()) {
383*b5893f02SDimitry Andric return true;
384*b5893f02SDimitry Andric }
385*b5893f02SDimitry Andric }
386*b5893f02SDimitry Andric
387*b5893f02SDimitry Andric return false;
388*b5893f02SDimitry Andric }
389*b5893f02SDimitry Andric
390*b5893f02SDimitry Andric public:
391*b5893f02SDimitry Andric static char ID; // Pass identification, replacement for typeid
WebAssemblyFixIrreducibleControlFlow()392*b5893f02SDimitry Andric WebAssemblyFixIrreducibleControlFlow() : MachineFunctionPass(ID) {}
393*b5893f02SDimitry Andric };
394*b5893f02SDimitry Andric } // end anonymous namespace
395*b5893f02SDimitry Andric
396*b5893f02SDimitry Andric char WebAssemblyFixIrreducibleControlFlow::ID = 0;
397*b5893f02SDimitry Andric INITIALIZE_PASS(WebAssemblyFixIrreducibleControlFlow, DEBUG_TYPE,
398*b5893f02SDimitry Andric "Removes irreducible control flow", false, false)
399*b5893f02SDimitry Andric
createWebAssemblyFixIrreducibleControlFlow()400*b5893f02SDimitry Andric FunctionPass *llvm::createWebAssemblyFixIrreducibleControlFlow() {
401*b5893f02SDimitry Andric return new WebAssemblyFixIrreducibleControlFlow();
402*b5893f02SDimitry Andric }
403*b5893f02SDimitry Andric
runOnMachineFunction(MachineFunction & MF)4043ca95b02SDimitry Andric bool WebAssemblyFixIrreducibleControlFlow::runOnMachineFunction(
4053ca95b02SDimitry Andric MachineFunction &MF) {
4064ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Fixing Irreducible Control Flow **********\n"
4073ca95b02SDimitry Andric "********** Function: "
4083ca95b02SDimitry Andric << MF.getName() << '\n');
4093ca95b02SDimitry Andric
4103ca95b02SDimitry Andric bool Changed = false;
4113ca95b02SDimitry Andric auto &MLI = getAnalysis<MachineLoopInfo>();
4123ca95b02SDimitry Andric
413*b5893f02SDimitry Andric // When we modify something, bail out and recompute MLI, then start again, as
414*b5893f02SDimitry Andric // we create a new natural loop when we resolve irreducible control flow, and
415*b5893f02SDimitry Andric // other loops may become nested in it, etc. In practice this is not an issue
416*b5893f02SDimitry Andric // because irreducible control flow is rare, only very few cycles are needed
417*b5893f02SDimitry Andric // here.
418*b5893f02SDimitry Andric while (LLVM_UNLIKELY(runIteration(MF, MLI))) {
419*b5893f02SDimitry Andric // We rewrote part of the function; recompute MLI and start again.
420*b5893f02SDimitry Andric LLVM_DEBUG(dbgs() << "Recomputing loops.\n");
4213ca95b02SDimitry Andric MF.getRegInfo().invalidateLiveness();
4223ca95b02SDimitry Andric MF.RenumberBlocks();
4233ca95b02SDimitry Andric getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
4243ca95b02SDimitry Andric MLI.runOnMachineFunction(MF);
425*b5893f02SDimitry Andric Changed = true;
4263ca95b02SDimitry Andric }
4273ca95b02SDimitry Andric
4283ca95b02SDimitry Andric return Changed;
4293ca95b02SDimitry Andric }
430