From cd887c2b87e9edb6ca4634f7a9c3e906d2d1788c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2024 16:07:11 -0800 Subject: [PATCH 1/3] fix --- src/passes/RemoveUnusedBrs.cpp | 12 +++++++++++- test/lit/passes/remove-unused-brs-gc.wast | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 96db281d87f..68fc12907f1 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -1146,6 +1146,7 @@ struct RemoveUnusedBrs : public WalkerPass> { PassOptions& passOptions; bool needUniqify = false; + bool refinalize = false; FinalOptimizer(PassOptions& passOptions) : passOptions(passOptions) {} @@ -1419,8 +1420,14 @@ struct RemoveUnusedBrs : public WalkerPass> { if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) { return nullptr; } - return Builder(*getModule()) + 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> { 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 0a9e0885873..41973a77bac 100644 --- a/test/lit/passes/remove-unused-brs-gc.wast +++ b/test/lit/passes/remove-unused-brs-gc.wast @@ -864,4 +864,22 @@ ) ) ) + + (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) + ) + ) ) From 32ba204d3d482693d9ce78ce5140424c5972892f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2024 16:08:14 -0800 Subject: [PATCH 2/3] update --- test/lit/passes/remove-unused-brs-gc.wast | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/lit/passes/remove-unused-brs-gc.wast b/test/lit/passes/remove-unused-brs-gc.wast index 41973a77bac..fa7a6d72739 100644 --- a/test/lit/passes/remove-unused-brs-gc.wast +++ b/test/lit/passes/remove-unused-brs-gc.wast @@ -865,6 +865,17 @@ ) ) + ;; 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. From 58ce3430c1fe3761ce123310124ad9d852dfb746 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2024 16:09:47 -0800 Subject: [PATCH 3/3] format --- src/passes/RemoveUnusedBrs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 68fc12907f1..44549f68dff 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -1421,7 +1421,7 @@ struct RemoveUnusedBrs : public WalkerPass> { return nullptr; } auto* select = Builder(*getModule()) - .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse); + .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.