@@ -338,6 +338,24 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
338338 // If the block has a single child which is a loop, and the block is named,
339339 // then it is the exit for the loop. It's better to move it into the loop,
340340 // where it can be better optimized by other passes.
341+ // Similar logic for ifs: if the block is an exit for the if, we can
342+ // move the block in, consider for example:
343+ // (block $label
344+ // (if (..condition1..)
345+ // (block
346+ // (br_if $label (..condition2..))
347+ // (..code..)
348+ // )
349+ // )
350+ // )
351+ // After also merging the blocks, we have
352+ // (if (..condition1..)
353+ // (block $label
354+ // (br_if $label (..condition2..))
355+ // (..code..)
356+ // )
357+ // )
358+ // which can be further optimized by other passes.
341359 if (curr->name .is () && curr->list .size () == 1 ) {
342360 if (auto * loop = curr->list [0 ]->dynCast <Loop>()) {
343361 curr->list [0 ] = loop->body ;
@@ -348,8 +366,29 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
348366 // After the flip, the outer type must be the same
349367 assert (loop->type == oldOuterType);
350368 replaceCurrent (loop);
351- // Fall through to optimize the block, which has a new child now.
369+ } else if (auto * iff = curr->list [0 ]->dynCast <If>()) {
370+ // The label can't be used in the condition.
371+ if (BranchUtils::BranchSeeker::countNamed (iff->condition , curr->name ) == 0 ) {
372+ // We can move the block into either arm, if there are no uses in the other.
373+ Expression** target = nullptr ;
374+ if (!iff->ifFalse ||
375+ BranchUtils::BranchSeeker::countNamed (iff->ifFalse , curr->name ) == 0 ) {
376+ target = &iff->ifTrue ;
377+ } else if (BranchUtils::BranchSeeker::countNamed (iff->ifTrue , curr->name ) == 0 ) {
378+ target = &iff->ifFalse ;
379+ }
380+ if (target) {
381+ curr->list [0 ] = *target;
382+ *target = curr;
383+ curr->finalize (curr->type );
384+ iff->finalize ();
385+ replaceCurrent (iff);
386+ // Note that the type might change, e.g. if the if condition is unreachable
387+ // but the block that was on the outside had a break.
388+ }
389+ }
352390 }
391+ // Always fall through to optimize the block, which has a new child now.
353392 }
354393 // Otherwise, do the main merging optimizations.
355394 optimizeBlock (curr, getModule (), getPassOptions ());
0 commit comments