diff options
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 26 | ||||
-rw-r--r-- | test/passes/remove-unused-brs.txt | 22 | ||||
-rw-r--r-- | test/passes/remove-unused-brs.wast | 23 |
3 files changed, 66 insertions, 5 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index a3ef15639..e627ce138 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -74,7 +74,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { flows.push_back(currp); self->valueCanFlow = true; // start optimistic } else { - self->valueCanFlow = false; + self->stopValueFlow(); } } else if (curr->is<Return>()) { flows.clear(); @@ -84,6 +84,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { auto* iff = curr->cast<If>(); if (iff->condition->type == unreachable) { // avoid trying to optimize this, we never reach it anyhow + self->stopFlow(); return; } if (iff->ifFalse) { @@ -94,7 +95,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { self->ifStack.pop_back(); } else { // if without else stops the flow of values - self->valueCanFlow = false; + self->stopValueFlow(); } } else if (curr->is<Block>()) { // any breaks flowing to here are unnecessary, as we get here anyhow @@ -132,16 +133,31 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { } } else if (curr->is<Nop>()) { // ignore (could be result of a previous cycle) - self->valueCanFlow = false; + self->stopValueFlow(); } else if (curr->is<Loop>()) { // do nothing - it's ok for values to flow out } else { // anything else stops the flow - flows.clear(); - self->valueCanFlow = false; + self->stopFlow(); } } + void stopFlow() { + flows.clear(); + valueCanFlow = false; + } + + void stopValueFlow() { + flows.erase(std::remove_if(flows.begin(), flows.end(), [&](Expression** currp) { + auto* curr = *currp; + if (auto* ret = curr->dynCast<Return>()) { + return ret->value; + } + return curr->cast<Break>()->value; + }), flows.end()); + valueCanFlow = false; + } + static void clear(RemoveUnusedBrs* self, Expression** currp) { self->flows.clear(); } diff --git a/test/passes/remove-unused-brs.txt b/test/passes/remove-unused-brs.txt index c4c2710d3..7951cf18f 100644 --- a/test/passes/remove-unused-brs.txt +++ b/test/passes/remove-unused-brs.txt @@ -7,6 +7,7 @@ (type $5 (func (param f32 i32 f32 i32 i32 f64 f32) (result i32))) (type $6 (func (param i32) (result i64))) (type $7 (func (result i64))) + (type $8 (func (result f32))) (memory $0 256 256) (func $b0-yes (type $0) (param $i1 i32) (block $topmost @@ -1083,4 +1084,25 @@ ) ) ) + (func $no-flow-through-if-without-else (type $8) (result f32) + (local $0 i32) + (local $2 f32) + (block $label$0 (result f32) + (if (result f32) + (get_local $0) + (block $label$11 + (return + (f32.const 239) + ) + (if + (i32.const 0) + (return + (get_local $2) + ) + ) + ) + (f32.const -9223372036854775808) + ) + ) + ) ) diff --git a/test/passes/remove-unused-brs.wast b/test/passes/remove-unused-brs.wast index 32c4ece6a..20441d9e4 100644 --- a/test/passes/remove-unused-brs.wast +++ b/test/passes/remove-unused-brs.wast @@ -966,5 +966,28 @@ ) ) ) + (func $no-flow-through-if-without-else (result f32) + (local $0 i32) + (local $2 f32) + (block $label$0 + (if + (get_local $0) + (block $label$11 + (return + (f32.const 239) + ) + (if + (i32.const 0) + (return + (get_local $2) + ) + ) + ) + (return + (f32.const -9223372036854775808) + ) + ) + ) + ) ) |