diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/type-updating.h | 15 | ||||
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 31 |
2 files changed, 45 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); } |