summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-11-25 09:33:10 -0800
committerGitHub <noreply@github.com>2024-11-25 09:33:10 -0800
commit3d394018fe30e5d7ea153c975a158b95c1720393 (patch)
tree18fd87113f0347cc3238d9cb3a398f7dc1a0cc71
parentca61aeeb87e330635548ce6368ac053576ee994c (diff)
downloadbinaryen-3d394018fe30e5d7ea153c975a158b95c1720393.tar.gz
binaryen-3d394018fe30e5d7ea153c975a158b95c1720393.tar.bz2
binaryen-3d394018fe30e5d7ea153c975a158b95c1720393.zip
[GC] Refinalize after selectify in RemoveUnusedBrs (#7104)
Replacing an if with a select may have refined the type. Without this fix, the sharper stale type checks complain.
-rw-r--r--src/passes/RemoveUnusedBrs.cpp14
-rw-r--r--test/lit/passes/remove-unused-brs-gc.wast29
2 files changed, 41 insertions, 2 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 96db281d8..44549f68d 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -1146,6 +1146,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
PassOptions& passOptions;
bool needUniqify = false;
+ bool refinalize = false;
FinalOptimizer(PassOptions& passOptions) : passOptions(passOptions) {}
@@ -1419,8 +1420,14 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) {
return nullptr;
}
- return Builder(*getModule())
- .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
+ auto* select = Builder(*getModule())
+ .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
+ if (select->type != iff->type) {
+ // If the select is more refined than the if it replaces, we must
+ // propagate that outwards.
+ refinalize = true;
+ }
+ return select;
}
void visitLocalSet(LocalSet* curr) {
@@ -1793,6 +1800,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (finalOptimizer.needUniqify) {
wasm::UniqueNameMapper::uniquify(func->body);
}
+ if (finalOptimizer.refinalize) {
+ ReFinalize().walkFunctionInModule(func, getModule());
+ }
}
};
diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast
index 0a9e08858..fa7a6d727 100644
--- a/test/lit/passes/remove-unused-brs-gc.wast
+++ b/test/lit/passes/remove-unused-brs-gc.wast
@@ -864,4 +864,33 @@
)
)
)
+
+ ;; CHECK: (func $select-refinalize (type $13) (param $param (ref $struct)) (result (ref struct))
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (struct.new_default $struct)
+ ;; CHECK-NEXT: (struct.new_default $struct)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $param)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $select-refinalize (param $param (ref $struct)) (result (ref struct))
+ ;; The inner if can turn into a select. The type then changes, allowing the
+ ;; outer select to be refined, which will error if we do not refinalize.
+ (select (result (ref struct))
+ (if (result (ref struct))
+ (i32.const 0)
+ (then
+ (struct.new_default $struct)
+ )
+ (else
+ (struct.new_default $struct)
+ )
+ )
+ (local.get $param)
+ (i32.const 0)
+ )
+ )
)