summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/RemoveUnusedBrs.cpp41
-rw-r--r--test/passes/remove-unused-brs.txt104
-rw-r--r--test/passes/remove-unused-brs.wast49
3 files changed, 186 insertions, 8 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 5f3018c5f..0ff48381f 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -27,14 +27,39 @@ struct RemoveUnusedBrs : public Pass {
void visitBlock(Block *curr) override {
if (curr->name.isNull()) return;
if (curr->list.size() == 0) return;
- Break* last = curr->list.back()->dyn_cast<Break>();
- if (!last) return;
- if (last->condition) return;
- if (last->name == curr->name) {
- if (!last->value) {
- curr->list.pop_back();
- } else {
- curr->list[curr->list.size()-1] = last->value; // can replace with the value
+ Expression* last = curr->list.back();
+ if (Break* br = last->dyn_cast<Break>()) {
+ if (br->condition) return;
+ if (br->name == curr->name) {
+ if (!br->value) {
+ curr->list.pop_back();
+ } else {
+ curr->list[curr->list.size()-1] = br->value; // can replace with the value
+ }
+ }
+ } else if (If* ifelse = curr->list.back()->dyn_cast<If>()) {
+ if (!ifelse->ifFalse) return;
+ if (ifelse->type != none) return;
+ // an if_else that indirectly returns a value by breaking to this block can potentially remove both breaks
+ auto process = [&curr](Expression *side, bool doIt) {
+ Block* b = side->dyn_cast<Block>();
+ if (!b) return false;
+ Expression* last = b->list.back();
+ Break* br = last->dyn_cast<Break>();
+ if (!br) return false;
+ if (br->condition) return false;
+ if (!br->value) return false;
+ if (br->name != curr->name) return false;
+ if (doIt) {
+ b->list[b->list.size()-1] = br->value;
+ }
+ return true;
+ };
+ // do both, or none
+ if (process(ifelse->ifTrue, false) && process(ifelse->ifFalse, false)) {
+ process(ifelse->ifTrue, true);
+ process(ifelse->ifFalse, true);
+ ifelse->type = curr->type; // if_else now returns a value
}
}
}
diff --git a/test/passes/remove-unused-brs.txt b/test/passes/remove-unused-brs.txt
index af5b9d1ed..8e03d583e 100644
--- a/test/passes/remove-unused-brs.txt
+++ b/test/passes/remove-unused-brs.txt
@@ -103,6 +103,60 @@
)
)
)
+ (func $b12-yes (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ (br $topmost
+ (i32.const 1)
+ )
+ )
+ (block $block1
+ (i32.const 27)
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ )
+ (func $b13 (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ (br_if
+ (i32.const 1)
+ $topmost
+ (i32.const 1)
+ )
+ )
+ (block $block1
+ (i32.const 27)
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ (i32.const 3)
+ )
+ )
+ (func $b14 (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ )
+ (block $block1
+ (i32.const 27)
+ )
+ )
+ )
+ )
)
(module
(memory 16777216 16777216)
@@ -203,4 +257,54 @@
)
)
)
+ (func $b12-yes (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ (i32.const 1)
+ )
+ (block $block1
+ (i32.const 27)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (func $b13 (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ (br_if
+ (i32.const 1)
+ $topmost
+ (i32.const 1)
+ )
+ )
+ (block $block1
+ (i32.const 27)
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ (i32.const 3)
+ )
+ )
+ (func $b14 (result i32)
+ (block $topmost
+ (if_else
+ (i32.const 1)
+ (block $block0
+ (i32.const 12)
+ )
+ (block $block1
+ (i32.const 27)
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/remove-unused-brs.wast b/test/passes/remove-unused-brs.wast
index b4a2cc5fe..8f90c75b0 100644
--- a/test/passes/remove-unused-brs.wast
+++ b/test/passes/remove-unused-brs.wast
@@ -88,5 +88,54 @@
)
)
)
+ (func $b12-yes (result i32)
+ (block $topmost
+ (if_else (i32.const 1)
+ (block
+ (i32.const 12)
+ (br $topmost
+ (i32.const 1)
+ )
+ )
+ (block
+ (i32.const 27)
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ )
+ (func $b13 (result i32)
+ (block $topmost
+ (if_else (i32.const 1)
+ (block
+ (i32.const 12)
+ (br_if (i32.const 1) $topmost
+ (i32.const 1)
+ )
+ )
+ (block
+ (i32.const 27)
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ (i32.const 3)
+ )
+ )
+ (func $b14 (result i32)
+ (block $topmost
+ (if_else (i32.const 1)
+ (block
+ (i32.const 12)
+ )
+ (block
+ (i32.const 27)
+ )
+ )
+ )
+ )
)