@@ -76,11 +76,16 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
7676 }
7777 }
7878
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
8080 bool isDead (Expression* child) {
8181 return child && child->type == unreachable;
8282 }
8383
84+ // a similar check, assumes the child exists
85+ bool isUnreachable (Expression* child) {
86+ return child->type == unreachable;
87+ }
88+
8489 // things that stop control flow
8590
8691 void visitBreak (Break* curr) {
@@ -117,7 +122,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
117122 replaceCurrent (curr->value );
118123 return ;
119124 }
120- if (isDead (curr->condition )) {
125+ if (isUnreachable (curr->condition )) {
121126 if (curr->value ) {
122127 auto * block = getModule ()->allocator .alloc <Block>();
123128 block->list .resize (2 );
@@ -149,45 +154,25 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
149154 reachable = false ;
150155 }
151156
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 ;
179168 }
180169 }
181170 }
182- }
183-
184- void visitBlock (Block* curr) {
185- blockStack.pop_back ();
186171 if (curr->name .is ()) {
187172 reachable = reachable || reachableBreaks.count (curr->name );
188173 reachableBreaks.erase (curr->name );
189174 }
190- if (curr-> list .size () == 1 && isDead (curr-> list [0 ])) {
175+ if (list.size () == 1 && isUnreachable ( list[0 ])) {
191176 replaceCurrent (BlockUtils::simplifyToContentsWithPossibleTypeChange (curr, this ));
192177 } else {
193178 // 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>>
199184 if (curr->name .is ()) {
200185 reachableBreaks.erase (curr->name );
201186 }
202- if (isDead (curr->body ) && !BreakSeeker::has (curr->body , curr->name )) {
187+ if (isUnreachable (curr->body ) && !BreakSeeker::has (curr->body , curr->name )) {
203188 replaceCurrent (curr->body );
204189 return ;
205190 }
@@ -225,7 +210,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
225210 // the ifStack has the branch that joins us, either from before if just an if, or the ifTrue if an if-else
226211 reachable = reachable || ifStack.back ();
227212 ifStack.pop_back ();
228- if (isDead (curr->condition )) {
213+ if (isUnreachable (curr->condition )) {
229214 replaceCurrent (curr->condition );
230215 }
231216 // 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>>
280265 self->pushTask (DeadCodeElimination::scan, &curr->cast <If>()->ifTrue );
281266 self->pushTask (DeadCodeElimination::doAfterIfCondition, currp);
282267 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);
291268 } else {
292269 WalkerPass<PostWalker<DeadCodeElimination>>::scan (self, currp);
293270 }
@@ -304,7 +281,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
304281 template <typename T>
305282 Expression* handleCall (T* curr) {
306283 for (Index i = 0 ; i < curr->operands .size (); i++) {
307- if (isDead (curr->operands [i])) {
284+ if (isUnreachable (curr->operands [i])) {
308285 if (i > 0 ) {
309286 auto * block = getModule ()->allocator .alloc <Block>();
310287 Index newSize = i + 1 ;
@@ -333,7 +310,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
333310
334311 void visitCallIndirect (CallIndirect* curr) {
335312 if (handleCall (curr) != curr) return ;
336- if (isDead (curr->target )) {
313+ if (isUnreachable (curr->target )) {
337314 auto * block = getModule ()->allocator .alloc <Block>();
338315 for (auto * operand : curr->operands ) {
339316 block->list .push_back (drop (operand));
@@ -345,23 +322,23 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
345322 }
346323
347324 void visitSetLocal (SetLocal* curr) {
348- if (isDead (curr->value )) {
325+ if (isUnreachable (curr->value )) {
349326 replaceCurrent (curr->value );
350327 }
351328 }
352329
353330 void visitLoad (Load* curr) {
354- if (isDead (curr->ptr )) {
331+ if (isUnreachable (curr->ptr )) {
355332 replaceCurrent (curr->ptr );
356333 }
357334 }
358335
359336 void visitStore (Store* curr) {
360- if (isDead (curr->ptr )) {
337+ if (isUnreachable (curr->ptr )) {
361338 replaceCurrent (curr->ptr );
362339 return ;
363340 }
364- if (isDead (curr->value )) {
341+ if (isUnreachable (curr->value )) {
365342 auto * block = getModule ()->allocator .alloc <Block>();
366343 block->list .resize (2 );
367344 block->list [0 ] = drop (curr->ptr );
@@ -372,17 +349,17 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
372349 }
373350
374351 void visitUnary (Unary* curr) {
375- if (isDead (curr->value )) {
352+ if (isUnreachable (curr->value )) {
376353 replaceCurrent (curr->value );
377354 }
378355 }
379356
380357 void visitBinary (Binary* curr) {
381- if (isDead (curr->left )) {
358+ if (isUnreachable (curr->left )) {
382359 replaceCurrent (curr->left );
383360 return ;
384361 }
385- if (isDead (curr->right )) {
362+ if (isUnreachable (curr->right )) {
386363 auto * block = getModule ()->allocator .alloc <Block>();
387364 block->list .resize (2 );
388365 block->list [0 ] = drop (curr->left );
@@ -393,11 +370,11 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
393370 }
394371
395372 void visitSelect (Select* curr) {
396- if (isDead (curr->ifTrue )) {
373+ if (isUnreachable (curr->ifTrue )) {
397374 replaceCurrent (curr->ifTrue );
398375 return ;
399376 }
400- if (isDead (curr->ifFalse )) {
377+ if (isUnreachable (curr->ifFalse )) {
401378 auto * block = getModule ()->allocator .alloc <Block>();
402379 block->list .resize (2 );
403380 block->list [0 ] = drop (curr->ifTrue );
@@ -406,7 +383,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
406383 replaceCurrent (block);
407384 return ;
408385 }
409- if (isDead (curr->condition )) {
386+ if (isUnreachable (curr->condition )) {
410387 auto * block = getModule ()->allocator .alloc <Block>();
411388 block->list .resize (3 );
412389 block->list [0 ] = drop (curr->ifTrue );
@@ -419,7 +396,7 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination>>
419396 }
420397
421398 void visitDrop (Drop* curr) {
422- if (isDead (curr->value )) {
399+ if (isUnreachable (curr->value )) {
423400 replaceCurrent (curr->value );
424401 }
425402 }
0 commit comments