diff options
-rw-r--r-- | src/ir/type-updating.h | 15 | ||||
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 31 | ||||
-rw-r--r-- | test/passes/dce_all-features.txt (renamed from test/passes/dce.txt) | 31 | ||||
-rw-r--r-- | test/passes/dce_all-features.wast (renamed from test/passes/dce.wast) | 34 |
4 files changed, 110 insertions, 1 deletions
diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h index 09b1b4bdc..40c17427c 100644 --- a/src/ir/type-updating.h +++ b/src/ir/type-updating.h @@ -249,6 +249,11 @@ struct TypeUpdater if (curr->type != unreachable) { return; // did not turn } + } else if (auto* tryy = curr->dynCast<Try>()) { + tryy->finalize(); + if (curr->type != unreachable) { + return; // did not turn + } } else { curr->type = unreachable; } @@ -299,6 +304,16 @@ struct TypeUpdater propagateTypesUp(curr); } } + + void maybeUpdateTypeToUnreachable(Try* curr) { + if (!isConcreteType(curr->type)) { + return; // nothing concrete to change to unreachable + } + curr->finalize(); + if (curr->type == unreachable) { + propagateTypesUp(curr); + } + } }; } // namespace wasm diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 5f562f7ba..058d9e4e4 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -201,10 +201,13 @@ struct DeadCodeElimination } } - // ifs need special handling + // ifs and trys need special handling: only one of (if body and else body / + // try body and catch body) should be reachable to make the whole of (if / + // try) to be reachable. // stack of reachable state, for forking and joining std::vector<bool> ifStack; + std::vector<bool> tryStack; static void doAfterIfCondition(DeadCodeElimination* self, Expression** currp) { @@ -232,6 +235,26 @@ struct DeadCodeElimination typeUpdater.maybeUpdateTypeToUnreachable(curr); } + static void doBeforeTryBody(DeadCodeElimination* self, Expression** currp) { + self->tryStack.push_back(self->reachable); + } + + static void doAfterTryBody(DeadCodeElimination* self, Expression** currp) { + bool reachableBefore = self->tryStack.back(); + self->tryStack.pop_back(); + self->tryStack.push_back(self->reachable); + self->reachable = reachableBefore; + } + + void visitTry(Try* curr) { + // the tryStack has the branch that joins us + reachable = reachable || tryStack.back(); + tryStack.pop_back(); + // the try may have had a type, but can now be unreachable, which allows + // more reduction outside + typeUpdater.maybeUpdateTypeToUnreachable(curr); + } + static void scan(DeadCodeElimination* self, Expression** currp) { auto* curr = *currp; if (!self->reachable) { @@ -349,6 +372,12 @@ struct DeadCodeElimination self->pushTask(DeadCodeElimination::scan, &curr->cast<If>()->ifTrue); self->pushTask(DeadCodeElimination::doAfterIfCondition, currp); self->pushTask(DeadCodeElimination::scan, &curr->cast<If>()->condition); + } else if (curr->is<Try>()) { + self->pushTask(DeadCodeElimination::doVisitTry, currp); + self->pushTask(DeadCodeElimination::scan, &curr->cast<Try>()->catchBody); + self->pushTask(DeadCodeElimination::doAfterTryBody, currp); + self->pushTask(DeadCodeElimination::scan, &curr->cast<Try>()->body); + self->pushTask(DeadCodeElimination::doBeforeTryBody, currp); } else { super::scan(self, currp); } diff --git a/test/passes/dce.txt b/test/passes/dce_all-features.txt index 6c7b6ca3a..f9e1b70a4 100644 --- a/test/passes/dce.txt +++ b/test/passes/dce_all-features.txt @@ -501,3 +501,34 @@ ) ) ) +(module + (type $FUNCSIG$v (func)) + (func $foo (; 0 ;) (type $FUNCSIG$v) + (nop) + ) + (func $try_unreachable (; 1 ;) (type $FUNCSIG$v) + (try + (unreachable) + (catch + ) + ) + (call $foo) + ) + (func $catch_unreachable (; 2 ;) (type $FUNCSIG$v) + (try + (nop) + (catch + (unreachable) + ) + ) + (call $foo) + ) + (func $both_unreachable (; 3 ;) (type $FUNCSIG$v) + (try + (unreachable) + (catch + (unreachable) + ) + ) + ) +) diff --git a/test/passes/dce.wast b/test/passes/dce_all-features.wast index 0d3b04557..c6fe0d5d0 100644 --- a/test/passes/dce.wast +++ b/test/passes/dce_all-features.wast @@ -734,3 +734,37 @@ ) ) +;; Exception handling instruction support +;; If either try body or catch body is reachable, the whole try construct is +;; reachable +(module + (func $foo) + + (func $try_unreachable + (try + (unreachable) + (catch + ) + ) + (call $foo) ;; shouldn't be dce'd + ) + + (func $catch_unreachable + (try + (catch + (unreachable) + ) + ) + (call $foo) ;; shouldn't be dce'd + ) + + (func $both_unreachable + (try + (unreachable) + (catch + (unreachable) + ) + ) + (call $foo) ;; should be dce'd + ) +) |