Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeFolding: Fix up old EH when we fold away an If #6420

Merged
merged 2 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/passes/CodeFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include <iterator>

#include "ir/branch-utils.h"
#include "ir/eh-utils.h"
#include "ir/effects.h"
#include "ir/find_all.h"
#include "ir/label-utils.h"
Expand Down Expand Up @@ -119,7 +120,11 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {

// state

// Set when we optimized and believe another pass is warranted.
bool anotherPass;
// Set when we optimized in a manner that requires EH fixups specifically,
// which is generally the case when we wrap things in a block.
bool needEHFixups;

// pass state

Expand Down Expand Up @@ -229,6 +234,7 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
// we must ensure we present the same type as the if had
ret->finalize(curr->type);
replaceCurrent(ret);
needEHFixups = true;
} else {
// if both are blocks, look for a tail we can merge
auto* left = curr->ifTrue->dynCast<Block>();
Expand Down Expand Up @@ -266,6 +272,7 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
anotherPass = true;
while (anotherPass) {
anotherPass = false;
needEHFixups = false;
super::doWalkFunction(func);
optimizeTerminatingTails(unreachableTails);
// optimize returns at the end, so we can benefit from a fallthrough if
Expand All @@ -279,6 +286,9 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
returnTails.clear();
unoptimizables.clear();
modifieds.clear();
if (needEHFixups) {
EHUtils::handleBlockNestedPops(func, *getModule());
}
// if we did any work, types may need to be propagated
if (anotherPass) {
ReFinalize().walkFunctionInModule(func, getModule());
Expand Down Expand Up @@ -488,6 +498,7 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
// ensure the replacement has the same type, so the outside is not surprised
block->finalize(oldType);
replaceCurrent(block);
needEHFixups = true;
}

// optimize tails that terminate control flow in this function, so we
Expand Down Expand Up @@ -745,6 +756,7 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
// ensure the replacement has the same type, so the outside is not surprised
outer->finalize(getFunction()->getResults());
getFunction()->body = outer;
needEHFixups = true;
return true;
}

Expand Down
58 changes: 57 additions & 1 deletion test/lit/passes/code-folding-eh-old.wast
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
;; CHECK-NEXT: )
(func $foo)

;; CHECK: (func $try-call-optimize-terminating-tails (type $2) (result i32)
;; CHECK: (func $try-call-optimize-terminating-tails (type $1) (result i32)
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (call $foo)
Expand Down Expand Up @@ -155,4 +155,60 @@
(unreachable)
)
)

;; CHECK: (func $if-arms-in-catch (type $1) (result i32)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $e-i32
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (pop i32)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $if-arms-in-catch (result i32)
(try
(do
(unreachable)
)
(catch $e-i32
;; These if arms can be folded, after which the if is replaced by a
;; block, so we need a fixup for the pop.
(if
(pop i32)
(then
(drop
(i32.eqz
(i32.const 1)
)
)
)
(else
(drop
(i32.eqz
(i32.const 1)
)
)
)
)
(unreachable)
)
)
)
)
Loading