diff options
-rw-r--r-- | src/cfg/Relooper.cpp | 11 | ||||
-rw-r--r-- | test/example/relooper-merge7.c | 49 | ||||
-rw-r--r-- | test/example/relooper-merge7.txt | 37 |
3 files changed, 95 insertions, 2 deletions
diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index 87dd4e379..08f28bc30 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -533,7 +533,10 @@ struct Liveness : public RelooperRecursor { typedef std::pair<Branch*, Block*> BranchBlock; struct Optimizer : public RelooperRecursor { - Optimizer(Relooper* Parent) : RelooperRecursor(Parent) { + Block* Entry; + + Optimizer(Relooper* Parent, Block* EntryInit) + : RelooperRecursor(Parent), Entry(EntryInit) { // TODO: there are likely some rare but possible O(N^2) cases with this // looping bool More = true; @@ -726,6 +729,7 @@ struct Optimizer : public RelooperRecursor { NumPredecessors[NextBlock]++; } } + NumPredecessors[Entry]++; for (auto* CurrBlock : Parent->Blocks) { if (CurrBlock->BranchesOut.size() == 1) { auto iter = CurrBlock->BranchesOut.begin(); @@ -744,6 +748,9 @@ 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. @@ -1032,7 +1039,7 @@ private: void Relooper::Calculate(Block* Entry) { // Optimize. - Optimizer(this); + Optimizer(this, Entry); // Find live blocks. Liveness Live(this); diff --git a/test/example/relooper-merge7.c b/test/example/relooper-merge7.c new file mode 100644 index 000000000..c942e3b25 --- /dev/null +++ b/test/example/relooper-merge7.c @@ -0,0 +1,49 @@ + +#include <assert.h> +#include <stdio.h> + +#include "binaryen-c.h" + +int main() { + BinaryenModuleRef module = BinaryenModuleCreate(); + + RelooperRef relooper = RelooperCreate(module); + + // Create the basic blocks + RelooperBlockRef b[4]; + int hasTerminator[4] = {0, 0, 0, 1}; + + int numBlocks = sizeof(b) / sizeof(RelooperBlockRef); + assert(sizeof(hasTerminator) / sizeof(int) == numBlocks); + int i; + for (i = 0; i < numBlocks; i++) { + BinaryenExpressionRef args[] = { + BinaryenConst(module, BinaryenLiteralInt32(i))}; + BinaryenExpressionRef list[] = { + BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), + BinaryenReturn(module, NULL) // relevant only if hasTerminator[i] + }; + b[i] = RelooperAddBlock( + relooper, + BinaryenBlock( + module, NULL, list, 1 + hasTerminator[i], BinaryenTypeNone())); + } + + // Create the branches. + // In this testcase, only b[2] and b[3] can be merged. + RelooperAddBranch(b[0], b[1], NULL, NULL); + RelooperAddBranch( + b[0], b[2], BinaryenConst(module, BinaryenLiteralInt32(-10)), NULL); + RelooperAddBranch(b[1], b[0], NULL, NULL); + RelooperAddBranch(b[2], b[3], NULL, NULL); + + BinaryenExpressionRef all = RelooperRenderAndDispose(relooper, b[0], 1); + + // Print it out + BinaryenExpressionPrint(all); + + // Clean up the module, which owns all the objects we created above + BinaryenModuleDispose(module); + + return 0; +} diff --git a/test/example/relooper-merge7.txt b/test/example/relooper-merge7.txt new file mode 100644 index 000000000..23ffffb21 --- /dev/null +++ b/test/example/relooper-merge7.txt @@ -0,0 +1,37 @@ +(block + (block $block$3$break + (loop $shape$0$continue + (block $block$2$break + (call $print + (i32.const 0) + ) + (if + (i32.const -10) + (br $block$3$break) + (br $block$2$break) + ) + ) + (block + (call $print + (i32.const 1) + ) + (block + (br $shape$0$continue) + ) + ) + ) + ) + (block + (block + (call $print + (i32.const 2) + ) + (block + (call $print + (i32.const 3) + ) + (return) + ) + ) + ) +) |