Skip to content

RemoveUnusedBrs: optimize unreachable control flow mixed with side-effecting branches #7639

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

Merged
merged 27 commits into from
Jun 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8b5a617
opt for #7637
xuruiyang2002 Jun 4, 2025
b9db9cf
tests
xuruiyang2002 Jun 4, 2025
223bfc0
add a test
xuruiyang2002 Jun 4, 2025
1f44ad6
Add comments
xuruiyang2002 Jun 4, 2025
1feb9ca
Use ChildLocalizer if there is no curr->value
xuruiyang2002 Jun 5, 2025
df10dce
Update test
xuruiyang2002 Jun 5, 2025
bae9749
NFC
xuruiyang2002 Jun 5, 2025
6eafa8c
Bugfix
xuruiyang2002 Jun 5, 2025
3dacea0
refinalize the type
xuruiyang2002 Jun 6, 2025
e41f344
Add test of two-branches-unreachable
xuruiyang2002 Jun 6, 2025
abbe4ce
Use auto_update script
xuruiyang2002 Jun 6, 2025
08234b3
Add export to make CHECK lines appear
xuruiyang2002 Jun 12, 2025
05f8a1a
work
xuruiyang2002 Jun 12, 2025
ed25e75
Update tests
xuruiyang2002 Jun 12, 2025
904b4ef
Update also
xuruiyang2002 Jun 12, 2025
9eca5a3
Remove unused include
xuruiyang2002 Jun 13, 2025
0252851
NFC: format the comments
xuruiyang2002 Jun 13, 2025
71c2082
Only one replaceCurrent
xuruiyang2002 Jun 13, 2025
e6116dc
Remove unused case
xuruiyang2002 Jun 15, 2025
8e92604
fine tune to make the irrelevant test case change minimal
xuruiyang2002 Jun 15, 2025
572e9ee
Update the comments
xuruiyang2002 Jun 17, 2025
832126d
Revert remove-unused-brs_shrink-level=1.wast (and .txt), use params
xuruiyang2002 Jun 17, 2025
fccf9fb
Revert remove-unused-brs_shrink-level=1__ignore-implicit-traps.wast (…
xuruiyang2002 Jun 17, 2025
3d1f166
Update also
xuruiyang2002 Jun 17, 2025
1dcd61b
Update tests, keep minimal change
xuruiyang2002 Jun 18, 2025
c036d3f
Amend remove-unused-brs_shrink-level=1.txt
xuruiyang2002 Jun 18, 2025
6cd9924
Update
xuruiyang2002 Jun 20, 2025
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
32 changes: 32 additions & 0 deletions src/passes/RemoveUnusedBrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "ir/effects.h"
#include "ir/gc-type-utils.h"
#include "ir/literal-utils.h"
#include "ir/localize.h"
#include "ir/properties.h"
#include "ir/utils.h"
#include "parsing.h"
#include "pass.h"
Expand Down Expand Up @@ -1881,6 +1883,36 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
start = end;
}
}

void visitBreak(Break* curr) {
if (!curr->condition) {
return;
}
auto* value = Properties::getFallthrough(
curr->condition, passOptions, *getModule());
// Optimize if condition's fallthrough is a constant.
if (auto* c = value->dynCast<Const>()) {
ChildLocalizer localizer(
curr, getFunction(), *getModule(), passOptions);
auto* block = localizer.getChildrenReplacement();
if (c->value.geti32()) {
// the branch is always taken, make it unconditional
curr->condition = nullptr;
curr->type = Type::unreachable;
block->list.push_back(curr);
block->finalize();
// The type changed, so refinalize.
refinalize = true;
} else {
// the branch is never taken, allow control flow to fall through
if (curr->value) {
block->list.push_back(curr->value);
block->finalize();
}
}
replaceCurrent(block);
}
}
};
FinalOptimizer finalOptimizer(getPassOptions());
finalOptimizer.setModule(getModule());
Expand Down
114 changes: 108 additions & 6 deletions test/lit/passes/remove-unused-brs.wast
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

(module
;; Regression test in which we need to calculate a proper LUB.
;; CHECK: (func $selectify-fresh-lub (type $4) (param $x i32) (result anyref)
;; CHECK: (func $selectify-fresh-lub (type $5) (param $x i32) (result anyref)
;; CHECK-NEXT: (select (result i31ref)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (ref.i31
Expand Down Expand Up @@ -340,6 +340,106 @@
)
)

;; CHECK: (func $restructure-br_if-constant-branch-1 (type $3) (param $x i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $x (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (local.tee $x
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $x
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $x0 (result i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 20)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $restructure-br_if-constant-branch-1 (param $x i32)
;; We can see a nonzero constant falls through the tee, so this br always happens.
(drop
(block $x (result i32)
(drop
(br_if $x
(i32.const 10)
(local.tee $x
(i32.const 42)
)
)
)
(i32.const 20)
)
)
;; We can see the zero condition, so just let the control flow fall through.
(drop
(block $x (result i32)
(drop
(br_if $x
(i32.const 10)
(i32.const 0)
)
)
(i32.const 20)
)
)
)
;; CHECK: (func $restructure-br_if-constant-branch-2 (type $3) (param $x i32)
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local $2 i32)
;; CHECK-NEXT: (block $x
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (local.tee $x
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $x0
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (local.tee $x
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $restructure-br_if-constant-branch-2 (param $x i32)
;; as before, but now there is no value.
(block $x
(br_if $x
(local.tee $x
(i32.const 1)
)
)
)
(block $x
(br_if $x
(local.tee $x
(i32.const 0)
)
)
)
)


;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-1 (type $2) (result i32)
;; CHECK-NEXT: (block $parent (result i32)
;; CHECK-NEXT: (call $nothing)
Expand Down Expand Up @@ -473,7 +573,7 @@
;; CHECK-NEXT: (br_if $block
;; CHECK-NEXT: (local.get $temp)
;; CHECK-NEXT: (local.tee $temp
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (local.get $temp)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
Expand All @@ -489,7 +589,7 @@
(br_if $block
(local.get $temp)
(local.tee $temp
(i32.const 1)
(local.get $temp)
)
)
)
Expand All @@ -498,8 +598,9 @@
)

;; CHECK: (func $restructure-select-no-multivalue (type $1)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (tuple.drop 2
;; CHECK-NEXT: (block $block (type $3) (result i32 i32)
;; CHECK-NEXT: (block $block (type $4) (result i32 i32)
;; CHECK-NEXT: (tuple.drop 2
;; CHECK-NEXT: (br_if $block
;; CHECK-NEXT: (tuple.make 2
Expand All @@ -508,7 +609,7 @@
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 3)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.make 2
Expand All @@ -519,6 +620,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $restructure-select-no-multivalue
(local $x i32)
(tuple.drop 2
(block $block (result i32 i32)
(tuple.drop 2
Expand All @@ -533,7 +635,7 @@
(i32.const 2)
)
)
(i32.const 3)
(local.get $x)
)
)
(tuple.make 2
Expand Down
6 changes: 4 additions & 2 deletions test/lit/passes/remove-unused-brs_all-features.wast
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@
)

;; CHECK: (func $test-prefinalize (type $4) (result f64)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (loop $loop (result f64)
;; CHECK-NEXT: (if (result f64)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (then
;; CHECK-NEXT: (f64.const 0)
;; CHECK-NEXT: )
Expand All @@ -85,12 +86,13 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $test-prefinalize (result f64)
(local $x i32)
(loop $loop (result f64)
(block $block (result f64)
(drop
(br_if $block
(f64.const 0)
(i32.const 1)
(local.get $x)
)
)
(if
Expand Down
Loading
Loading