summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/type-updating.h15
-rw-r--r--src/passes/DeadCodeElimination.cpp31
-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
+ )
+)