1cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===-- Relooper.cpp - Top-level interface for WebAssembly  ----*- C++ -*-===//
2cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
3cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
4cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
5cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
6cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// License. See LICENSE.TXT for details.
7cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//
8cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===---------------------------------------------------------------------===//
9cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
10cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// \file
11cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// \brief This implements the Relooper algorithm. This implementation includes
12cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// optimizations added since the original academic paper [1] was published.
13cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
14cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// [1] Alon Zakai. 2011. Emscripten: an LLVM-to-JavaScript compiler. In
15cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// Proceedings of the ACM international conference companion on Object
16cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// oriented programming systems languages and applications companion
17cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// (SPLASH '11). ACM, New York, NY, USA, 301-312. DOI=10.1145/2048147.2048224
18cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// http://doi.acm.org/10.1145/2048147.2048224
19cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
20cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar//===-------------------------------------------------------------------===//
21cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
22cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "Relooper.h"
23cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "WebAssembly.h"
24cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
25cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h"
26cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/IR/CFG.h"
27cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/IR/Function.h"
28cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/Pass.h"
29cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/Support/CommandLine.h"
30cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/Support/Debug.h"
31cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "llvm/Support/raw_ostream.h"
32cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
33cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <cstring>
34cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <cstdlib>
35cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <functional>
36cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <list>
37cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <stack>
38cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include <string>
39cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
40cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#define DEBUG_TYPE "relooper"
41cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
42cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarusing namespace llvm;
43cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarusing namespace Relooper;
44cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
45cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic cl::opt<int> RelooperSplittingFactor(
46cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    "relooper-splitting-factor",
47cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::desc(
48cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        "How much to discount code size when deciding whether to split a node"),
49cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::init(5));
50cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
51cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic cl::opt<unsigned> RelooperMultipleSwitchThreshold(
52cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    "relooper-multiple-switch-threshold",
53cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::desc(
54cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        "How many entries to allow in a multiple before we use a switch"),
55cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::init(10));
56cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
57cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic cl::opt<unsigned> RelooperNestingLimit(
58cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    "relooper-nesting-limit",
59cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::desc(
60cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        "How much nesting is acceptable"),
61cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    cl::init(20));
62cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
63cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
64cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarnamespace {
65cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
66cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// Implements the relooper algorithm for a function's blocks.
67cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
68cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// Implementation details: The Relooper instance has
69cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// ownership of the blocks and shapes, and frees them when done.
70cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar///
71cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstruct RelooperAlgorithm {
72cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  std::deque<Block *> Blocks;
73cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  std::deque<Shape *> Shapes;
74cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Shape *Root;
75cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  bool MinSize;
76cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  int BlockIdCounter;
77cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  int ShapeIdCounter;
78cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
79cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  RelooperAlgorithm();
80cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  ~RelooperAlgorithm();
81cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
82cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  void AddBlock(Block *New, int Id = -1);
83cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
84cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Calculates the shapes
85cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  void Calculate(Block *Entry);
86cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
87cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Sets us to try to minimize size
88cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  void SetMinSize(bool MinSize_) { MinSize = MinSize_; }
89cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar};
90cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
91cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstruct RelooperAnalysis final : public FunctionPass {
92cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  static char ID;
93cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  RelooperAnalysis() : FunctionPass(ID) {}
94cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  const char *getPassName() const override { return "relooper"; }
95cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  void getAnalysisUsage(AnalysisUsage &AU) const override {
96cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    AU.setPreservesAll();
97cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
98cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  bool runOnFunction(Function &F) override;
99cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar};
100cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
101cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
102cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// RelooperAnalysis
103cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
104cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarchar RelooperAnalysis::ID = 0;
105cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarFunctionPass *llvm::createWebAssemblyRelooper() {
106cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return new RelooperAnalysis();
107cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
108cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
109cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarbool RelooperAnalysis::runOnFunction(Function &F) {
110cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  DEBUG(dbgs() << "Relooping function '" << F.getName() << "'\n");
111cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  RelooperAlgorithm R;
112cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // FIXME: remove duplication between relooper's and LLVM's BBs.
113cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  std::map<const BasicBlock *, Block *> BB2B;
114cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  std::map<const Block *, const BasicBlock *> B2BB;
115cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (const BasicBlock &BB : F) {
116cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // FIXME: getName is wrong here, Code is meant to represent amount of code.
117cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // FIXME: use BranchVarInit for switch.
118cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Block *B = new Block(BB.getName().str().data(), /*BranchVarInit=*/nullptr);
119cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    R.AddBlock(B);
120cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    assert(BB2B.find(&BB) == BB2B.end() && "Inserting the same block twice");
121cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    assert(B2BB.find(B) == B2BB.end() && "Inserting the same block twice");
122cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    BB2B[&BB] = B;
123cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    B2BB[B] = &BB;
124cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
125cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (Block *B : R.Blocks) {
126cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    const BasicBlock *BB = B2BB[B];
127cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    for (const BasicBlock *Successor : successors(BB))
128cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // FIXME: add branch's Condition and Code below.
129cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      B->AddBranchTo(BB2B[Successor], /*Condition=*/nullptr, /*Code=*/nullptr);
130cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
131cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  R.Calculate(BB2B[&F.getEntryBlock()]);
132cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return false; // Analysis passes don't modify anything.
133cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
134cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
135cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Helpers
136cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
137cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainartypedef MapVector<Block *, BlockSet> BlockBlockSetMap;
138cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainartypedef std::list<Block *> BlockList;
139cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
140cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainartemplate <class T, class U>
141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic bool contains(const T &container, const U &contained) {
142cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return container.count(contained);
143cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
144cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
145cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
146cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Branch
147cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
148cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarBranch::Branch(const char *ConditionInit, const char *CodeInit)
149cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    : Ancestor(nullptr), Labeled(true) {
150cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // FIXME: move from char* to LLVM data structures
151cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Condition = ConditionInit ? strdup(ConditionInit) : nullptr;
152cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Code = CodeInit ? strdup(CodeInit) : nullptr;
153cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
154cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
155cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarBranch::~Branch() {
156cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // FIXME: move from char* to LLVM data structures
157cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  free(static_cast<void *>(const_cast<char *>(Condition)));
158cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  free(static_cast<void *>(const_cast<char *>(Code)));
159cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
160cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
161cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Block
162cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
163cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarBlock::Block(const char *CodeInit, const char *BranchVarInit)
164cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    : Parent(nullptr), Id(-1), IsCheckedMultipleEntry(false) {
165cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // FIXME: move from char* to LLVM data structures
166cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Code = strdup(CodeInit);
167cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BranchVar = BranchVarInit ? strdup(BranchVarInit) : nullptr;
168cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
169cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
170cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarBlock::~Block() {
171cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // FIXME: move from char* to LLVM data structures
172cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  free(static_cast<void *>(const_cast<char *>(Code)));
173cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  free(static_cast<void *>(const_cast<char *>(BranchVar)));
174cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
175cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
176cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarvoid Block::AddBranchTo(Block *Target, const char *Condition,
177cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        const char *Code) {
178cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  assert(!contains(BranchesOut, Target) &&
179cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar         "cannot add more than one branch to the same target");
180cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BranchesOut[Target] = make_unique<Branch>(Condition, Code);
181cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
182cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
183cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar// Relooper
184cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
185cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarRelooperAlgorithm::RelooperAlgorithm()
186cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    : Root(nullptr), MinSize(false), BlockIdCounter(1),
187cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      ShapeIdCounter(0) { // block ID 0 is reserved for clearings
188cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
189cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
190cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarRelooperAlgorithm::~RelooperAlgorithm() {
191cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (auto Curr : Blocks)
192cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    delete Curr;
193cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (auto Curr : Shapes)
194cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    delete Curr;
195cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
196cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
197cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarvoid RelooperAlgorithm::AddBlock(Block *New, int Id) {
198cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  New->Id = Id == -1 ? BlockIdCounter++ : Id;
199cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Blocks.push_back(New);
200cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
201cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
202cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstruct RelooperRecursor {
203cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  RelooperAlgorithm *Parent;
204cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  RelooperRecursor(RelooperAlgorithm *ParentInit) : Parent(ParentInit) {}
205cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar};
206cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
207cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarvoid RelooperAlgorithm::Calculate(Block *Entry) {
208cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Scan and optimize the input
209cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  struct PreOptimizer : public RelooperRecursor {
210cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    PreOptimizer(RelooperAlgorithm *Parent) : RelooperRecursor(Parent) {}
211cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    BlockSet Live;
212cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
213cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void FindLive(Block *Root) {
214cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockList ToInvestigate;
215cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      ToInvestigate.push_back(Root);
216cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (!ToInvestigate.empty()) {
217cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *Curr = ToInvestigate.front();
218cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        ToInvestigate.pop_front();
219cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (contains(Live, Curr))
220cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue;
221cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Live.insert(Curr);
222cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Curr->BranchesOut)
223cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          ToInvestigate.push_back(iter.first);
224cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
225cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
226cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
227cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // If a block has multiple entries but no exits, and it is small enough, it
228cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // is useful to split it. A common example is a C++ function where
229cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // everything ends up at a final exit block and does some RAII cleanup.
230cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Without splitting, we will be forced to introduce labelled loops to
231cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // allow reaching the final block
232cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void SplitDeadEnds() {
233cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      unsigned TotalCodeSize = 0;
234cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &Curr : Live) {
235cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        TotalCodeSize += strlen(Curr->Code);
236cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
237cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet Splits;
238cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet Removed;
239cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &Original : Live) {
240cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (Original->BranchesIn.size() <= 1 ||
241cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            !Original->BranchesOut.empty())
242cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue; // only dead ends, for now
243cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (contains(Original->BranchesOut, Original))
244cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue; // cannot split a looping node
245cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (strlen(Original->Code) * (Original->BranchesIn.size() - 1) >
246cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            TotalCodeSize / RelooperSplittingFactor)
247cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue; // if splitting increases raw code size by a significant
248cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    // amount, abort
249cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // Split the node (for simplicity, we replace all the blocks, even
250cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // though we could have reused the original)
251cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        DEBUG(dbgs() << "  Splitting '" << Original->Code << "'\n");
252cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &Prior : Original->BranchesIn) {
253cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Split = new Block(Original->Code, Original->BranchVar);
254cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Parent->AddBlock(Split, Original->Id);
255cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Split->BranchesIn.insert(Prior);
256cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          std::unique_ptr<Branch> Details;
257cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Details.swap(Prior->BranchesOut[Original]);
258cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Prior->BranchesOut[Split] = make_unique<Branch>(Details->Condition,
259cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                                          Details->Code);
260cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (const auto &iter : Original->BranchesOut) {
261cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *Post = iter.first;
262cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Branch *Details = iter.second.get();
263cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Split->BranchesOut[Post] = make_unique<Branch>(Details->Condition,
264cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                                           Details->Code);
265cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Post->BranchesIn.insert(Split);
266cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
267cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Splits.insert(Split);
268cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Removed.insert(Original);
269cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
270cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Original->BranchesOut) {
271cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Post = iter.first;
272cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Post->BranchesIn.remove(Original);
273cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
274cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
275cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Splits)
276cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Live.insert(iter);
277cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Removed)
278cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Live.remove(iter);
279cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
280cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  };
281cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  PreOptimizer Pre(this);
282cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Pre.FindLive(Entry);
283cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
284cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Add incoming branches from live blocks, ignoring dead code
285cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (unsigned i = 0; i < Blocks.size(); i++) {
286cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Block *Curr = Blocks[i];
287cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    if (!contains(Pre.Live, Curr))
288cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      continue;
289cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    for (const auto &iter : Curr->BranchesOut)
290cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      iter.first->BranchesIn.insert(Curr);
291cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
292cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
293cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!MinSize)
294cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Pre.SplitDeadEnds();
295cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
296cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Recursively process the graph
297cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
298cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  struct Analyzer : public RelooperRecursor {
299cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Analyzer(RelooperAlgorithm *Parent) : RelooperRecursor(Parent) {}
300cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
301cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Add a shape to the list of shapes in this Relooper calculation
302cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void Notice(Shape *New) {
303cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      New->Id = Parent->ShapeIdCounter++;
304cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Parent->Shapes.push_back(New);
305cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
306cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
307cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Create a list of entries from a block. If LimitTo is provided, only
308cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // results in that set will appear
309cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void GetBlocksOut(Block *Source, BlockSet &Entries,
310cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      BlockSet *LimitTo = nullptr) {
311cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Source->BranchesOut)
312cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!LimitTo || contains(*LimitTo, iter.first))
313cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Entries.insert(iter.first);
314cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
315cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
316cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Converts/processes all branchings to a specific target
317cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor,
318cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                   BlockSet &From) {
319cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      DEBUG(dbgs() << "  Solipsize '" << Target->Code << "' type " << Type
320cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                   << "\n");
321cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (auto iter = Target->BranchesIn.begin();
322cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar           iter != Target->BranchesIn.end();) {
323cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *Prior = *iter;
324cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!contains(From, Prior)) {
325cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          iter++;
326cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue;
327cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
328cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        std::unique_ptr<Branch> PriorOut;
329cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        PriorOut.swap(Prior->BranchesOut[Target]);
330cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        PriorOut->Ancestor = Ancestor;
331cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        PriorOut->Type = Type;
332cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (MultipleShape *Multiple = dyn_cast<MultipleShape>(Ancestor))
333cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Multiple->Breaks++; // We are breaking out of this Multiple, so need a
334cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                              // loop
335cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        iter++; // carefully increment iter before erasing
336cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Target->BranchesIn.remove(Prior);
337cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Target->ProcessedBranchesIn.insert(Prior);
338cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Prior->ProcessedBranchesOut[Target].swap(PriorOut);
339cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
340cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
341cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
342cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) {
343cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      DEBUG(dbgs() << "  MakeSimple inner block '" << Inner->Code << "'\n");
344cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      SimpleShape *Simple = new SimpleShape;
345cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Notice(Simple);
346cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Simple->Inner = Inner;
347cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Inner->Parent = Simple;
348cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (Blocks.size() > 1) {
349cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Blocks.remove(Inner);
350cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        GetBlocksOut(Inner, NextEntries, &Blocks);
351cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockSet JustInner;
352cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        JustInner.insert(Inner);
353cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : NextEntries)
354cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Solipsize(iter, Branch::Direct, Simple, JustInner);
355cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
356cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return Simple;
357cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
358cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
359cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Shape *MakeLoop(BlockSet &Blocks, BlockSet &Entries,
360cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    BlockSet &NextEntries) {
361cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Find the inner blocks in this loop. Proceed backwards from the entries
362cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // until
363cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // you reach a seen block, collecting as you go.
364cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet InnerBlocks;
365cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet Queue = Entries;
366cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (!Queue.empty()) {
367cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *Curr = *(Queue.begin());
368cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Queue.remove(*Queue.begin());
369cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!contains(InnerBlocks, Curr)) {
370cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // This element is new, mark it as inner and remove from outer
371cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          InnerBlocks.insert(Curr);
372cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Blocks.remove(Curr);
373cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Add the elements prior to it
374cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (const auto &iter : Curr->BranchesIn)
375cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Queue.insert(iter);
376cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
377cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
378cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      assert(!InnerBlocks.empty());
379cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
380cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &Curr : InnerBlocks) {
381cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Curr->BranchesOut) {
382cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Possible = iter.first;
383cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (!contains(InnerBlocks, Possible))
384cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            NextEntries.insert(Possible);
385cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
386cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
387cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
388cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      LoopShape *Loop = new LoopShape();
389cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Notice(Loop);
390cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
391cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Solipsize the loop, replacing with break/continue and marking branches
392cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // as Processed (will not affect later calculations)
393cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // A. Branches to the loop entries become a continue to this shape
394cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Entries)
395cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Solipsize(iter, Branch::Continue, Loop, InnerBlocks);
396cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // B. Branches to outside the loop (a next entry) become breaks on this
397cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // shape
398cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : NextEntries)
399cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Solipsize(iter, Branch::Break, Loop, InnerBlocks);
400cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Finish up
401cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Shape *Inner = Process(InnerBlocks, Entries, nullptr);
402cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Loop->Inner = Inner;
403cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return Loop;
404cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
405cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
406cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // For each entry, find the independent group reachable by it. The
407cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // independent group is the entry itself, plus all the blocks it can
408cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // reach that cannot be directly reached by another entry. Note that we
409cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // ignore directly reaching the entry itself by another entry.
410cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    //   @param Ignore - previous blocks that are irrelevant
411cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void FindIndependentGroups(BlockSet &Entries,
412cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               BlockBlockSetMap &IndependentGroups,
413cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               BlockSet *Ignore = nullptr) {
414cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      typedef std::map<Block *, Block *> BlockBlockMap;
415cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
416cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      struct HelperClass {
417cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockBlockSetMap &IndependentGroups;
418cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockBlockMap Ownership; // For each block, which entry it belongs to.
419cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                 // We have reached it from there.
420cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
421cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        HelperClass(BlockBlockSetMap &IndependentGroupsInit)
422cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            : IndependentGroups(IndependentGroupsInit) {}
423cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        void InvalidateWithChildren(Block *New) {
424cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Being in the list means you need to be invalidated
425cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          BlockList ToInvalidate;
426cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          ToInvalidate.push_back(New);
427cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          while (!ToInvalidate.empty()) {
428cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *Invalidatee = ToInvalidate.front();
429cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            ToInvalidate.pop_front();
430cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *Owner = Ownership[Invalidatee];
431cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // Owner may have been invalidated, do not add to
432cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // IndependentGroups!
433cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (contains(IndependentGroups, Owner))
434cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              IndependentGroups[Owner].remove(Invalidatee);
435cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Ownership[Invalidatee]) { // may have been seen before and
436cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                          // invalidated already
437cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Ownership[Invalidatee] = nullptr;
438cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              for (const auto &iter : Invalidatee->BranchesOut) {
439cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                Block *Target = iter.first;
440cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                BlockBlockMap::iterator Known = Ownership.find(Target);
441cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                if (Known != Ownership.end()) {
442cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Block *TargetOwner = Known->second;
443cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  if (TargetOwner)
444cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    ToInvalidate.push_back(Target);
445cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                }
446cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
447cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
448cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
449cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
450cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      };
451cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      HelperClass Helper(IndependentGroups);
452cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
453cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // We flow out from each of the entries, simultaneously.
454cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // When we reach a new block, we add it as belonging to the one we got to
455cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // it from.
456cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // If we reach a new block that is already marked as belonging to someone,
457cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // it is reachable by two entries and is not valid for any of them.
458cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Remove it and all it can reach that have been visited.
459cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
460cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Being in the queue means we just added this item, and
461cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // we need to add its children
462cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockList Queue;
463cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &Entry : Entries) {
464cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Helper.Ownership[Entry] = Entry;
465cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        IndependentGroups[Entry].insert(Entry);
466cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Queue.push_back(Entry);
467cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
468cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (!Queue.empty()) {
469cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *Curr = Queue.front();
470cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Queue.pop_front();
471cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *Owner = Helper.Ownership[Curr]; // Curr must be in the ownership
472cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                               // map if we are in the queue
473cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!Owner)
474cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue; // we have been invalidated meanwhile after being reached
475cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    // from two entries
476cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // Add all children
477cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Curr->BranchesOut) {
478cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *New = iter.first;
479cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          BlockBlockMap::iterator Known = Helper.Ownership.find(New);
480cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (Known == Helper.Ownership.end()) {
481cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // New node. Add it, and put it in the queue
482cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Helper.Ownership[New] = Owner;
483cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            IndependentGroups[Owner].insert(New);
484cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Queue.push_back(New);
485cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            continue;
486cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
487cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *NewOwner = Known->second;
488cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (!NewOwner)
489cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            continue; // We reached an invalidated node
490cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (NewOwner != Owner)
491cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // Invalidate this and all reachable that we have seen - we reached
492cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // this from two locations
493cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Helper.InvalidateWithChildren(New);
494cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // otherwise, we have the same owner, so do nothing
495cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
496cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
497cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
498cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Having processed all the interesting blocks, we remain with just one
499cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // potential issue:
500cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // If a->b, and a was invalidated, but then b was later reached by
501cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // someone else, we must invalidate b. To check for this, we go over all
502cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // elements in the independent groups, if an element has a parent which
503cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // does *not* have the same owner, we/ must remove it and all its
504cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // children.
505cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
506cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Entries) {
507cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockSet &CurrGroup = IndependentGroups[iter];
508cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockList ToInvalidate;
509cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : CurrGroup) {
510cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Child = iter;
511cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (const auto &iter : Child->BranchesIn) {
512cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *Parent = iter;
513cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Ignore && contains(*Ignore, Parent))
514cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              continue;
515cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Helper.Ownership[Parent] != Helper.Ownership[Child])
516cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              ToInvalidate.push_back(Child);
517cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
518cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
519cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        while (!ToInvalidate.empty()) {
520cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Invalidatee = ToInvalidate.front();
521cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          ToInvalidate.pop_front();
522cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Helper.InvalidateWithChildren(Invalidatee);
523cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
524cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
525cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
526cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Remove empty groups
527cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &iter : Entries)
528cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (IndependentGroups[iter].empty())
529cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          IndependentGroups.erase(iter);
530cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
531cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
532cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Shape *MakeMultiple(BlockSet &Blocks, BlockSet &Entries,
533cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        BlockBlockSetMap &IndependentGroups, Shape *Prev,
534cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        BlockSet &NextEntries) {
535cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      bool Fused = isa<SimpleShape>(Prev);
536cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      MultipleShape *Multiple = new MultipleShape();
537cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Notice(Multiple);
538cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet CurrEntries;
539cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (auto &iter : IndependentGroups) {
540cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Block *CurrEntry = iter.first;
541cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockSet &CurrBlocks = iter.second;
542cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // Create inner block
543cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        CurrEntries.clear();
544cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        CurrEntries.insert(CurrEntry);
545cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &CurrInner : CurrBlocks) {
546cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Remove the block from the remaining blocks
547cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Blocks.remove(CurrInner);
548cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Find new next entries and fix branches to them
549cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (auto iter = CurrInner->BranchesOut.begin();
550cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar               iter != CurrInner->BranchesOut.end();) {
551cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *CurrTarget = iter->first;
552cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            auto Next = iter;
553cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Next++;
554cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (!contains(CurrBlocks, CurrTarget)) {
555cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              NextEntries.insert(CurrTarget);
556cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks);
557cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
558cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            iter = Next; // increment carefully because Solipsize can remove us
559cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
560cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
561cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Multiple->InnerMap[CurrEntry->Id] =
562cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Process(CurrBlocks, CurrEntries, nullptr);
563cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // If we are not fused, then our entries will actually be checked
564cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!Fused)
565cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          CurrEntry->IsCheckedMultipleEntry = true;
566cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
567cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // Add entries not handled as next entries, they are deferred
568cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      for (const auto &Entry : Entries)
569cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!contains(IndependentGroups, Entry))
570cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          NextEntries.insert(Entry);
571cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      // The multiple has been created, we can decide how to implement it
572cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (Multiple->InnerMap.size() >= RelooperMultipleSwitchThreshold) {
573cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Multiple->UseSwitch = true;
574cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Multiple->Breaks++; // switch captures breaks
575cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
576cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return Multiple;
577cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
578cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
579cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Main function.
580cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Process a set of blocks with specified entries, returns a shape
581cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // The Make* functions receive a NextEntries. If they fill it with data,
582cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // those are the entries for the ->Next block on them, and the blocks
583cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // are what remains in Blocks (which Make* modify). In this way
584cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // we avoid recursing on Next (imagine a long chain of Simples, if we
585cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // recursed we could blow the stack).
586cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    Shape *Process(BlockSet &Blocks, BlockSet &InitialEntries, Shape *Prev) {
587cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet *Entries = &InitialEntries;
588cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet TempEntries[2];
589cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      int CurrTempIndex = 0;
590cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet *NextEntries;
591cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Shape *Ret = nullptr;
592cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
593cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      auto Make = [&](Shape *Temp) {
594cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (Prev)
595cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Prev->Next = Temp;
596cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!Ret)
597cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Ret = Temp;
598cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Prev = Temp;
599cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Entries = NextEntries;
600cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      };
601cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
602cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (1) {
603cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        CurrTempIndex = 1 - CurrTempIndex;
604cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        NextEntries = &TempEntries[CurrTempIndex];
605cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        NextEntries->clear();
606cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
607cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (Entries->empty())
608cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          return Ret;
609cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (Entries->size() == 1) {
610cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Block *Curr = *(Entries->begin());
611cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (Curr->BranchesIn.empty()) {
612cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // One entry, no looping ==> Simple
613cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Make(MakeSimple(Blocks, Curr, *NextEntries));
614cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (NextEntries->empty())
615cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              return Ret;
616cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            continue;
617cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
618cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // One entry, looping ==> Loop
619cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          Make(MakeLoop(Blocks, *Entries, *NextEntries));
620cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (NextEntries->empty())
621cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            return Ret;
622cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          continue;
623cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
624cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
625cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // More than one entry, try to eliminate through a Multiple groups of
626cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // independent blocks from an entry/ies. It is important to remove
627cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // through multiples as opposed to looping since the former is more
628cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // performant.
629cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        BlockBlockSetMap IndependentGroups;
630cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FindIndependentGroups(*Entries, IndependentGroups);
631cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
632cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (!IndependentGroups.empty()) {
633cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // We can handle a group in a multiple if its entry cannot be reached
634cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // by another group.
635cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Note that it might be reachable by itself - a loop. But that is
636cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // fine, we will create a loop inside the multiple block (which
637cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // is the performant order to do it).
638cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (auto iter = IndependentGroups.begin();
639cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar               iter != IndependentGroups.end();) {
640cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *Entry = iter->first;
641cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            BlockSet &Group = iter->second;
642cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            auto curr = iter++; // iterate carefully, we may delete
643cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin();
644cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                 iterBranch != Entry->BranchesIn.end(); iterBranch++) {
645cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Block *Origin = *iterBranch;
646cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (!contains(Group, Origin)) {
647cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                // Reached from outside the group, so we cannot handle this
648cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                IndependentGroups.erase(curr);
649cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                break;
650cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
651cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
652cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
653cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
654cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // As an optimization, if we have 2 independent groups, and one is a
655cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // small dead end, we can handle only that dead end.
656cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // The other then becomes a Next - without nesting in the code and
657cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // recursion in the analysis.
658cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // TODO: if the larger is the only dead end, handle that too
659cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // TODO: handle >2 groups
660cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // TODO: handle not just dead ends, but also that do not branch to the
661cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // NextEntries. However, must be careful there since we create a
662cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // Next, and that Next can prevent eliminating a break (since we no
663cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // longer naturally reach the same place), which may necessitate a
664cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // one-time loop, which makes the unnesting pointless.
665cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (IndependentGroups.size() == 2) {
666cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // Find the smaller one
667cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            auto iter = IndependentGroups.begin();
668cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *SmallEntry = iter->first;
669cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            auto SmallSize = iter->second.size();
670cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            iter++;
671cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Block *LargeEntry = iter->first;
672cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            auto LargeSize = iter->second.size();
673cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (SmallSize != LargeSize) { // ignore the case where they are
674cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                          // identical - keep things symmetrical
675cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                          // there
676cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (SmallSize > LargeSize) {
677cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                Block *Temp = SmallEntry;
678cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                SmallEntry = LargeEntry;
679cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                LargeEntry = Temp; // Note: we did not flip the Sizes too, they
680cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                   // are now invalid. TODO: use the smaller
681cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                   // size as a limit?
682cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
683cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              // Check if dead end
684cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              bool DeadEnd = true;
685cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              BlockSet &SmallGroup = IndependentGroups[SmallEntry];
686cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              for (const auto &Curr : SmallGroup) {
687cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                for (const auto &iter : Curr->BranchesOut) {
688cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Block *Target = iter.first;
689cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  if (!contains(SmallGroup, Target)) {
690cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    DeadEnd = false;
691cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    break;
692cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  }
693cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                }
694cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                if (!DeadEnd)
695cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  break;
696cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
697cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (DeadEnd)
698cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                IndependentGroups.erase(LargeEntry);
699cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
700cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
701cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
702cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (!IndependentGroups.empty())
703cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            // Some groups removable ==> Multiple
704cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Make(MakeMultiple(Blocks, *Entries, IndependentGroups, Prev,
705cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                              *NextEntries));
706cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (NextEntries->empty())
707cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              return Ret;
708cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            continue;
709cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
710cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        // No independent groups, must be loopable ==> Loop
711cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Make(MakeLoop(Blocks, *Entries, *NextEntries));
712cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        if (NextEntries->empty())
713cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          return Ret;
714cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        continue;
715cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
716cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
717cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  };
718cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
719cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // Main
720cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
721cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BlockSet AllBlocks;
722cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  for (const auto &Curr : Pre.Live) {
723cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    AllBlocks.insert(Curr);
724cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
725cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
726cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  BlockSet Entries;
727cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Entries.insert(Entry);
728cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  Root = Analyzer(this).Process(AllBlocks, Entries, nullptr);
729cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  assert(Root);
730cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
731cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  ///
732cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  /// Relooper post-optimizer
733cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  ///
734cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  struct PostOptimizer {
735cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    RelooperAlgorithm *Parent;
736cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    std::stack<Shape *> LoopStack;
737cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
738cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    PostOptimizer(RelooperAlgorithm *ParentInit) : Parent(ParentInit) {}
739cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
740cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void ShapeSwitch(Shape* var,
741cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                     std::function<void (SimpleShape*)> simple,
742cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                     std::function<void (MultipleShape*)> multiple,
743cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                     std::function<void (LoopShape*)> loop) {
744cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      switch (var->getKind()) {
745cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        case Shape::SK_Simple: {
746cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          simple(cast<SimpleShape>(var));
747cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          break;
748cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
749cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        case Shape::SK_Multiple: {
750cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          multiple(cast<MultipleShape>(var));
751cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          break;
752cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
753cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        case Shape::SK_Loop: {
754cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          loop(cast<LoopShape>(var));
755cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          break;
756cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
757cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
758cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
759cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
760cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Find the blocks that natural control flow can get us directly to, or
761cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // through a multiple that we ignore
762cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void FollowNaturalFlow(Shape *S, BlockSet &Out) {
763cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      ShapeSwitch(S, [&](SimpleShape* Simple) {
764cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Out.insert(Simple->Inner);
765cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }, [&](MultipleShape* Multiple) {
766cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Multiple->InnerMap) {
767cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          FollowNaturalFlow(iter.second, Out);
768cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
769cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FollowNaturalFlow(Multiple->Next, Out);
770cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }, [&](LoopShape* Loop) {
771cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FollowNaturalFlow(Loop->Inner, Out);
772cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      });
773cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
774cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
775cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void FindNaturals(Shape *Root, Shape *Otherwise = nullptr) {
776cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      if (Root->Next) {
777cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Root->Natural = Root->Next;
778cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FindNaturals(Root->Next, Otherwise);
779cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      } else {
780cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Root->Natural = Otherwise;
781cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
782cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
783cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      ShapeSwitch(Root, [](SimpleShape* Simple) {
784cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }, [&](MultipleShape* Multiple) {
785cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        for (const auto &iter : Multiple->InnerMap) {
786cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          FindNaturals(iter.second, Root->Natural);
787cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        }
788cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }, [&](LoopShape* Loop){
789cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        FindNaturals(Loop->Inner, Loop->Inner);
790cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      });
791cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
792cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
793cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // Remove unneeded breaks and continues.
794cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // A flow operation is trivially unneeded if the shape we naturally get to
795cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // by normal code execution is the same as the flow forces us to.
796cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void RemoveUnneededFlows(Shape *Root, Shape *Natural = nullptr,
797cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                             LoopShape *LastLoop = nullptr,
798cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                             unsigned Depth = 0) {
799cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      BlockSet NaturalBlocks;
800cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      FollowNaturalFlow(Natural, NaturalBlocks);
801cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Shape *Next = Root;
802cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (Next) {
803cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Root = Next;
804cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Next = nullptr;
805cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        ShapeSwitch(
806cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Root,
807cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            [&](SimpleShape* Simple) {
808cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (Simple->Inner->BranchVar)
809cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                LastLoop =
810cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    nullptr; // a switch clears out the loop (TODO: only for
811cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                             // breaks, not continue)
812cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
813cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (Simple->Next) {
814cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                if (!Simple->Inner->BranchVar &&
815cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Simple->Inner->ProcessedBranchesOut.size() == 2 &&
816cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Depth < RelooperNestingLimit) {
817cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // If there is a next block, we already know at Simple
818cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // creation time to make direct branches, and we can do
819cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // nothing more in general. But, we try to optimize the
820cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // case of a break and a direct: This would normally be
821cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  //   if (break?) { break; } ..
822cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // but if we make sure to nest the else, we can save the
823cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // break,
824cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  //   if (!break?) { .. }
825cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // This is also better because the more canonical nested
826cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // form is easier to further optimize later. The
827cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // downside is more nesting, which adds to size in builds with
828cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // whitespace.
829cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // Note that we avoid switches, as it complicates control flow
830cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  // and is not relevant for the common case we optimize here.
831cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  bool Found = false;
832cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  bool Abort = false;
833cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  for (const auto &iter : Simple->Inner->ProcessedBranchesOut) {
834cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Block *Target = iter.first;
835cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Branch *Details = iter.second.get();
836cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    if (Details->Type == Branch::Break) {
837cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      Found = true;
838cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      if (!contains(NaturalBlocks, Target))
839cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        Abort = true;
840cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    } else if (Details->Type != Branch::Direct)
841cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      Abort = true;
842cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  }
843cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  if (Found && !Abort) {
844cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    for (const auto &iter : Simple->Inner->ProcessedBranchesOut) {
845cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      Branch *Details = iter.second.get();
846cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      if (Details->Type == Branch::Break) {
847cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        Details->Type = Branch::Direct;
848cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        if (MultipleShape *Multiple =
849cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                dyn_cast<MultipleShape>(Details->Ancestor))
850cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                          Multiple->Breaks--;
851cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      } else {
852cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        assert(Details->Type == Branch::Direct);
853cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        Details->Type = Branch::Nested;
854cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      }
855cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    }
856cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  }
857cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Depth++; // this optimization increases depth, for us and all
858cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                           // our next chain (i.e., until this call returns)
859cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                }
860cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                Next = Simple->Next;
861cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              } else {
862cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                // If there is no next then Natural is where we will
863cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                // go to by doing nothing, so we can potentially optimize some
864cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                // branches to direct.
865cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                for (const auto &iter : Simple->Inner->ProcessedBranchesOut) {
866cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Block *Target = iter.first;
867cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Branch *Details = iter.second.get();
868cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  if (Details->Type != Branch::Direct &&
869cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      contains(NaturalBlocks,
870cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               Target)) { // note: cannot handle split blocks
871cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Details->Type = Branch::Direct;
872cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    if (MultipleShape *Multiple =
873cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                            dyn_cast<MultipleShape>(Details->Ancestor))
874cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      Multiple->Breaks--;
875cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  } else if (Details->Type == Branch::Break && LastLoop &&
876cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                             LastLoop->Natural == Details->Ancestor->Natural) {
877cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    // it is important to simplify breaks, as simpler breaks
878cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    // enable other optimizations
879cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    Details->Labeled = false;
880cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                    if (MultipleShape *Multiple =
881cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                            dyn_cast<MultipleShape>(Details->Ancestor))
882cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                      Multiple->Breaks--;
883cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  }
884cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                }
885cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
886cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }, [&](MultipleShape* Multiple)
887cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            {
888cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              for (const auto &iter : Multiple->InnerMap) {
889cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                RemoveUnneededFlows(iter.second, Multiple->Next,
890cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                    Multiple->Breaks ? nullptr : LastLoop,
891cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                    Depth + 1);
892cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
893cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Next = Multiple->Next;
894cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }, [&](LoopShape* Loop)
895cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            {
896cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              RemoveUnneededFlows(Loop->Inner, Loop->Inner, Loop, Depth + 1);
897cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Next = Loop->Next;
898cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            });
899cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
900cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
901cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
902cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // After we know which loops exist, we can calculate which need to be
903cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    // labeled
904cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void FindLabeledLoops(Shape *Root) {
905cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      Shape *Next = Root;
906cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      while (Next) {
907cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Root = Next;
908cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        Next = nullptr;
909cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
910cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        ShapeSwitch(
911cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Root,
912cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            [&](SimpleShape *Simple) {
913cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          MultipleShape *Fused = dyn_cast<MultipleShape>(Root->Next);
914cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // If we are fusing a Multiple with a loop into this Simple, then
915cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          // visit it now
916cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (Fused && Fused->Breaks)
917cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            LoopStack.push(Fused);
918cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (Simple->Inner->BranchVar)
919cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            LoopStack.push(nullptr); // a switch means breaks are now useless,
920cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                     // push a dummy
921cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          if (Fused) {
922cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Fused->UseSwitch)
923cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.push(nullptr); // a switch means breaks are now
924cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                       // useless, push a dummy
925cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            for (const auto &iter : Fused->InnerMap) {
926cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              FindLabeledLoops(iter.second);
927cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
928cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
929cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          for (const auto &iter : Simple->Inner->ProcessedBranchesOut) {
930cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Branch *Details = iter.second.get();
931cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Details->Type == Branch::Break ||
932cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                Details->Type == Branch::Continue) {
933cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              assert(!LoopStack.empty());
934cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              if (Details->Ancestor != LoopStack.top() && Details->Labeled) {
935cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                if (MultipleShape *Multiple =
936cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                        dyn_cast<MultipleShape>(Details->Ancestor)) {
937cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Multiple->Labeled = true;
938cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                } else {
939cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  LoopShape *Loop = cast<LoopShape>(Details->Ancestor);
940cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                  Loop->Labeled = true;
941cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                }
942cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              } else {
943cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                Details->Labeled = false;
944cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              }
945cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            }
946cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Fused && Fused->UseSwitch)
947cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.pop();
948cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Simple->Inner->BranchVar)
949cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.pop();
950cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Fused && Fused->Breaks)
951cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.pop();
952cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Fused)
953cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Next = Fused->Next;
954cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            else
955cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              Next = Root->Next;
956cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
957cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
958cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          , [&](MultipleShape* Multiple) {
959cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Multiple->Breaks)
960cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.push(Multiple);
961cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            for (const auto &iter : Multiple->InnerMap)
962cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              FindLabeledLoops(iter.second);
963cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            if (Multiple->Breaks)
964cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar              LoopStack.pop();
965cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Next = Root->Next;
966cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          }
967cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          , [&](LoopShape* Loop) {
968cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            LoopStack.push(Loop);
969cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            FindLabeledLoops(Loop->Inner);
970cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            LoopStack.pop();
971cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar            Next = Root->Next;
972cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          });
973cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      }
974cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
975cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
976cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    void Process(Shape * Root) {
977cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      FindNaturals(Root);
978cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      RemoveUnneededFlows(Root);
979cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      FindLabeledLoops(Root);
980cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    }
981cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  };
982cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
983cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  PostOptimizer(this).Process(Root);
984cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
985