summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/MergeBlocks.cpp23
-rw-r--r--test/passes/remove-unused-names_merge-blocks_all-features.txt (renamed from test/passes/remove-unused-names_merge-blocks_enable-threads.txt)47
-rw-r--r--test/passes/remove-unused-names_merge-blocks_all-features.wast (renamed from test/passes/remove-unused-names_merge-blocks_enable-threads.wast)57
3 files changed, 126 insertions, 1 deletions
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index ab368429f..1401cd2f4 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -129,6 +129,11 @@ struct ProblemFinder : public ControlFlowWalker<ProblemFinder> {
}
}
+ void visitBrOnExn(BrOnExn* curr) {
+ // We should not take exnref value out of br_on_exn
+ foundProblem = true;
+ }
+
bool found() {
assert(brIfs >= droppedBrIfs);
return foundProblem || brIfs > droppedBrIfs;
@@ -526,6 +531,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
void visitBreak(Break* curr) {
optimize(curr, curr->condition, optimize(curr, curr->value), &curr->value);
}
+
void visitSwitch(Switch* curr) {
optimize(curr, curr->condition, optimize(curr, curr->value), &curr->value);
}
@@ -540,7 +546,6 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
}
outer = optimize(curr, curr->operands[i], outer);
}
- return;
}
void visitCall(Call* curr) { handleCall(curr); }
@@ -561,6 +566,22 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
}
optimize(curr, curr->target, outer);
}
+
+ void visitThrow(Throw* curr) {
+ Block* outer = nullptr;
+ for (Index i = 0; i < curr->operands.size(); i++) {
+ if (EffectAnalyzer(
+ getPassOptions(), getModule()->features, curr->operands[i])
+ .hasSideEffects()) {
+ return;
+ }
+ outer = optimize(curr, curr->operands[i], outer);
+ }
+ }
+
+ void visitRethrow(Rethrow* curr) { optimize(curr, curr->exnref); }
+
+ void visitBrOnExn(BrOnExn* curr) { optimize(curr, curr->exnref); }
};
Pass* createMergeBlocksPass() { return new MergeBlocks(); }
diff --git a/test/passes/remove-unused-names_merge-blocks_enable-threads.txt b/test/passes/remove-unused-names_merge-blocks_all-features.txt
index cf37ebc9d..90a56d32d 100644
--- a/test/passes/remove-unused-names_merge-blocks_enable-threads.txt
+++ b/test/passes/remove-unused-names_merge-blocks_all-features.txt
@@ -1697,3 +1697,50 @@
)
)
)
+(module
+ (type $none_=>_none (func))
+ (type $i32_=>_none (func (param i32)))
+ (type $none_=>_i32 (func (result i32)))
+ (event $e (attr 0) (param i32))
+ (func $foo
+ (nop)
+ )
+ (func $throw
+ (nop)
+ (throw $e
+ (i32.const 3)
+ )
+ )
+ (func $rethrow
+ (local $0 exnref)
+ (call $foo)
+ (rethrow
+ (local.get $0)
+ )
+ )
+ (func $br_on_exn (result i32)
+ (local $0 exnref)
+ (block $label$0 (result i32)
+ (call $foo)
+ (drop
+ (br_on_exn $label$0 $e
+ (local.get $0)
+ )
+ )
+ (i32.const 3)
+ )
+ )
+ (func $cannot_extract_br_on_exn_exnref
+ (local $0 exnref)
+ (drop
+ (block $label$0 (result i32)
+ (drop
+ (br_on_exn $label$0 $e
+ (local.get $0)
+ )
+ )
+ (i32.const 5)
+ )
+ )
+ )
+)
diff --git a/test/passes/remove-unused-names_merge-blocks_enable-threads.wast b/test/passes/remove-unused-names_merge-blocks_all-features.wast
index f9603a60d..9a6840650 100644
--- a/test/passes/remove-unused-names_merge-blocks_enable-threads.wast
+++ b/test/passes/remove-unused-names_merge-blocks_all-features.wast
@@ -1556,3 +1556,60 @@
)
)
)
+
+(module
+ (event $e (attr 0) (param i32))
+ (func $foo)
+
+ ;; 'nop' within 'block' of `throw' can be hoisted
+ (func $throw
+ (throw $e
+ (block (result i32)
+ (nop)
+ (i32.const 3)
+ )
+ )
+ )
+
+ ;; 'call $foo' within 'block' of `rethrow' can be hoisted
+ (func $rethrow (local $0 exnref)
+ (rethrow
+ (block (result exnref)
+ (call $foo)
+ (local.get $0)
+ )
+ )
+ )
+
+ ;; 'call $foo' within 'block' of `br_on_exn' can be hoisted
+ (func $br_on_exn (result i32) (local $0 exnref)
+ (block $label$0 (result i32)
+ (drop
+ (br_on_exn $label$0 $e
+ (block (result exnref)
+ (call $foo)
+ (local.get $0)
+ )
+ )
+ )
+ (i32.const 3)
+ )
+ )
+
+ ;; Unlike br_if, br_on_exn's exnref argument itself cannot be extracted.
+ ;; Without proper handling for br_on_exn in ProblemFinder, this crashes.
+ (func $cannot_extract_br_on_exn_exnref (local $0 exnref)
+ (block
+ (drop
+ (block $label$0 (result i32)
+ (drop
+ (br_on_exn $label$0 $e
+ (local.get $0)
+ )
+ )
+ (i32.const 5)
+ )
+ )
+ )
+ )
+)