@@ -136,6 +136,12 @@ static void replaceInPlace(Ref target, Ref value) {
136136 }
137137}
138138
139+ static void replaceInPlaceIfPossible (Ref target, Ref value) {
140+ if (target->isArray () && value->isArray ()) {
141+ replaceInPlace (target, value);
142+ }
143+ }
144+
139145static void optimizeJS (Ref ast) {
140146 // Helpers
141147
@@ -377,7 +383,8 @@ static void optimizeJS(Ref ast) {
377383 }
378384 });
379385
380- // Remove unnecessary break/continue labels, when referring to the top level.
386+ // Remove unnecessary break/continue labels, when the name is that of the
387+ // highest target anyhow, which we would reach without the name.
381388
382389 std::vector<Ref> breakCapturers;
383390 std::vector<Ref> continueCapturers;
@@ -437,6 +444,30 @@ static void optimizeJS(Ref ast) {
437444 }
438445 }
439446 });
447+
448+ // Remove unnecessary block/loop labels.
449+
450+ std::set<IString> usedLabelNames;
451+
452+ traversePost (ast, [&](Ref node) {
453+ if (node->isArray () && !node->empty ()) {
454+ if (node[0 ] == BREAK || node[0 ] == CONTINUE) {
455+ if (!node[1 ]->isNull ()) {
456+ auto label = node[1 ]->getIString ();
457+ usedLabelNames.insert (label);
458+ }
459+ } else if (node[0 ] == LABEL) {
460+ auto label = node[1 ]->getIString ();
461+ if (usedLabelNames.count (label)) {
462+ // It's used; just erase it from the data structure.
463+ usedLabelNames.erase (label);
464+ } else {
465+ // It's not used - get rid of it.
466+ replaceInPlaceIfPossible (node, node[2 ]);
467+ }
468+ }
469+ }
470+ });
440471}
441472
442473static void emitWasm (Module& wasm,
0 commit comments