summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-09-16 08:55:07 -0700
committerGitHub <noreply@github.com>2022-09-16 08:55:07 -0700
commit3892b0bbe0aa0e57864e6785e43d33e89d39000b (patch)
tree4f7d0b968a680d6adb6f54a3a71b7ceacb8d0575
parent989489020e635d35870b22894a5d129c8c55d640 (diff)
downloadbinaryen-3892b0bbe0aa0e57864e6785e43d33e89d39000b.tar.gz
binaryen-3892b0bbe0aa0e57864e6785e43d33e89d39000b.tar.bz2
binaryen-3892b0bbe0aa0e57864e6785e43d33e89d39000b.zip
Vacuum trivial trys (#5046)
A try whose body throws, and does nothing else, and the try catches that exception, can be removed.
-rw-r--r--src/passes/Vacuum.cpp13
-rw-r--r--test/lit/passes/vacuum-eh.wast39
2 files changed, 52 insertions, 0 deletions
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 6adab04e9..208e973da 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -365,6 +365,19 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
for (auto* catchBody : curr->catchBodies) {
typeUpdater.noteRecursiveRemoval(catchBody);
}
+ return;
+ }
+
+ // The try's body does throw. However, throwing may be the only thing it
+ // does, and if the try has a catch-all, then the entire try including
+ // children may have no effects. Note that this situation can only happen
+ // if we do have a catch-all, so avoid wasted work by checking that first.
+ // Also, we can't do this if a result is returned, so check the type.
+ if (curr->type == Type::none && curr->hasCatchAll() &&
+ !EffectAnalyzer(getPassOptions(), *getModule(), curr)
+ .hasUnremovableSideEffects()) {
+ typeUpdater.noteRecursiveRemoval(curr);
+ ExpressionManipulator::nop(curr);
}
}
diff --git a/test/lit/passes/vacuum-eh.wast b/test/lit/passes/vacuum-eh.wast
index 574a525bc..de0eb0e1a 100644
--- a/test/lit/passes/vacuum-eh.wast
+++ b/test/lit/passes/vacuum-eh.wast
@@ -176,4 +176,43 @@
)
)
)
+
+ ;; CHECK: (func $trivial-catch-all-of-throw
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (try $try3
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $trivial-catch-all-of-throw (local $0 i32)
+ ;; This try-catch's body throws, but the catch-all catches it, so the entire
+ ;; try can be optimized out.
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all)
+ )
+ ;; Here we also have a possible trap, so we can't do it.
+ (try
+ (do
+ (if
+ (local.get $0)
+ (throw $e (i32.const 0))
+ (unreachable)
+ )
+ )
+ (catch_all)
+ )
+ )
)