summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cfg/Relooper.cpp11
-rw-r--r--test/example/relooper-merge7.c49
-rw-r--r--test/example/relooper-merge7.txt37
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)
+ )
+ )
+ )
+)