summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/type-updating.h15
-rw-r--r--src/passes/DeadCodeElimination.cpp31
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);
}