@@ -76,11 +76,16 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
76
76
}
77
77
}
78
78
79
- // if a child is unreachable, we can replace ourselves with it
79
+ // if a child exists and is unreachable, we can replace ourselves with it
80
80
bool isDead (Expression* child) {
81
81
return child && child->type == unreachable;
82
82
}
83
83
84
+ // a similar check, assumes the child exists
85
+ bool isUnreachable (Expression* child) {
86
+ return child->type == unreachable;
87
+ }
88
+
84
89
// things that stop control flow
85
90
86
91
void visitBreak (Break* curr) {
@@ -117,7 +122,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
117
122
replaceCurrent (curr->value );
118
123
return ;
119
124
}
120
- if (isDead (curr->condition )) {
125
+ if (isUnreachable (curr->condition )) {
121
126
if (curr->value ) {
122
127
auto * block = getModule ()->allocator .alloc <Block>();
123
128
block->list .resize (2 );
@@ -149,45 +154,25 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
149
154
reachable = false ;
150
155
}
151
156
152
- // we maintain a stack for blocks, as we visit each item, and the parameter is the index
153
-
154
- std::vector<Index> blockStack; // index in current block
155
-
156
- static void doPreBlock (DeadCodeElimination* self, Expression** currp) {
157
- self->blockStack .push_back (0 );
158
- }
159
-
160
- static void doAfterBlockElement (DeadCodeElimination* self, Expression** currp) {
161
- auto * block = (*currp)->cast <Block>();
162
- Index i = self->blockStack .back ();
163
- self->blockStack .back ()++;
164
- if (!self->reachable ) {
165
- // control flow ended in the middle of the block, so we can truncate the rest.
166
- // note that we still visit the rest, so if we already truncated, do not lengthen.
167
- // note that it is ok that we visit the others even though the list was shortened;
168
- // our arena vectors leave things as they are when shrinking.
169
- if (block->list .size () > i + 1 ) {
170
- // but note that it is not legal to truncate a block if it leaves a bad last element,
171
- // given the wasm type rules. For example, if the last element is a return, then
172
- // the block doesn't care about it for type checking purposes, but if removing
173
- // it would leave an element with type none as the last, that could be a problem,
174
- // see https://github.com/WebAssembly/spec/issues/355
175
- if (!(isConcreteWasmType (block->type ) && block->list [i]->type == none)) {
176
- block->list .resize (i + 1 );
177
- // note that we still walk the children, so typeUpdater will already
178
- // note they are being removed, and we don't need to do that here
157
+ void visitBlock (Block* curr) {
158
+ auto & list = curr->list ;
159
+ // if we are currently unreachable (before we take into account
160
+ // breaks to the block) then a child may be unreachable, and we
161
+ // can shorten
162
+ if (!reachable && list.size () > 1 ) {
163
+ // to do here: nothing to remove after it)
164
+ for (Index i = 0 ; i < list.size () - 1 ; i++) {
165
+ if (list[i]->type == unreachable) {
166
+ list.resize (i + 1 );
167
+ break ;
179
168
}
180
169
}
181
170
}
182
- }
183
-
184
- void visitBlock (Block* curr) {
185
- blockStack.pop_back ();
186
171
if (curr->name .is ()) {
187
172
reachable = reachable || reachableBreaks.count (curr->name );
188
173
reachableBreaks.erase (curr->name );
189
174
}
190
- if (curr-> list .size () == 1 && isDead (curr-> list [0 ])) {
175
+ if (list.size () == 1 && isUnreachable ( list[0 ])) {
191
176
replaceCurrent (BlockUtils::simplifyToContentsWithPossibleTypeChange (curr, this ));
192
177
} else {
193
178
// the block may have had a type, but can now be unreachable, which allows more reduction outside
@@ -199,7 +184,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
199
184
if (curr->name .is ()) {
200
185
reachableBreaks.erase (curr->name );
201
186
}
202
- if (isDead (curr->body ) && !BreakSeeker::has (curr->body , curr->name )) {
187
+ if (isUnreachable (curr->body ) && !BreakSeeker::has (curr->body , curr->name )) {
203
188
replaceCurrent (curr->body );
204
189
return ;
205
190
}
@@ -225,7 +210,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
225
210
// the ifStack has the branch that joins us, either from before if just an if, or the ifTrue if an if-else
226
211
reachable = reachable || ifStack.back ();
227
212
ifStack.pop_back ();
228
- if (isDead (curr->condition )) {
213
+ if (isUnreachable (curr->condition )) {
229
214
replaceCurrent (curr->condition );
230
215
}
231
216
// the if may have had a type, but can now be unreachable, which allows more reduction outside
@@ -280,14 +265,6 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
280
265
self->pushTask (DeadCodeElimination::scan, &curr->cast <If>()->ifTrue );
281
266
self->pushTask (DeadCodeElimination::doAfterIfCondition, currp);
282
267
self->pushTask (DeadCodeElimination::scan, &curr->cast <If>()->condition );
283
- } else if (curr->is <Block>()) {
284
- self->pushTask (DeadCodeElimination::doVisitBlock, currp);
285
- auto & list = curr->cast <Block>()->list ;
286
- for (int i = int (list.size ()) - 1 ; i >= 0 ; i--) {
287
- self->pushTask (DeadCodeElimination::doAfterBlockElement, currp);
288
- self->pushTask (DeadCodeElimination::scan, &list[i]);
289
- }
290
- self->pushTask (DeadCodeElimination::doPreBlock, currp);
291
268
} else {
292
269
WalkerPass<PostWalker<DeadCodeElimination>>::scan (self, currp);
293
270
}
@@ -304,7 +281,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
304
281
template <typename T>
305
282
Expression* handleCall (T* curr) {
306
283
for (Index i = 0 ; i < curr->operands .size (); i++) {
307
- if (isDead (curr->operands [i])) {
284
+ if (isUnreachable (curr->operands [i])) {
308
285
if (i > 0 ) {
309
286
auto * block = getModule ()->allocator .alloc <Block>();
310
287
Index newSize = i + 1 ;
@@ -333,7 +310,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
333
310
334
311
void visitCallIndirect (CallIndirect* curr) {
335
312
if (handleCall (curr) != curr) return ;
336
- if (isDead (curr->target )) {
313
+ if (isUnreachable (curr->target )) {
337
314
auto * block = getModule ()->allocator .alloc <Block>();
338
315
for (auto * operand : curr->operands ) {
339
316
block->list .push_back (drop (operand));
@@ -345,23 +322,23 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
345
322
}
346
323
347
324
void visitSetLocal (SetLocal* curr) {
348
- if (isDead (curr->value )) {
325
+ if (isUnreachable (curr->value )) {
349
326
replaceCurrent (curr->value );
350
327
}
351
328
}
352
329
353
330
void visitLoad (Load* curr) {
354
- if (isDead (curr->ptr )) {
331
+ if (isUnreachable (curr->ptr )) {
355
332
replaceCurrent (curr->ptr );
356
333
}
357
334
}
358
335
359
336
void visitStore (Store* curr) {
360
- if (isDead (curr->ptr )) {
337
+ if (isUnreachable (curr->ptr )) {
361
338
replaceCurrent (curr->ptr );
362
339
return ;
363
340
}
364
- if (isDead (curr->value )) {
341
+ if (isUnreachable (curr->value )) {
365
342
auto * block = getModule ()->allocator .alloc <Block>();
366
343
block->list .resize (2 );
367
344
block->list [0 ] = drop (curr->ptr );
@@ -372,17 +349,17 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
372
349
}
373
350
374
351
void visitUnary (Unary* curr) {
375
- if (isDead (curr->value )) {
352
+ if (isUnreachable (curr->value )) {
376
353
replaceCurrent (curr->value );
377
354
}
378
355
}
379
356
380
357
void visitBinary (Binary* curr) {
381
- if (isDead (curr->left )) {
358
+ if (isUnreachable (curr->left )) {
382
359
replaceCurrent (curr->left );
383
360
return ;
384
361
}
385
- if (isDead (curr->right )) {
362
+ if (isUnreachable (curr->right )) {
386
363
auto * block = getModule ()->allocator .alloc <Block>();
387
364
block->list .resize (2 );
388
365
block->list [0 ] = drop (curr->left );
@@ -393,11 +370,11 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
393
370
}
394
371
395
372
void visitSelect (Select* curr) {
396
- if (isDead (curr->ifTrue )) {
373
+ if (isUnreachable (curr->ifTrue )) {
397
374
replaceCurrent (curr->ifTrue );
398
375
return ;
399
376
}
400
- if (isDead (curr->ifFalse )) {
377
+ if (isUnreachable (curr->ifFalse )) {
401
378
auto * block = getModule ()->allocator .alloc <Block>();
402
379
block->list .resize (2 );
403
380
block->list [0 ] = drop (curr->ifTrue );
@@ -406,7 +383,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
406
383
replaceCurrent (block);
407
384
return ;
408
385
}
409
- if (isDead (curr->condition )) {
386
+ if (isUnreachable (curr->condition )) {
410
387
auto * block = getModule ()->allocator .alloc <Block>();
411
388
block->list .resize (3 );
412
389
block->list [0 ] = drop (curr->ifTrue );
@@ -419,7 +396,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
419
396
}
420
397
421
398
void visitDrop (Drop* curr) {
422
- if (isDead (curr->value )) {
399
+ if (isUnreachable (curr->value )) {
423
400
replaceCurrent (curr->value );
424
401
}
425
402
}
0 commit comments