diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-11-13 16:36:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-13 16:36:50 -0800 |
commit | 37d82ba9574d440a89b1d7f91af89cd30b35b158 (patch) | |
tree | dee891b1c91fd9511948b3f9aee0b9ed578ea71e /src | |
parent | b67917ee7392c4d49402cb5e7320e663208390ef (diff) | |
download | binaryen-37d82ba9574d440a89b1d7f91af89cd30b35b158.tar.gz binaryen-37d82ba9574d440a89b1d7f91af89cd30b35b158.tar.bz2 binaryen-37d82ba9574d440a89b1d7f91af89cd30b35b158.zip |
Modernize relooper code (#1738)
Use c++11 auto, iterators, etc.
Diffstat (limited to 'src')
-rw-r--r-- | src/cfg/Relooper.cpp | 319 | ||||
-rw-r--r-- | src/cfg/Relooper.h | 34 |
2 files changed, 176 insertions, 177 deletions
diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index 22b455aaf..2387922a8 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -107,7 +107,7 @@ Branch::Branch(std::vector<wasm::Index>&& ValuesInit, wasm::Expression* CodeInit // otherwise, it is the default } -wasm::Expression* Branch::Render(RelooperBuilder& Builder, Block *Target, bool SetLabel) { +wasm::Expression* Branch::Render(RelooperBuilder& Builder, Block* Target, bool SetLabel) { auto* Ret = Builder.makeBlock(); if (Code) Ret->list.push_back(Code); if (SetLabel) Ret->list.push_back(Builder.makeSetLabel(Target->Id)); @@ -126,20 +126,20 @@ wasm::Expression* Branch::Render(RelooperBuilder& Builder, Block *Target, bool S Block::Block(wasm::Expression* CodeInit, wasm::Expression* SwitchConditionInit) : Parent(nullptr), Id(-1), Code(CodeInit), SwitchCondition(SwitchConditionInit), IsCheckedMultipleEntry(false) {} Block::~Block() { - for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { - delete iter->second; + for (auto& iter : ProcessedBranchesOut) { + delete iter.second; } - for (BlockBranchMap::iterator iter = BranchesOut.begin(); iter != BranchesOut.end(); iter++) { - delete iter->second; + for (auto& iter : BranchesOut) { + delete iter.second; } } -void Block::AddBranchTo(Block *Target, wasm::Expression* Condition, wasm::Expression* Code) { +void Block::AddBranchTo(Block* Target, wasm::Expression* Condition, wasm::Expression* Code) { assert(!contains(BranchesOut, Target)); // cannot add more than one branch to the same target BranchesOut[Target] = new Branch(Condition, Code); } -void Block::AddSwitchBranchTo(Block *Target, std::vector<wasm::Index>&& Values, wasm::Expression* Code) { +void Block::AddSwitchBranchTo(Block* Target, std::vector<wasm::Index>&& Values, wasm::Expression* Code) { assert(!contains(BranchesOut, Target)); // cannot add more than one branch to the same target BranchesOut[Target] = new Branch(std::move(Values), Code); } @@ -181,7 +181,7 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { // *must* appear in the Simple (the Simple is the only one reaching the // Multiple), so we can remove the Multiple and add its independent groups // into the Simple's branches. - MultipleShape *Fused = Shape::IsMultiple(Parent->Next); + MultipleShape* Fused = Shape::IsMultiple(Parent->Next); if (Fused) { PrintDebug("Fusing Multiple to Simple\n", 0); Parent->Next = Parent->Next->Next; @@ -194,16 +194,16 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { } } - Block *DefaultTarget = nullptr; // The block we branch to without checking the condition, if none of the other conditions held. + Block* DefaultTarget = nullptr; // The block we branch to without checking the condition, if none of the other conditions held. // Find the default target, the one without a condition - for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { - if ((!SwitchCondition && !iter->second->Condition) || (SwitchCondition && !iter->second->SwitchValues)) { + for (auto& iter : ProcessedBranchesOut) { + if ((!SwitchCondition && !iter.second->Condition) || (SwitchCondition && !iter.second->SwitchValues)) { assert(!DefaultTarget && "block has branches without a default (nullptr for the condition)"); // Must be exactly one default // nullptr - DefaultTarget = iter->first; + DefaultTarget = iter.first; } } - assert(DefaultTarget); // Since each block *must* branch somewhere, this must be set + assert(DefaultTarget); // Since each Block* must* branch somewhere, this must be set wasm::Expression* Root = nullptr; // root of the main part, that we are about to emit @@ -217,9 +217,9 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { wasm::Expression* RemainingConditions = nullptr; - for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin();; iter++) { - Block *Target; - Branch *Details; + for (auto iter = ProcessedBranchesOut.begin();; iter++) { + Block* Target; + Branch* Details; if (iter != ProcessedBranchesOut.end()) { Target = iter->first; if (Target == DefaultTarget) continue; // done at the end @@ -300,8 +300,8 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { auto* Inner = Outer; std::vector<wasm::Name> Table; for (auto& iter : ProcessedBranchesOut) { - Block *Target = iter.first; - Branch *Details = iter.second; + Block* Target = iter.first; + Branch* Details = iter.second; wasm::Name CurrName; if (Details->SwitchValues) { CurrName = wasm::Name(Base + "$case$" + std::to_string(Target->Id)); @@ -384,12 +384,13 @@ wasm::Expression* SimpleShape::Render(RelooperBuilder& Builder, bool InLoop) { wasm::Expression* MultipleShape::Render(RelooperBuilder& Builder, bool InLoop) { // TODO: consider switch // emit an if-else chain - wasm::If *FirstIf = nullptr, *CurrIf = nullptr; + wasm::If* FirstIf = nullptr; + wasm::If* CurrIf = nullptr; std::vector<wasm::If*> finalizeStack; - for (IdShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { + for (auto& iter : InnerMap) { auto* Now = Builder.makeIf( - Builder.makeCheckLabel(iter->first), - iter->second->Render(Builder, InLoop) + Builder.makeCheckLabel(iter.first), + iter.second->Render(Builder, InLoop) ); finalizeStack.push_back(Now); if (!CurrIf) { @@ -434,82 +435,87 @@ Relooper::~Relooper() { for (unsigned i = 0; i < Shapes.size(); i++) delete Shapes[i]; } -void Relooper::AddBlock(Block *New, int Id) { +void Relooper::AddBlock(Block* New, int Id) { New->Id = Id == -1 ? BlockIdCounter++ : Id; Blocks.push_back(New); } -struct RelooperRecursor { - Relooper *Parent; - RelooperRecursor(Relooper *ParentInit) : Parent(ParentInit) {} -}; +namespace { typedef std::list<Block*> BlockList; -void Relooper::Calculate(Block *Entry) { - // Scan and optimize the input - struct PreOptimizer : public RelooperRecursor { - PreOptimizer(Relooper *Parent) : RelooperRecursor(Parent) {} - BlockSet Live; - - void FindLive(Block *Root) { - BlockList ToInvestigate; - ToInvestigate.push_back(Root); - while (ToInvestigate.size() > 0) { - Block *Curr = ToInvestigate.front(); - ToInvestigate.pop_front(); - if (contains(Live, Curr)) continue; - Live.insert(Curr); - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - ToInvestigate.push_back(iter->first); - } +struct RelooperRecursor { + Relooper* Parent; + RelooperRecursor(Relooper* ParentInit) : Parent(ParentInit) {} +}; + +struct Liveness : public RelooperRecursor { + Liveness(Relooper* Parent) : RelooperRecursor(Parent) {} + BlockSet Live; + + void FindLive(Block* Root) { + BlockList ToInvestigate; + ToInvestigate.push_back(Root); + while (ToInvestigate.size() > 0) { + Block* Curr = ToInvestigate.front(); + ToInvestigate.pop_front(); + if (contains(Live, Curr)) continue; + Live.insert(Curr); + for (auto& iter : Curr->BranchesOut) { + ToInvestigate.push_back(iter.first); } } - }; - PreOptimizer Pre(this); - Pre.FindLive(Entry); + } +}; + +} // namespace + +void Relooper::Calculate(Block* Entry) { + // Find live blocks. + Liveness Live(this); + Live.FindLive(Entry); // Add incoming branches from live blocks, ignoring dead code for (unsigned i = 0; i < Blocks.size(); i++) { - Block *Curr = Blocks[i]; - if (!contains(Pre.Live, Curr)) continue; - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - iter->first->BranchesIn.insert(Curr); + Block* Curr = Blocks[i]; + if (!contains(Live.Live, Curr)) continue; + for (auto& iter : Curr->BranchesOut) { + iter.first->BranchesIn.insert(Curr); } } // Recursively process the graph struct Analyzer : public RelooperRecursor { - Analyzer(Relooper *Parent) : RelooperRecursor(Parent) {} + Analyzer(Relooper* Parent) : RelooperRecursor(Parent) {} // Add a shape to the list of shapes in this Relooper calculation - void Notice(Shape *New) { + void Notice(Shape* New) { New->Id = Parent->ShapeIdCounter++; Parent->Shapes.push_back(New); } // Create a list of entries from a block. If LimitTo is provided, only results in that set // will appear - void GetBlocksOut(Block *Source, BlockSet& Entries, BlockSet *LimitTo = nullptr) { - for (BlockBranchMap::iterator iter = Source->BranchesOut.begin(); iter != Source->BranchesOut.end(); iter++) { - if (!LimitTo || contains(*LimitTo, iter->first)) { - Entries.insert(iter->first); + void GetBlocksOut(Block* Source, BlockSet& Entries, BlockSet* LimitTo = nullptr) { + for (auto& iter : Source->BranchesOut) { + if (!LimitTo || contains(*LimitTo, iter.first)) { + Entries.insert(iter.first); } } } // Converts/processes all branchings to a specific target - void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) { + void Solipsize(Block* Target, Branch::FlowType Type, Shape* Ancestor, BlockSet &From) { PrintDebug("Solipsizing branches into %d\n", Target->Id); DebugDump(From, " relevant to solipsize: "); - for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { - Block *Prior = *iter; + for (auto iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { + Block* Prior = *iter; if (!contains(From, Prior)) { iter++; continue; } - Branch *PriorOut = Prior->BranchesOut[Target]; + Branch* PriorOut = Prior->BranchesOut[Target]; PriorOut->Ancestor = Ancestor; PriorOut->Type = Type; iter++; // carefully increment iter before erasing @@ -521,9 +527,9 @@ void Relooper::Calculate(Block *Entry) { } } - Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) { + Shape* MakeSimple(BlockSet &Blocks, Block* Inner, BlockSet &NextEntries) { PrintDebug("creating simple block with block #%d\n", Inner->Id); - SimpleShape *Simple = new SimpleShape; + SimpleShape* Simple = new SimpleShape; Notice(Simple); Simple->Inner = Inner; Inner->Parent = Simple; @@ -532,34 +538,34 @@ void Relooper::Calculate(Block *Entry) { GetBlocksOut(Inner, NextEntries, &Blocks); BlockSet JustInner; JustInner.insert(Inner); - for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) { - Solipsize(*iter, Branch::Break, Simple, JustInner); + for (auto* Next : NextEntries) { + Solipsize(Next, Branch::Break, Simple, JustInner); } } return Simple; } - Shape *MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) { + Shape* MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) { // Find the inner blocks in this loop. Proceed backwards from the entries until // you reach a seen block, collecting as you go. BlockSet InnerBlocks; BlockSet Queue = Entries; while (Queue.size() > 0) { - Block *Curr = *(Queue.begin()); + Block* Curr = *(Queue.begin()); Queue.erase(Queue.begin()); if (!contains(InnerBlocks, Curr)) { // This element is new, mark it as inner and remove from outer InnerBlocks.insert(Curr); Blocks.erase(Curr); // Add the elements prior to it - for (BlockSet::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) { - Queue.insert(*iter); + for (auto* Prev : Curr->BranchesIn) { + Queue.insert(Prev); } #if 0 // Add elements it leads to, if they are dead ends. There is no reason not to hoist dead ends // into loops, as it can avoid multiple entries after the loop - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - Block *Target = iter->first; + for (auto iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + Block* Target = iter->first; if (Target->BranchesIn.size() <= 1 && Target->BranchesOut.size() == 0) { Queue.insert(Target); } @@ -569,10 +575,9 @@ void Relooper::Calculate(Block *Entry) { } assert(InnerBlocks.size() > 0); - for (BlockSet::iterator iter = InnerBlocks.begin(); iter != InnerBlocks.end(); iter++) { - Block *Curr = *iter; - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - Block *Possible = iter->first; + for (auto* Curr : InnerBlocks) { + for (auto& iter : Curr->BranchesOut) { + Block* Possible = iter.first; if (!contains(InnerBlocks, Possible)) { NextEntries.insert(Possible); } @@ -586,10 +591,10 @@ void Relooper::Calculate(Block *Entry) { FindIndependentGroups(NextEntries, IndependentGroups, &InnerBlocks); while (IndependentGroups.size() > 0 && NextEntries.size() > 1) { - Block *Min = nullptr; + Block* Min = nullptr; int MinSize = 0; - for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { - Block *Entry = iter->first; + for (auto iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { + Block* Entry = iter->first; BlockSet &Blocks = iter->second; if (!Min || Blocks.size() < MinSize) { // TODO: code size, not # of blocks Min = Entry; @@ -599,10 +604,10 @@ void Relooper::Calculate(Block *Entry) { // check how many new entries this would cause BlockSet &Hoisted = IndependentGroups[Min]; bool abort = false; - for (BlockSet::iterator iter = Hoisted.begin(); iter != Hoisted.end() && !abort; iter++) { - Block *Curr = *iter; - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - Block *Target = iter->first; + for (auto iter = Hoisted.begin(); iter != Hoisted.end() && !abort; iter++) { + Block* Curr = *iter; + for (auto iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { + Block* Target = iter->first; if (!contains(Hoisted, Target) && !contains(NextEntries, Target)) { // abort this hoisting abort = true; @@ -617,8 +622,8 @@ void Relooper::Calculate(Block *Entry) { // hoist this entry PrintDebug("hoisting %d into loop\n", Min->Id); NextEntries.erase(Min); - for (BlockSet::iterator iter = Hoisted.begin(); iter != Hoisted.end(); iter++) { - Block *Curr = *iter; + for (auto iter = Hoisted.begin(); iter != Hoisted.end(); iter++) { + Block* Curr = *iter; InnerBlocks.insert(Curr); Blocks.erase(Curr); } @@ -633,20 +638,20 @@ void Relooper::Calculate(Block *Entry) { DebugDump(Blocks, " outer blocks:"); DebugDump(NextEntries, " outer entries:"); - LoopShape *Loop = new LoopShape(); + LoopShape* Loop = new LoopShape(); Notice(Loop); // Solipsize the loop, replacing with break/continue and marking branches as Processed (will not affect later calculations) // A. Branches to the loop entries become a continue to this shape - for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { - Solipsize(*iter, Branch::Continue, Loop, InnerBlocks); + for (auto* Entry : Entries) { + Solipsize(Entry, Branch::Continue, Loop, InnerBlocks); } // B. Branches to outside the loop (a next entry) become breaks on this shape - for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) { - Solipsize(*iter, Branch::Break, Loop, InnerBlocks); + for (auto* Next : NextEntries) { + Solipsize(Next, Branch::Break, Loop, InnerBlocks); } // Finish up - Shape *Inner = Process(InnerBlocks, Entries); + Shape* Inner = Process(InnerBlocks, Entries); Loop->Inner = Inner; Loop->Entries = Entries; return Loop; @@ -656,7 +661,7 @@ void Relooper::Calculate(Block *Entry) { // the entry itself, plus all the blocks it can reach that cannot be directly reached by another entry. Note that we // ignore directly reaching the entry itself by another entry. // @param Ignore - previous blocks that are irrelevant - void FindIndependentGroups(BlockSet &Entries, BlockBlockSetMap& IndependentGroups, BlockSet *Ignore = nullptr) { + void FindIndependentGroups(BlockSet &Entries, BlockBlockSetMap& IndependentGroups, BlockSet* Ignore = nullptr) { typedef std::map<Block*, Block*> BlockBlockMap; struct HelperClass { @@ -664,23 +669,23 @@ void Relooper::Calculate(Block *Entry) { BlockBlockMap Ownership; // For each block, which entry it belongs to. We have reached it from there. HelperClass(BlockBlockSetMap& IndependentGroupsInit) : IndependentGroups(IndependentGroupsInit) {} - void InvalidateWithChildren(Block *New) { // TODO: rename New + void InvalidateWithChildren(Block* New) { // TODO: rename New BlockList ToInvalidate; // Being in the list means you need to be invalidated ToInvalidate.push_back(New); while (ToInvalidate.size() > 0) { - Block *Invalidatee = ToInvalidate.front(); + Block* Invalidatee = ToInvalidate.front(); ToInvalidate.pop_front(); - Block *Owner = Ownership[Invalidatee]; + Block* Owner = Ownership[Invalidatee]; if (contains(IndependentGroups, Owner)) { // Owner may have been invalidated, do not add to IndependentGroups! IndependentGroups[Owner].erase(Invalidatee); } if (Ownership[Invalidatee]) { // may have been seen before and invalidated already Ownership[Invalidatee] = nullptr; - for (BlockBranchMap::iterator iter = Invalidatee->BranchesOut.begin(); iter != Invalidatee->BranchesOut.end(); iter++) { - Block *Target = iter->first; - BlockBlockMap::iterator Known = Ownership.find(Target); + for (auto& iter : Invalidatee->BranchesOut) { + Block* Target = iter.first; + auto Known = Ownership.find(Target); if (Known != Ownership.end()) { - Block *TargetOwner = Known->second; + Block* TargetOwner = Known->second; if (TargetOwner) { ToInvalidate.push_back(Target); } @@ -699,21 +704,20 @@ void Relooper::Calculate(Block *Entry) { // visited. BlockList Queue; // Being in the queue means we just added this item, and we need to add its children - for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { - Block *Entry = *iter; + for (auto* Entry : Entries) { Helper.Ownership[Entry] = Entry; IndependentGroups[Entry].insert(Entry); Queue.push_back(Entry); } while (Queue.size() > 0) { - Block *Curr = Queue.front(); + Block* Curr = Queue.front(); Queue.pop_front(); - Block *Owner = Helper.Ownership[Curr]; // Curr must be in the ownership map if we are in the queue + Block* Owner = Helper.Ownership[Curr]; // Curr must be in the ownership map if we are in the queue if (!Owner) continue; // we have been invalidated meanwhile after being reached from two entries // Add all children - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - Block *New = iter->first; - BlockBlockMap::iterator Known = Helper.Ownership.find(New); + for (auto& iter : Curr->BranchesOut) { + Block* New = iter.first; + auto Known = Helper.Ownership.find(New); if (Known == Helper.Ownership.end()) { // New node. Add it, and put it in the queue Helper.Ownership[New] = Owner; @@ -721,7 +725,7 @@ void Relooper::Calculate(Block *Entry) { Queue.push_back(New); continue; } - Block *NewOwner = Known->second; + Block* NewOwner = Known->second; if (!NewOwner) continue; // We reached an invalidated node if (NewOwner != Owner) { // Invalidate this and all reachable that we have seen - we reached this from two locations @@ -737,13 +741,11 @@ void Relooper::Calculate(Block *Entry) { // if an element has a parent which does *not* have the same owner, we must remove it // and all its children. - for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { - BlockSet &CurrGroup = IndependentGroups[*iter]; + for (auto* Entry : Entries) { + BlockSet &CurrGroup = IndependentGroups[Entry]; BlockList ToInvalidate; - for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) { - Block *Child = *iter; - for (BlockSet::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) { - Block *Parent = *iter; + for (auto* Child : CurrGroup) { + for (auto* Parent : Child->BranchesIn) { if (Ignore && contains(*Ignore, Parent)) continue; if (Helper.Ownership[Parent] != Helper.Ownership[Child]) { ToInvalidate.push_back(Child); @@ -751,48 +753,47 @@ void Relooper::Calculate(Block *Entry) { } } while (ToInvalidate.size() > 0) { - Block *Invalidatee = ToInvalidate.front(); + Block* Invalidatee = ToInvalidate.front(); ToInvalidate.pop_front(); Helper.InvalidateWithChildren(Invalidatee); } } // Remove empty groups - for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { - if (IndependentGroups[*iter].size() == 0) { - IndependentGroups.erase(*iter); + for (auto* Entry : Entries) { + if (IndependentGroups[Entry].size() == 0) { + IndependentGroups.erase(Entry); } } #ifdef RELOOPER_DEBUG PrintDebug("Investigated independent groups:\n"); - for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { - DebugDump(iter->second, " group: "); + for (auto& iter : IndependentGroups) { + DebugDump(iter.second, " group: "); } #endif } - Shape *MakeMultiple(BlockSet &Blocks, BlockSet& Entries, BlockBlockSetMap& IndependentGroups, BlockSet &NextEntries, bool IsCheckedMultiple) { + Shape* MakeMultiple(BlockSet &Blocks, BlockSet& Entries, BlockBlockSetMap& IndependentGroups, BlockSet &NextEntries, bool IsCheckedMultiple) { PrintDebug("creating multiple block with %d inner groups\n", IndependentGroups.size()); - MultipleShape *Multiple = new MultipleShape(); + MultipleShape* Multiple = new MultipleShape(); Notice(Multiple); BlockSet CurrEntries; - for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { - Block *CurrEntry = iter->first; - BlockSet &CurrBlocks = iter->second; + for (auto& iter : IndependentGroups) { + Block* CurrEntry = iter.first; + BlockSet &CurrBlocks = iter.second; PrintDebug(" multiple group with entry %d:\n", CurrEntry->Id); DebugDump(CurrBlocks, " "); // Create inner block CurrEntries.clear(); CurrEntries.insert(CurrEntry); - for (BlockSet::iterator iter = CurrBlocks.begin(); iter != CurrBlocks.end(); iter++) { - Block *CurrInner = *iter; + for (auto* CurrInner : CurrBlocks) { // Remove the block from the remaining blocks Blocks.erase(CurrInner); // Find new next entries and fix branches to them - for (BlockBranchMap::iterator iter = CurrInner->BranchesOut.begin(); iter != CurrInner->BranchesOut.end();) { - Block *CurrTarget = iter->first; - BlockBranchMap::iterator Next = iter; + for (auto iter = CurrInner->BranchesOut.begin(); iter != CurrInner->BranchesOut.end();) { + Block* CurrTarget = iter->first; + auto Next = iter; Next++; if (!contains(CurrBlocks, CurrTarget)) { NextEntries.insert(CurrTarget); @@ -808,8 +809,7 @@ void Relooper::Calculate(Block *Entry) { } DebugDump(Blocks, " remaining blocks after multiple:"); // Add entries not handled as next entries, they are deferred - for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { - Block *Entry = *iter; + for (auto* Entry : Entries) { if (!contains(IndependentGroups, Entry)) { NextEntries.insert(Entry); } @@ -822,16 +822,16 @@ void Relooper::Calculate(Block *Entry) { // The Make* functions receive a NextEntries. If they fill it with data, those are the entries for the // ->Next block on them, and the blocks are what remains in Blocks (which Make* modify). In this way // we avoid recursing on Next (imagine a long chain of Simples, if we recursed we could blow the stack). - Shape *Process(BlockSet &Blocks, BlockSet& InitialEntries) { + Shape* Process(BlockSet &Blocks, BlockSet& InitialEntries) { PrintDebug("Process() called\n", 0); - BlockSet *Entries = &InitialEntries; + BlockSet* Entries = &InitialEntries; BlockSet TempEntries[2]; int CurrTempIndex = 0; - BlockSet *NextEntries; - Shape *Ret = nullptr; - Shape *Prev = nullptr; + BlockSet* NextEntries; + Shape* Ret = nullptr; + Shape* Prev = nullptr; #define Make(call) \ - Shape *Temp = call; \ + Shape* Temp = call; \ if (Prev) Prev->Next = Temp; \ if (!Ret) Ret = Temp; \ if (!NextEntries->size()) { PrintDebug("Process() returning\n", 0); return Ret; } \ @@ -849,7 +849,7 @@ void Relooper::Calculate(Block *Entry) { if (Entries->size() == 0) return Ret; if (Entries->size() == 1) { - Block *Curr = *(Entries->begin()); + Block* Curr = *(Entries->begin()); if (Curr->BranchesIn.size() == 0) { // One entry, no looping ==> Simple Make(MakeSimple(Blocks, Curr, *NextEntries)); @@ -871,12 +871,12 @@ void Relooper::Calculate(Block *Entry) { // Note that it might be reachable by itself - a loop. But that is fine, we will create // a loop inside the multiple block, which is both the performant order to do it, and // preserves the property that a loop will always reach an entry. - for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end();) { - Block *Entry = iter->first; + for (auto iter = IndependentGroups.begin(); iter != IndependentGroups.end();) { + Block* Entry = iter->first; BlockSet &Group = iter->second; - BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete - for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { - Block *Origin = *iterBranch; + auto curr = iter++; // iterate carefully, we may delete + for (auto iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { + Block* Origin = *iterBranch; if (!contains(Group, Origin)) { // Reached from outside the group, so we cannot handle this PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id); @@ -896,25 +896,24 @@ void Relooper::Calculate(Block *Entry) { // pointless. if (IndependentGroups.size() == 2) { // Find the smaller one - BlockBlockSetMap::iterator iter = IndependentGroups.begin(); - Block *SmallEntry = iter->first; + auto iter = IndependentGroups.begin(); + Block* SmallEntry = iter->first; int SmallSize = iter->second.size(); iter++; - Block *LargeEntry = iter->first; + Block* LargeEntry = iter->first; int LargeSize = iter->second.size(); if (SmallSize != LargeSize) { // ignore the case where they are identical - keep things symmetrical there if (SmallSize > LargeSize) { - Block *Temp = SmallEntry; + Block* Temp = SmallEntry; SmallEntry = LargeEntry; LargeEntry = Temp; // Note: we did not flip the Sizes too, they are now invalid. TODO: use the smaller size as a limit? } // Check if dead end bool DeadEnd = true; BlockSet &SmallGroup = IndependentGroups[SmallEntry]; - for (BlockSet::iterator iter = SmallGroup.begin(); iter != SmallGroup.end(); iter++) { - Block *Curr = *iter; - for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - Block *Target = iter->first; + for (auto* Curr : SmallGroup) { + for (auto& iter : Curr->BranchesOut) { + Block* Target = iter.first; if (!contains(SmallGroup, Target)) { DeadEnd = false; break; @@ -956,8 +955,7 @@ void Relooper::Calculate(Block *Entry) { // Main BlockSet AllBlocks; - for (BlockSet::iterator iter = Pre.Live.begin(); iter != Pre.Live.end(); iter++) { - Block *Curr = *iter; + for (auto* Curr : Live.Live) { AllBlocks.insert(Curr); #ifdef RELOOPER_DEBUG PrintDebug("Adding block %d (%s)\n", Curr->Id, Curr->Code); @@ -983,30 +981,29 @@ wasm::Expression* Relooper::Render(RelooperBuilder& Builder) { void Debugging::Dump(BlockSet &Blocks, const char *prefix) { if (prefix) printf("%s ", prefix); - for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) { - Block *Curr = *iter; + for (auto* Curr : Blocks) { printf("%d:\n", Curr->Id); - for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) { - Block *Other = iter2->first; + for (auto iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) { + Block* Other = iter2->first; printf(" -> %d\n", Other->Id); assert(contains(Other->BranchesIn, Curr)); } } } -void Debugging::Dump(Shape *S, const char *prefix) { +void Debugging::Dump(Shape* S, const char *prefix) { if (prefix) printf("%s ", prefix); if (!S) { printf(" (null)\n"); return; } printf(" %d ", S->Id); - if (SimpleShape *Simple = Shape::IsSimple(S)) { + if (SimpleShape* Simple = Shape::IsSimple(S)) { printf("<< Simple with block %d\n", Simple->Inner->Id); - } else if (MultipleShape *Multiple = Shape::IsMultiple(S)) { + } else if (MultipleShape* Multiple = Shape::IsMultiple(S)) { printf("<< Multiple\n"); - for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { - printf(" with entry %d\n", iter->first); + for (auto& iter : Multiple->InnerMap) { + printf(" with entry %d\n", iter.first); } } else if (Shape::IsLoop(S)) { printf("<< Loop\n"); diff --git a/src/cfg/Relooper.h b/src/cfg/Relooper.h index 9cd6156f7..5af55a744 100644 --- a/src/cfg/Relooper.h +++ b/src/cfg/Relooper.h @@ -82,7 +82,7 @@ struct Branch { Break = 1, Continue = 2 }; - Shape *Ancestor; // If not NULL, this shape is the relevant one for purposes of getting to the target block. We break or continue on it + Shape* Ancestor; // If not NULL, this shape is the relevant one for purposes of getting to the target block. We break or continue on it Branch::FlowType Type; // If Ancestor is not NULL, this says whether to break or continue // A branch either has a condition expression if the block ends in ifs, or if the block ends in a switch, then a list of indexes, which @@ -97,7 +97,7 @@ struct Branch { Branch(std::vector<wasm::Index>&& ValuesInit, wasm::Expression* CodeInit = nullptr); // Emits code for branch - wasm::Expression* Render(RelooperBuilder& Builder, Block *Target, bool SetLabel); + wasm::Expression* Render(RelooperBuilder& Builder, Block* Target, bool SetLabel); }; // like std::set, except that begin() -> end() iterates in the @@ -223,7 +223,7 @@ struct Block { BlockSet BranchesIn; BlockBranchMap ProcessedBranchesOut; BlockSet ProcessedBranchesIn; - Shape *Parent; // The shape we are directly inside + Shape* Parent; // The shape we are directly inside int Id; // A unique identifier, defined when added to relooper wasm::Expression* Code; // The code in this block. This can be arbitrary wasm code, including internal control flow, it should just not branch to the outside wasm::Expression* SwitchCondition; // If nullptr, then this block ends in ifs (or nothing). otherwise, this block ends in a switch, done on this condition @@ -239,11 +239,13 @@ struct Block { // instruction, as the relooper doesn't know whether you want control flow to stop with // an `unreachable` or a `return` or something else (if you forget to do this, control // flow may continue into the block that happens to be emitted right after it). - void AddBranchTo(Block *Target, wasm::Expression* Condition, wasm::Expression* Code = nullptr); + // Internally, adding a branch only adds the outgoing branch. The matching incoming branch + // on the target is added by the Relooper itself as it works. + void AddBranchTo(Block* Target, wasm::Expression* Condition, wasm::Expression* Code = nullptr); // Add a switch branch: if the switch condition is one of these values, we branch (or if the list is empty, we are the default) // Note that there can be only one branch from A to B (if you need multiple values for the branch, that's what the array and default are for). - void AddSwitchBranchTo(Block *Target, std::vector<wasm::Index>&& Values, wasm::Expression* Code = nullptr); + void AddSwitchBranchTo(Block* Target, std::vector<wasm::Index>&& Values, wasm::Expression* Code = nullptr); // Emit code for the block, including its contents and branchings out wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop); @@ -273,8 +275,8 @@ struct LoopShape; struct Shape { int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id. Defined when added to relooper - Shape *Next; // The shape that will appear in the code right after this one - Shape *Natural; // The shape that control flow gets to naturally (if there is Next, then this is Next) + Shape* Next; // The shape that will appear in the code right after this one + Shape* Natural; // The shape that control flow gets to naturally (if there is Next, then this is Next) enum ShapeType { Simple, @@ -288,13 +290,13 @@ struct Shape { virtual wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) = 0; - static SimpleShape *IsSimple(Shape *It) { return It && It->Type == Simple ? (SimpleShape*)It : NULL; } - static MultipleShape *IsMultiple(Shape *It) { return It && It->Type == Multiple ? (MultipleShape*)It : NULL; } - static LoopShape *IsLoop(Shape *It) { return It && It->Type == Loop ? (LoopShape*)It : NULL; } + static SimpleShape* IsSimple(Shape* It) { return It && It->Type == Simple ? (SimpleShape*)It : NULL; } + static MultipleShape* IsMultiple(Shape* It) { return It && It->Type == Multiple ? (MultipleShape*)It : NULL; } + static LoopShape* IsLoop(Shape* It) { return It && It->Type == Loop ? (LoopShape*)It : NULL; } }; struct SimpleShape : public Shape { - Block *Inner; + Block* Inner; SimpleShape() : Shape(Simple), Inner(NULL) {} wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) override; @@ -311,7 +313,7 @@ struct MultipleShape : public Shape { }; struct LoopShape : public Shape { - Shape *Inner; + Shape* Inner; BlockSet Entries; // we must visit at least one of these @@ -333,7 +335,7 @@ struct LoopShape : public Shape { struct Relooper { std::deque<Block*> Blocks; std::deque<Shape*> Shapes; - Shape *Root; + Shape* Root; bool MinSize; int BlockIdCounter; int ShapeIdCounter; @@ -341,10 +343,10 @@ struct Relooper { Relooper(); ~Relooper(); - void AddBlock(Block *New, int Id=-1); + void AddBlock(Block* New, int Id=-1); // Calculates the shapes - void Calculate(Block *Entry); + void Calculate(Block* Entry); // Renders the result. wasm::Expression* Render(RelooperBuilder& Builder); @@ -358,7 +360,7 @@ typedef InsertOrderedMap<Block*, BlockSet> BlockBlockSetMap; #ifdef RELOOPER_DEBUG struct Debugging { static void Dump(BlockSet &Blocks, const char *prefix=NULL); - static void Dump(Shape *S, const char *prefix=NULL); + static void Dump(Shape* S, const char *prefix=NULL); }; #endif |