diff options
-rw-r--r-- | src/ir/effects.h | 10 | ||||
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 10 | ||||
-rw-r--r-- | test/passes/simplify-locals_all-features.txt | 46 | ||||
-rw-r--r-- | test/passes/simplify-locals_all-features.wast | 41 |
4 files changed, 102 insertions, 5 deletions
diff --git a/src/ir/effects.h b/src/ir/effects.h index 4f3af012f..55c78f05a 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -446,8 +446,16 @@ struct EffectAnalyzer if (tryDepth == 0) { throws = true; } + if (!ignoreImplicitTraps) { // rethrow traps when the arg is null + implicitTrap = true; + } + } + void visitBrOnExn(BrOnExn* curr) { + breakNames.insert(curr->name); + if (!ignoreImplicitTraps) { // br_on_exn traps when the arg is null + implicitTrap = true; + } } - void visitBrOnExn(BrOnExn* curr) { breakNames.insert(curr->name); } void visitNop(Nop* curr) {} void visitUnreachable(Unreachable* curr) { branches = true; } void visitPush(Push* curr) { calls = true; } diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 23ab1bc92..2f269a00d 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -126,8 +126,7 @@ struct SimplifyLocals Expression** currp) { // Main processing. auto* curr = *currp; - if (curr->is<Break>()) { - auto* br = curr->cast<Break>(); + if (auto* br = curr->dynCast<Break>()) { if (br->value) { // value means the block already has a return value self->unoptimizableBlocks.insert(br->name); @@ -147,6 +146,10 @@ struct SimplifyLocals self->unoptimizableBlocks.insert(target); } // TODO: we could use this info to stop gathering data on these blocks + } else if (auto* br = curr->dynCast<BrOnExn>()) { + // We cannot optimize the block this targets to have a return value, as + // the br_on_exn doesn't support a change to the block's type + self->unoptimizableBlocks.insert(br->name); } self->sinkables.clear(); } @@ -162,10 +165,9 @@ struct SimplifyLocals static void doNoteIfTrue(SimplifyLocals<allowTee, allowStructure, allowNesting>* self, Expression** currp) { - auto* iff = (*currp)->dynCast<If>(); + auto* iff = (*currp)->cast<If>(); if (iff->ifFalse) { // We processed the ifTrue side of this if-else, save it on the stack. - assert((*currp)->cast<If>()->ifFalse); self->ifStack.push_back(std::move(self->sinkables)); } else { // This is an if without an else. diff --git a/test/passes/simplify-locals_all-features.txt b/test/passes/simplify-locals_all-features.txt index d5937fabb..4a003360d 100644 --- a/test/passes/simplify-locals_all-features.txt +++ b/test/passes/simplify-locals_all-features.txt @@ -1892,3 +1892,49 @@ (local.get $0) ) ) +(module + (type $none_=>_none (func)) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_exnref (func (result exnref))) + (event $event$0 (attr 0) (param)) + (event $event$1 (attr 0) (param exnref)) + (func $unoptimizable-br_on_exn-block (result exnref) + (local $0 exnref) + (block $label$0 + (local.set $0 + (br_on_exn $label$0 $event$0 + (ref.null) + ) + ) + ) + (local.get $0) + ) + (func $br_on_exn-trap + (local $0 exnref) + (drop + (block $label$1 (result exnref) + (br_on_exn $label$1 $event$1 + (ref.null) + ) + ) + ) + ) + (func $rethrow-trap + (local $0 i32) + (drop + (block $label$1 (result i32) + (try + (do + (rethrow + (ref.null) + ) + ) + (catch + (nop) + ) + ) + (i32.const 0) + ) + ) + ) +) diff --git a/test/passes/simplify-locals_all-features.wast b/test/passes/simplify-locals_all-features.wast index a819dda15..bfe86f448 100644 --- a/test/passes/simplify-locals_all-features.wast +++ b/test/passes/simplify-locals_all-features.wast @@ -1671,3 +1671,44 @@ (local.get $1) ) ) +(module + (event $event$0 (attr 0) (param)) + (func $unoptimizable-br_on_exn-block (result exnref) (local $0 exnref) + (block $label$0 + (local.set $0 + ;; br_on_exn's target block cannot be optimized to have a return value + (br_on_exn $label$0 $event$0 + (ref.null) + ) + ) + ) + (local.get $0) + ) + + (event $event$1 (attr 0) (param exnref)) + (func $br_on_exn-trap (local $0 exnref) + ;; This dead local.set cannot be replaced with a nop because br_on_exn can + ;; trap. + (local.set $0 + (block $label$1 (result exnref) + (br_on_exn $label$1 $event$1 + (ref.null) + ) + ) + ) + ) + + (func $rethrow-trap (local $0 i32) + ;; This dead local.set cannot be replaced with a nop because rethrow can + ;; trap. + (local.set $0 + (block $label$1 (result i32) + (try + (do (rethrow (ref.null))) + (catch) + ) + (i32.const 0) + ) + ) + ) +) |