@@ -398,7 +398,14 @@ struct CodeFolding
398398 // if one of the items has a branch to something inside outOf that is not
399399 // inside that item
400400 bool canMove (const std::vector<Expression*>& items, Expression* outOf) {
401- auto allTargets = BranchUtils::getBranchTargets (outOf);
401+ return canMove (items, outOf, BranchUtils::getBranchTargets (outOf));
402+ }
403+
404+ // Overload that accepts pre-computed branch targets to avoid redundant
405+ // O(N) getBranchTargets calls.
406+ bool canMove (const std::vector<Expression*>& items,
407+ Expression* outOf,
408+ const BranchUtils::NameSet& allTargets) {
402409 for (auto * item : items) {
403410 auto exiting = BranchUtils::getExitingBranches (item);
404411 std::vector<Name> intersection;
@@ -707,33 +714,7 @@ struct CodeFolding
707714 // if we cannot merge to the end, then we definitely need 2 blocks,
708715 // and a branch. Use the pre-computed bodyTargets to avoid repeated
709716 // O(N) getBranchTargets calls.
710- auto * body = getFunction ()->body ;
711- bool canMoveItems = [&]() {
712- for (auto * item : items) {
713- auto exiting = BranchUtils::getExitingBranches (item);
714- std::vector<Name> intersection;
715- std::set_intersection (bodyTargets->begin (),
716- bodyTargets->end (),
717- exiting.begin (),
718- exiting.end (),
719- std::back_inserter (intersection));
720- if (intersection.size () > 0 ) {
721- return false ;
722- }
723- if (getModule ()->features .hasExceptionHandling ()) {
724- EffectAnalyzer effects (getPassOptions (), *getModule (), item);
725- if (effects.danglingPop ) {
726- return false ;
727- }
728- if (effects.throws () &&
729- (FindAll<Try>(body).has () ||
730- FindAll<TryTable>(body).has ())) {
731- return false ;
732- }
733- }
734- }
735- return true ;
736- }();
717+ bool canMoveItems = canMove (items, getFunction ()->body , *bodyTargets);
737718 if (!canMoveItems) {
738719 cost += 1 + WORTH_ADDING_BLOCK_TO_REMOVE_THIS_MUCH ;
739720 // TODO: to do this, we need to maintain a map of element=>parent,
0 commit comments