Skip to content

Commit cf6c4cf

Browse files
committed
infinite loops have side effects
1 parent b2c17a1 commit cf6c4cf

5 files changed

Lines changed: 79 additions & 8 deletions

File tree

src/ast/effects.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
3939
if (breakNames.size() > 0) branches = true;
4040
}
4141

42-
bool branches = false; // branches out of this expression
42+
bool branches = false; // branches out of this expression, returns, infinite loops, etc
4343
bool calls = false;
4444
std::set<Index> localsRead;
4545
std::set<Index> localsWritten;
@@ -138,6 +138,18 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
138138
}
139139
void visitLoop(Loop* curr) {
140140
if (curr->name.is()) breakNames.erase(curr->name); // these were internal breaks
141+
// if the loop is unreachable, then there is branching control flow:
142+
// (1) if the body is unreachable because of a (return), uncaught (br) etc., then we
143+
// already noted branching, so it is ok to mark it again (if we have *caught*
144+
// (br)s, then they did not lead to the loop body being unreachable).
145+
// (same logic applies to blocks)
146+
// (2) if the loop is unreachable because it only has branches up to the loop
147+
// top, but no way to get out, then it is an infinite loop, and we consider
148+
// that a branching side effect (note how the same logic does not apply to
149+
// blocks).
150+
if (curr->type == unreachable) {
151+
branches = true;
152+
}
141153
}
142154

143155
void visitCall(Call *curr) { calls = true; }
@@ -182,6 +194,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
182194
case TruncUFloat64ToInt32:
183195
case TruncUFloat64ToInt64: {
184196
implicitTrap = true;
197+
break;
185198
}
186199
default: {}
187200
}
@@ -199,6 +212,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
199212
case RemSInt64:
200213
case RemUInt64: {
201214
implicitTrap = true;
215+
break;
202216
}
203217
default: {}
204218
}

test/passes/remove-unused-brs_shrink-level=1.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,20 @@
123123
)
124124
)
125125
)
126+
(func $join-and-it-becomes-unreachable (type $1)
127+
(block $label$1
128+
(block $block
129+
(br_if $label$1
130+
(i32.load8_u
131+
(i32.const -93487262)
132+
)
133+
)
134+
(br_if $label$1
135+
(loop $label$5
136+
(br $label$5)
137+
)
138+
)
139+
)
140+
)
141+
)
126142
)

test/passes/remove-unused-brs_shrink-level=1.wast

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,21 @@
7777
(br_if $out8 (call $b14)) ;; side effect
7878
)
7979
)
80+
(func $join-and-it-becomes-unreachable
81+
(block $label$1
82+
(block
83+
(br_if $label$1
84+
(i32.load8_u
85+
(i32.const -93487262)
86+
)
87+
)
88+
(br_if $label$1
89+
(loop $label$5 ;; this is unreachable (infinite loop, no exit)
90+
(br $label$5)
91+
)
92+
)
93+
)
94+
)
95+
)
8096
)
8197

test/passes/remove-unused-names_vacuum.txt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
(memory $0 0)
55
(func $return-i32-but-body-is-unreachable3 (type $0) (result i32)
66
(local $label i32)
7-
(unreachable)
7+
(loop $while-in$1
8+
(br $while-in$1)
9+
)
810
)
911
(func $return-i32-but-body-is-unreachable4 (type $0) (result i32)
1012
(local $label i32)
11-
(unreachable)
13+
(loop $while-in$1
14+
(br $while-in$1)
15+
)
1216
)
1317
(func $to-drop-unreachable (type $1)
1418
(drop
@@ -17,4 +21,12 @@
1721
)
1822
)
1923
)
24+
(func $return-i32-but-body-is-unreachable5 (type $0) (result i32)
25+
(local $label i32)
26+
(unreachable)
27+
)
28+
(func $return-i32-but-body-is-unreachable6 (type $0) (result i32)
29+
(local $label i32)
30+
(unreachable)
31+
)
2032
)

test/passes/remove-unused-names_vacuum.wast

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,25 @@
1616
)
1717
(i32.const 0)
1818
)
19-
(func $to-drop-unreachable
20-
(drop
21-
(block (result i32)
22-
(unreachable)
19+
(func $to-drop-unreachable
20+
(drop
21+
(block (result i32)
22+
(unreachable)
23+
)
2324
)
2425
)
25-
)
26+
(func $return-i32-but-body-is-unreachable5 (result i32)
27+
(local $label i32)
28+
(block ;; without a name here, vaccum had a too-eager bug
29+
(unreachable)
30+
)
31+
)
32+
(func $return-i32-but-body-is-unreachable6 (result i32)
33+
(local $label i32)
34+
(block ;; without a name here, vaccum had a too-eager bug
35+
(unreachable)
36+
)
37+
(i32.const 0)
38+
)
2639
)
2740

0 commit comments

Comments
 (0)