summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/effects.h10
-rw-r--r--src/passes/SimplifyLocals.cpp10
-rw-r--r--test/passes/simplify-locals_all-features.txt46
-rw-r--r--test/passes/simplify-locals_all-features.wast41
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)
+ )
+ )
+ )
+)