diff options
-rw-r--r-- | src/passes/MergeBlocks.cpp | 23 | ||||
-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) + ) + ) + ) + ) +) |