Skip to content

Commit 4455853

Browse files
authored
remove-unused-brs: do not flow a value through a block if the block does not actually flow a value. fixes #1833 (#1835)
1 parent af0ff22 commit 4455853

File tree

3 files changed

+81
-14
lines changed

3 files changed

+81
-14
lines changed

src/passes/RemoveUnusedBrs.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
106106
} else if (auto* block = curr->dynCast<Block>()) {
107107
// any breaks flowing to here are unnecessary, as we get here anyhow
108108
auto name = block->name;
109+
auto& list = block->list;
109110
if (name.is()) {
110-
size_t size = flows.size();
111-
size_t skip = 0;
112-
for (size_t i = 0; i < size; i++) {
111+
Index size = flows.size();
112+
Index skip = 0;
113+
for (Index i = 0; i < size; i++) {
113114
auto* flow = (*flows[i])->dynCast<Break>();
114115
if (flow && flow->name == name) {
115116
if (!flow->value) {
@@ -129,11 +130,22 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
129130
flows.resize(size - skip);
130131
}
131132
// drop a nop at the end of a block, which prevents a value flowing
132-
while (block->list.size() > 0 && block->list.back()->is<Nop>()) {
133-
block->list.resize(block->list.size() - 1);
133+
while (list.size() > 0 && list.back()->is<Nop>()) {
134+
list.resize(list.size() - 1);
134135
self->anotherCycle = true;
135136
}
136137
}
138+
// A value flowing is only valid if it is a value that the block actually
139+
// flows out. If it is never reached, it does not flow out, and may be
140+
// invalid to represent as such.
141+
auto size = list.size();
142+
for (Index i = 0; i < size; i++) {
143+
if (i != size - 1 && list[i]->type == unreachable) {
144+
// No value flows out of this block.
145+
self->stopValueFlow();
146+
break;
147+
}
148+
}
137149
} else if (curr->is<Nop>()) {
138150
// ignore (could be result of a previous cycle)
139151
self->stopValueFlow();
@@ -515,7 +527,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
515527
super::doWalkFunction(func);
516528
assert(ifStack.empty());
517529
// flows may contain returns, which are flowing out and so can be optimized
518-
for (size_t i = 0; i < flows.size(); i++) {
530+
for (Index i = 0; i < flows.size(); i++) {
519531
auto* flow = (*flows[i])->dynCast<Return>();
520532
if (!flow) continue;
521533
if (!flow->value) {

test/passes/remove-unused-brs.txt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,21 +2212,20 @@
22122212
(func $refinalize-need-br-value (; 101 ;) (type $2) (result i32)
22132213
(loop $label$3 (result i32)
22142214
(block $label$6 (result i32)
2215-
(block $label$10 (result i32)
2215+
(block $label$10
22162216
(unreachable)
2217-
(block $label$503 (result i32)
2217+
(block $label$503
22182218
(br_if $label$3
22192219
(block $label$530 (result i32)
2220-
(block
2221-
(unreachable)
2222-
(drop
2223-
(i32.const 0)
2224-
)
2220+
(br_if $label$503
2221+
(i32.const 0)
22252222
)
22262223
(i32.const 0)
22272224
)
22282225
)
2229-
(i32.const 127)
2226+
(return
2227+
(i32.const 127)
2228+
)
22302229
)
22312230
)
22322231
)
@@ -2404,4 +2403,32 @@
24042403
(i32.const 1)
24052404
)
24062405
)
2406+
(func $do-not-flow-values-through-unreachable-code (; 113 ;) (type $2) (result i32)
2407+
(block $block
2408+
(unreachable)
2409+
(if
2410+
(i32.const 0)
2411+
(block $A
2412+
(return
2413+
(i32.const 0)
2414+
)
2415+
)
2416+
(nop)
2417+
)
2418+
)
2419+
)
2420+
(func $do-not-flow-values-through-unreachable-code-b (; 114 ;) (type $2) (result i32)
2421+
(loop $loop-in
2422+
(unreachable)
2423+
(if
2424+
(i32.const 0)
2425+
(block $A
2426+
(return
2427+
(i32.const 0)
2428+
)
2429+
)
2430+
(nop)
2431+
)
2432+
)
2433+
)
24072434
)

test/passes/remove-unused-brs.wast

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,5 +2011,33 @@
20112011
)
20122012
)
20132013
)
2014+
(func $do-not-flow-values-through-unreachable-code (result i32)
2015+
(block
2016+
(unreachable)
2017+
(block $A
2018+
(if
2019+
(i32.const 0)
2020+
(return
2021+
(i32.const 0) ;; seems to flow out, but we are in unreachable code, and do not actually reach anywhere
2022+
)
2023+
(br $A) ;; can be a nop
2024+
)
2025+
)
2026+
)
2027+
)
2028+
(func $do-not-flow-values-through-unreachable-code-b (result i32)
2029+
(loop
2030+
(unreachable)
2031+
(block $A
2032+
(if
2033+
(i32.const 0)
2034+
(return
2035+
(i32.const 0)
2036+
)
2037+
(br $A)
2038+
)
2039+
)
2040+
)
2041+
)
20142042
)
20152043

0 commit comments

Comments
 (0)