Skip to content

Commit b69f8a6

Browse files
committed
don't remove values from breaks if the values have side effects
1 parent 6cdffee commit b69f8a6

3 files changed

Lines changed: 70 additions & 15 deletions

File tree

src/passes/MergeBlocks.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,23 @@ namespace wasm {
7373
// For example, if there is a switch targeting us, we can't do it - we can't remove the value from other targets
7474
struct ProblemFinder : public ControlFlowWalker<ProblemFinder> {
7575
Name origin;
76-
bool foundSwitch = false;
76+
bool noWay = false;
7777
// count br_ifs, and dropped br_ifs. if they don't match, then a br_if flow value is used, and we can't drop it
7878
Index brIfs = 0;
7979
Index droppedBrIfs = 0;
80+
PassOptions& passOptions;
81+
82+
ProblemFinder(PassOptions& passOptions) : passOptions(passOptions) {}
8083

8184
void visitBreak(Break* curr) {
82-
if (curr->name == origin && curr->condition) {
83-
brIfs++;
85+
if (curr->name == origin) {
86+
if (curr->condition) {
87+
brIfs++;
88+
}
89+
// if the value has side effects, we can't remove it
90+
if (EffectAnalyzer(passOptions, curr->value).hasSideEffects()) {
91+
noWay = true;
92+
}
8493
}
8594
}
8695

@@ -94,27 +103,30 @@ struct ProblemFinder : public ControlFlowWalker<ProblemFinder> {
94103

95104
void visitSwitch(Switch* curr) {
96105
if (curr->default_ == origin) {
97-
foundSwitch = true;
106+
noWay = true;
98107
return;
99108
}
100109
for (auto& target : curr->targets) {
101110
if (target == origin) {
102-
foundSwitch = true;
111+
noWay = true;
103112
return;
104113
}
105114
}
106115
}
107116

108117
bool found() {
109118
assert(brIfs >= droppedBrIfs);
110-
return foundSwitch || brIfs > droppedBrIfs;
119+
return noWay || brIfs > droppedBrIfs;
111120
}
112121
};
113122

114123
// Drops values from breaks to an origin.
115124
// While doing so it can create new blocks, so optimize blocks as well.
116125
struct BreakValueDropper : public ControlFlowWalker<BreakValueDropper> {
117126
Name origin;
127+
PassOptions& passOptions;
128+
129+
BreakValueDropper(PassOptions& passOptions) : passOptions(passOptions) {}
118130

119131
void visitBlock(Block* curr);
120132

@@ -143,7 +155,7 @@ struct BreakValueDropper : public ControlFlowWalker<BreakValueDropper> {
143155
};
144156

145157
// core block optimizer routine
146-
static void optimizeBlock(Block* curr, Module* module) {
158+
static void optimizeBlock(Block* curr, Module* module, PassOptions& passOptions) {
147159
bool more = true;
148160
bool changed = false;
149161
while (more) {
@@ -159,14 +171,14 @@ static void optimizeBlock(Block* curr, Module* module) {
159171
if (child->name.is()) {
160172
Expression* expression = child;
161173
// check if it's ok to remove the value from all breaks to us
162-
ProblemFinder finder;
174+
ProblemFinder finder(passOptions);
163175
finder.origin = child->name;
164176
finder.walk(expression);
165177
if (finder.found()) {
166178
child = nullptr;
167179
} else {
168180
// fix up breaks
169-
BreakValueDropper fixer;
181+
BreakValueDropper fixer(passOptions);
170182
fixer.origin = child->name;
171183
fixer.setModule(module);
172184
fixer.walk(expression);
@@ -217,7 +229,7 @@ static void optimizeBlock(Block* curr, Module* module) {
217229
}
218230

219231
void BreakValueDropper::visitBlock(Block* curr) {
220-
optimizeBlock(curr, getModule());
232+
optimizeBlock(curr, getModule(), passOptions);
221233
}
222234

223235
struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
@@ -226,7 +238,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
226238
Pass* create() override { return new MergeBlocks; }
227239

228240
void visitBlock(Block *curr) {
229-
optimizeBlock(curr, getModule());
241+
optimizeBlock(curr, getModule(), getPassOptions());
230242
}
231243

232244
Block* optimize(Expression* curr, Expression*& child, Block* outer = nullptr, Expression** dependency1 = nullptr, Expression** dependency2 = nullptr) {

test/passes/merge-blocks.txt

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,15 @@
7878
)
7979
(func $drop-unreachable-br_if (type $2) (result i32)
8080
(block $label$0 (result i32)
81-
(block $label$2
82-
(drop
83-
(br $label$0
84-
(i32.const 538976371)
81+
(drop
82+
(block $label$2
83+
(drop
84+
(br_if $label$2
85+
(br $label$0
86+
(i32.const 538976371)
87+
)
88+
(i32.const 1918987552)
89+
)
8590
)
8691
)
8792
)
@@ -100,4 +105,23 @@
100105
)
101106
)
102107
)
108+
(func $br-goes-away-label2-becomes-unreachable (type $0)
109+
(block $block
110+
(drop
111+
(block $label$1 (result i32)
112+
(block $label$2
113+
(drop
114+
(br_if $label$1
115+
(unreachable)
116+
(i32.eqz
117+
(br $label$2)
118+
)
119+
)
120+
)
121+
)
122+
(i32.const 1)
123+
)
124+
)
125+
)
126+
)
103127
)

test/passes/merge-blocks.wast

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,24 @@
8282
)
8383
)
8484
)
85+
(func $br-goes-away-label2-becomes-unreachable
86+
(block
87+
(drop
88+
(block $label$1 (result i32)
89+
(block $label$2
90+
(drop
91+
(br_if $label$1
92+
(unreachable)
93+
(i32.eqz
94+
(br $label$2)
95+
)
96+
)
97+
)
98+
)
99+
(i32.const 1)
100+
)
101+
)
102+
)
103+
)
85104
)
86105

0 commit comments

Comments
 (0)