diff options
-rw-r--r-- | src/binaryen-c.cpp | 11 | ||||
-rw-r--r-- | src/cfg/Relooper.cpp | 109 | ||||
-rw-r--r-- | src/cfg/Relooper.h | 41 | ||||
-rw-r--r-- | src/passes/ReReloop.cpp | 6 |
4 files changed, 100 insertions, 67 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 101af5172..4c5063114 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3941,9 +3941,8 @@ RelooperRef RelooperCreate(BinaryenModuleRef module) { RelooperBlockRef RelooperAddBlock(RelooperRef relooper, BinaryenExpressionRef code) { - auto* ret = new CFG::Block((Expression*)code); - ((CFG::Relooper*)relooper)->AddBlock(ret); - return RelooperBlockRef(ret); + return RelooperBlockRef( + ((CFG::Relooper*)relooper)->AddBlock((Expression*)code)); } void RelooperAddBranch(RelooperBlockRef from, @@ -3957,9 +3956,9 @@ void RelooperAddBranch(RelooperBlockRef from, RelooperBlockRef RelooperAddBlockWithSwitch(RelooperRef relooper, BinaryenExpressionRef code, BinaryenExpressionRef condition) { - auto* ret = new CFG::Block((Expression*)code, (Expression*)condition); - ((CFG::Relooper*)relooper)->AddBlock(ret); - return RelooperBlockRef(ret); + return RelooperBlockRef( + ((CFG::Relooper*)relooper) + ->AddBlock((Expression*)code, (Expression*)condition)); } void RelooperAddBranchForSwitch(RelooperBlockRef from, diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index b3bbe0153..4404f2d20 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -140,25 +140,18 @@ Branch::Render(RelooperBuilder& Builder, Block* Target, bool SetLabel) { // Block -Block::Block(wasm::Expression* CodeInit, wasm::Expression* SwitchConditionInit) - : Code(CodeInit), SwitchCondition(SwitchConditionInit), +Block::Block(Relooper* relooper, + wasm::Expression* CodeInit, + wasm::Expression* SwitchConditionInit) + : relooper(relooper), Code(CodeInit), SwitchCondition(SwitchConditionInit), IsCheckedMultipleEntry(false) {} -Block::~Block() { - for (auto& iter : ProcessedBranchesOut) { - delete iter.second; - } - for (auto& iter : BranchesOut) { - delete iter.second; - } -} - void Block::AddBranchTo(Block* Target, wasm::Expression* Condition, wasm::Expression* Code) { // cannot add more than one branch to the same target assert(!contains(BranchesOut, Target)); - BranchesOut[Target] = new Branch(Condition, Code); + BranchesOut[Target] = relooper->AddBranch(Condition, Code); } void Block::AddSwitchBranchTo(Block* Target, @@ -166,7 +159,7 @@ void Block::AddSwitchBranchTo(Block* Target, wasm::Expression* Code) { // cannot add more than one branch to the same target assert(!contains(BranchesOut, Target)); - BranchesOut[Target] = new Branch(std::move(Values), Code); + BranchesOut[Target] = relooper->AddBranch(std::move(Values), Code); } wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { @@ -486,18 +479,53 @@ Relooper::Relooper(wasm::Module* ModuleInit) ShapeIdCounter(0) { // block ID 0 is reserved for clearings } -Relooper::~Relooper() { - for (unsigned i = 0; i < Blocks.size(); i++) { - delete Blocks[i]; - } - for (unsigned i = 0; i < Shapes.size(); i++) { - delete Shapes[i]; - } +Block* Relooper::AddBlock(wasm::Expression* CodeInit, + wasm::Expression* SwitchConditionInit) { + + auto block = std::make_unique<Block>(this, CodeInit, SwitchConditionInit); + block->Id = BlockIdCounter++; + auto* blockPtr = block.get(); + Blocks.push_back(std::move(block)); + return blockPtr; +} + +Branch* Relooper::AddBranch(wasm::Expression* ConditionInit, + wasm::Expression* CodeInit) { + auto branch = std::make_unique<Branch>(ConditionInit, CodeInit); + auto* branchPtr = branch.get(); + Branches.push_back(std::move(branch)); + return branchPtr; +} +Branch* Relooper::AddBranch(std::vector<wasm::Index>&& ValuesInit, + wasm::Expression* CodeInit) { + auto branch = std::make_unique<Branch>(std::move(ValuesInit), CodeInit); + auto* branchPtr = branch.get(); + Branches.push_back(std::move(branch)); + return branchPtr; +} + +SimpleShape* Relooper::AddSimpleShape() { + auto shape = std::make_unique<SimpleShape>(); + shape->Id = ShapeIdCounter++; + auto* shapePtr = shape.get(); + Shapes.push_back(std::move(shape)); + return shapePtr; +} + +MultipleShape* Relooper::AddMultipleShape() { + auto shape = std::make_unique<MultipleShape>(); + shape->Id = ShapeIdCounter++; + auto* shapePtr = shape.get(); + Shapes.push_back(std::move(shape)); + return shapePtr; } -void Relooper::AddBlock(Block* New, int Id) { - New->Id = Id == -1 ? BlockIdCounter++ : Id; - Blocks.push_back(New); +LoopShape* Relooper::AddLoopShape() { + auto shape = std::make_unique<LoopShape>(); + shape->Id = ShapeIdCounter++; + auto* shapePtr = shape.get(); + Shapes.push_back(std::move(shape)); + return shapePtr; } namespace { @@ -580,7 +608,7 @@ struct Optimizer : public RelooperRecursor { // We will be performing code comparisons, so do some basic canonicalization // to avoid things being unequal for silly reasons. void CanonicalizeCode() { - for (auto* Block : Parent->Blocks) { + for (auto& Block : Parent->Blocks) { Block->Code = Canonicalize(Block->Code); for (auto& iter : Block->BranchesOut) { auto* Branch = iter.second; @@ -595,7 +623,7 @@ struct Optimizer : public RelooperRecursor { // and there is no phi or switch to worry us, just skip through. bool SkipEmptyBlocks() { bool Worked = false; - for (auto* CurrBlock : Parent->Blocks) { + for (auto& CurrBlock : Parent->Blocks) { // Generate a new set of branches out TODO optimize BlockBranchMap NewBranchesOut; for (auto& iter : CurrBlock->BranchesOut) { @@ -653,7 +681,6 @@ struct Optimizer : public RelooperRecursor { NewBranchesOut[Replacement] = NextBranch; } } - // FIXME do we leak old unused Branches? CurrBlock->BranchesOut.swap(NewBranchesOut); } return Worked; @@ -664,7 +691,7 @@ struct Optimizer : public RelooperRecursor { // equivalent in their *contents*. bool MergeEquivalentBranches() { bool Worked = false; - for (auto* ParentBlock : Parent->Blocks) { + for (auto& ParentBlock : Parent->Blocks) { #if RELOOPER_OPTIMIZER_DEBUG std::cout << "at parent " << ParentBlock->Id << '\n'; #endif @@ -722,20 +749,20 @@ struct Optimizer : public RelooperRecursor { bool Worked = false; // First, count predecessors. std::map<Block*, size_t> NumPredecessors; - for (auto* CurrBlock : Parent->Blocks) { + for (auto& CurrBlock : Parent->Blocks) { for (auto& iter : CurrBlock->BranchesOut) { auto* NextBlock = iter.first; NumPredecessors[NextBlock]++; } } NumPredecessors[Entry]++; - for (auto* CurrBlock : Parent->Blocks) { + for (auto& CurrBlock : Parent->Blocks) { if (CurrBlock->BranchesOut.size() == 1) { auto iter = CurrBlock->BranchesOut.begin(); auto* NextBlock = iter->first; auto* NextBranch = iter->second; assert(NumPredecessors[NextBlock] > 0); - if (NextBlock != CurrBlock && NumPredecessors[NextBlock] == 1) { + if (NextBlock != CurrBlock.get() && NumPredecessors[NextBlock] == 1) { // Good to merge! wasm::Builder Builder(*Parent->Module); // Merge in code on the branch as well, if any. @@ -747,9 +774,6 @@ struct Optimizer : public RelooperRecursor { Builder.makeSequence(CurrBlock->Code, NextBlock->Code); // Use the next block's branching behavior CurrBlock->BranchesOut.swap(NextBlock->BranchesOut); - for (auto& iter : NextBlock->BranchesOut) { - delete iter.second; - } NextBlock->BranchesOut.clear(); CurrBlock->SwitchCondition = NextBlock->SwitchCondition; // The next block now has no predecessors. @@ -765,7 +789,7 @@ struct Optimizer : public RelooperRecursor { // no switch is needed. bool UnSwitch() { bool Worked = false; - for (auto* ParentBlock : Parent->Blocks) { + for (auto& ParentBlock : Parent->Blocks) { #if RELOOPER_OPTIMIZER_DEBUG std::cout << "un-switching at " << ParentBlock->Id << ' ' << !!ParentBlock->SwitchCondition << ' ' @@ -1049,7 +1073,7 @@ void Relooper::Calculate(Block* Entry) { // Add incoming branches from live blocks, ignoring dead code for (unsigned i = 0; i < Blocks.size(); i++) { - Block* Curr = Blocks[i]; + Block* Curr = Blocks[i].get(); if (!contains(Live.Live, Curr)) { continue; } @@ -1063,12 +1087,6 @@ void Relooper::Calculate(Block* Entry) { struct Analyzer : public RelooperRecursor { Analyzer(Relooper* Parent) : RelooperRecursor(Parent) {} - // Add a shape to the list of shapes in this Relooper calculation - 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, @@ -1109,8 +1127,7 @@ void Relooper::Calculate(Block* Entry) { Shape* MakeSimple(BlockSet& Blocks, Block* Inner, BlockSet& NextEntries) { PrintDebug("creating simple block with block #%d\n", Inner->Id); - SimpleShape* Simple = new SimpleShape; - Notice(Simple); + SimpleShape* Simple = Parent->AddSimpleShape(); Simple->Inner = Inner; Inner->Parent = Simple; if (Blocks.size() > 1) { @@ -1219,8 +1236,7 @@ void Relooper::Calculate(Block* Entry) { DebugDump(Blocks, " outer blocks:"); DebugDump(NextEntries, " outer entries:"); - LoopShape* Loop = new LoopShape(); - Notice(Loop); + LoopShape* Loop = Parent->AddLoopShape(); // Solipsize the loop, replacing with break/continue and marking branches // as Processed (will not affect later calculations) A. Branches to the @@ -1386,8 +1402,7 @@ void Relooper::Calculate(Block* Entry) { bool IsCheckedMultiple) { PrintDebug("creating multiple block with %d inner groups\n", IndependentGroups.size()); - MultipleShape* Multiple = new MultipleShape(); - Notice(Multiple); + MultipleShape* Multiple = Parent->AddMultipleShape(); BlockSet CurrEntries; for (auto& iter : IndependentGroups) { Block* CurrEntry = iter.first; diff --git a/src/cfg/Relooper.h b/src/cfg/Relooper.h index f13d02711..1821336ba 100644 --- a/src/cfg/Relooper.h +++ b/src/cfg/Relooper.h @@ -79,6 +79,7 @@ public: } }; +struct Relooper; struct Block; struct Shape; @@ -241,6 +242,8 @@ typedef InsertOrderedMap<Block*, Branch*> BlockBranchMap; // Represents a basic block of code - some instructions that end with a // control flow modifier (a branch, return or throw). struct Block { + // Reference to the relooper containing this block. + Relooper* relooper; // Branches become processed after we finish the shape relevant to them. For // example, when we recreate a loop, branches to the loop start become // continues and are now processed. When we calculate what shape to generate @@ -262,9 +265,9 @@ struct Block { // variable bool IsCheckedMultipleEntry; - Block(wasm::Expression* CodeInit, + Block(Relooper* relooper, + wasm::Expression* CodeInit, wasm::Expression* SwitchConditionInit = nullptr); - ~Block(); // Add a branch: if the condition holds we branch (or if null, we branch if // all others failed) Note that there can be only one branch from A to B (if @@ -373,26 +376,44 @@ struct LoopShape : public Shape { // // Usage: // 1. Instantiate this struct. -// 2. Call AddBlock with the blocks you have. Each should already -// have its branchings in specified (the branchings out will +// 2. Create the blocks you have. Each should have its +// branchings in specified (the branchings out will // be calculated by the relooper). // 3. Call Render(). // -// Implementation details: The Relooper instance has -// ownership of the blocks and shapes, and frees them when done. +// Implementation details: The Relooper instance takes ownership of the blocks, +// branches and shapes when created using the `AddBlock` etc. methods, and frees +// them when done. struct Relooper { wasm::Module* Module; - std::deque<Block*> Blocks; - std::deque<Shape*> Shapes; + std::deque<std::unique_ptr<Block>> Blocks; + std::deque<std::unique_ptr<Branch>> Branches; + std::deque<std::unique_ptr<Shape>> Shapes; Shape* Root; bool MinSize; int BlockIdCounter; int ShapeIdCounter; Relooper(wasm::Module* ModuleInit); - ~Relooper(); - void AddBlock(Block* New, int Id = -1); + // Creates a new block associated with (and cleaned up along) this relooper. + Block* AddBlock(wasm::Expression* CodeInit, + wasm::Expression* SwitchConditionInit = nullptr); + // Creates a new branch associated with (and cleaned up along) this relooper. + Branch* AddBranch(wasm::Expression* ConditionInit, + wasm::Expression* CodeInit); + // Creates a new branch associated with (and cleaned up along) this relooper. + Branch* AddBranch(std::vector<wasm::Index>&& ValuesInit, + wasm::Expression* CodeInit = nullptr); + // Creates a new simple shape associated with (and cleaned up along) this + // relooper. + SimpleShape* AddSimpleShape(); + // Creates a new multiple shape associated with (and cleaned up along) this + // relooper. + MultipleShape* AddMultipleShape(); + // Creates a new loop shape associated with (and cleaned up along) this + // relooper. + LoopShape* AddLoopShape(); // Calculates the shapes void Calculate(Block* Entry); diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp index 004e922ed..b35efa8d4 100644 --- a/src/passes/ReReloop.cpp +++ b/src/passes/ReReloop.cpp @@ -50,9 +50,7 @@ struct ReReloop final : public Pass { CFG::Block* currCFGBlock = nullptr; CFG::Block* makeCFGBlock() { - auto* ret = new CFG::Block(builder->makeBlock()); - relooper->AddBlock(ret); - return ret; + return relooper->AddBlock(builder->makeBlock()); } CFG::Block* setCurrCFGBlock(CFG::Block* curr) { @@ -321,7 +319,7 @@ struct ReReloop final : public Pass { // blocks that do not have any exits are dead ends in the relooper. we need // to make sure that are in fact dead ends, and do not flow control // anywhere. add a return as needed - for (auto* cfgBlock : relooper->Blocks) { + for (auto& cfgBlock : relooper->Blocks) { auto* block = cfgBlock->Code->cast<Block>(); if (cfgBlock->BranchesOut.empty() && block->type != Type::unreachable) { block->list.push_back(function->sig.results == Type::none |