diff options
author | Heejin Ahn <aheejin@gmail.com> | 2020-05-13 17:10:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-13 17:10:59 -0700 |
commit | 5db77a72a7c62d045e6650e96974fe1455fa1a1a (patch) | |
tree | d4b32705b0c6090d6763063025fc503ba650c8cf /src/passes/MergeBlocks.cpp | |
parent | 5930ada5bee7061d8063f2638cdb1cb25dce5292 (diff) | |
download | binaryen-5db77a72a7c62d045e6650e96974fe1455fa1a1a.tar.gz binaryen-5db77a72a7c62d045e6650e96974fe1455fa1a1a.tar.bz2 binaryen-5db77a72a7c62d045e6650e96974fe1455fa1a1a.zip |
Add EH support in MergeBlocks (#2848)
This adds support for `throw`, `rethrow`, and `br_on_exn` in
MergeBlocks. While unrelated instructions within blocks can be hoisted
as in other instructions, `br_on_exn` requires a special handling in
`ProblemFinder`, because unlike `br_if`, its `exnref` argument itself
cannot be moved out of `br_on_exn`.
Diffstat (limited to 'src/passes/MergeBlocks.cpp')
-rw-r--r-- | src/passes/MergeBlocks.cpp | 23 |
1 files changed, 22 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(); } |