summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp11
-rw-r--r--src/cfg/Relooper.cpp109
-rw-r--r--src/cfg/Relooper.h41
-rw-r--r--src/passes/ReReloop.cpp6
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