diff options
-rw-r--r-- | src/passes/Vacuum.cpp | 13 | ||||
-rw-r--r-- | test/lit/passes/vacuum-eh.wast | 39 |
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) + ) + ) ) |