From 5db77a72a7c62d045e6650e96974fe1455fa1a1a Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Wed, 13 May 2020 17:10:59 -0700 Subject: 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`. --- src/passes/MergeBlocks.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src/passes/MergeBlocks.cpp') 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 { } } + 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> { 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> { } outer = optimize(curr, curr->operands[i], outer); } - return; } void visitCall(Call* curr) { handleCall(curr); } @@ -561,6 +566,22 @@ struct MergeBlocks : public WalkerPass> { } 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(); } -- cgit v1.2.3