diff --git a/src/ir/effects.h b/src/ir/effects.h index 6901f99de2d..b5210f1e7cc 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -478,7 +478,7 @@ class EffectAnalyzer { // the target function throws and we know that will be caught anyhow, // the same as the code below for the general path. const auto& targetEffects = iter->second; - if (targetEffects.throws_ && parent.tryDepth > 0) { + if (targetEffects.throws_ && parent.tryDepth > 0 && !curr->isReturn) { auto filteredEffects = targetEffects; filteredEffects.throws_ = false; parent.mergeIn(filteredEffects); @@ -492,13 +492,15 @@ class EffectAnalyzer { parent.calls = true; // When EH is enabled, any call can throw. - if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { + if (parent.features.hasExceptionHandling() && + (parent.tryDepth == 0 || curr->isReturn)) { parent.throws_ = true; } } void visitCallIndirect(CallIndirect* curr) { parent.calls = true; - if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { + if (parent.features.hasExceptionHandling() && + (parent.tryDepth == 0 || curr->isReturn)) { parent.throws_ = true; } if (curr->isReturn) { @@ -750,7 +752,8 @@ class EffectAnalyzer { return; } parent.calls = true; - if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { + if (parent.features.hasExceptionHandling() && + (parent.tryDepth == 0 || curr->isReturn)) { parent.throws_ = true; } if (curr->isReturn) { diff --git a/test/lit/passes/global-effects.wast b/test/lit/passes/global-effects.wast index d0d3228df5a..c4221c0eaf4 100644 --- a/test/lit/passes/global-effects.wast +++ b/test/lit/passes/global-effects.wast @@ -450,4 +450,77 @@ (call $cycle-with-unknown-call) (call $import) ) + + ;; WITHOUT: (func $throw-through-return-call (type $0) + ;; WITHOUT-NEXT: (try $try + ;; WITHOUT-NEXT: (do + ;; WITHOUT-NEXT: (return_call $throw) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: (catch_all + ;; WITHOUT-NEXT: (nop) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: ) + ;; INCLUDE: (func $throw-through-return-call (type $0) + ;; INCLUDE-NEXT: (try $try + ;; INCLUDE-NEXT: (do + ;; INCLUDE-NEXT: (return_call $throw) + ;; INCLUDE-NEXT: ) + ;; INCLUDE-NEXT: (catch_all + ;; INCLUDE-NEXT: (nop) + ;; INCLUDE-NEXT: ) + ;; INCLUDE-NEXT: ) + ;; INCLUDE-NEXT: ) + ;; DISCARD: (func $throw-through-return-call (type $0) + ;; DISCARD-NEXT: (try $try + ;; DISCARD-NEXT: (do + ;; DISCARD-NEXT: (return_call $throw) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: (catch_all + ;; DISCARD-NEXT: (nop) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: ) + (func $throw-through-return-call + ;; The exception is not catched, so this code cannot be simplified + (try + (do + (return_call $throw) + ) + (catch_all) + ) + ) + + ;; WITHOUT: (func $catch-all-effects (type $0) + ;; WITHOUT-NEXT: (try $try + ;; WITHOUT-NEXT: (do + ;; WITHOUT-NEXT: (call $throw-through-return-call) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: (catch_all + ;; WITHOUT-NEXT: (nop) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: ) + ;; WITHOUT-NEXT: ) + ;; INCLUDE: (func $catch-all-effects (type $0) + ;; INCLUDE-NEXT: (nop) + ;; INCLUDE-NEXT: ) + ;; DISCARD: (func $catch-all-effects (type $0) + ;; DISCARD-NEXT: (try $try + ;; DISCARD-NEXT: (do + ;; DISCARD-NEXT: (call $throw-through-return-call) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: (catch_all + ;; DISCARD-NEXT: (nop) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: ) + ;; DISCARD-NEXT: ) + (func $catch-all-effects + ;; The exception is catched, so the function body can be optimized away + (try + (do + (call $throw-through-return-call) + ) + (catch_all) + ) + ) )