@@ -568,14 +568,6 @@ struct ConstraintAnalysis
568568 return ;
569569 }
570570
571- // See above on binary action counting limits.
572- if (auto * binary = set->value ->dynCast <Binary>()) {
573- if (binaryActionCounts[binary]++ >= MaxBinaryActions) {
574- constraints.setProvesNothing (set->index );
575- return ;
576- }
577- }
578-
579571 // Look at the fallthrough. It is valid to do so, because our constraints
580572 // only track two things, constants and locals. For a constant, it does
581573 // not change while falling through. For a local, the only way for the
@@ -600,8 +592,47 @@ struct ConstraintAnalysis
600592 // opportunity to write any other value while falling through. (And, any
601593 // local.tee appearing here would have been reached earlier in the
602594 // traversal, and handled.)
603- auto * value =
604- Properties::getFallthrough (set->value , getPassOptions (), *getModule ());
595+ auto * value = set->value ;
596+ while (1 ) {
597+ if (value->is <LocalSet>()) {
598+ // We stop at the first tee: we don't need to look any further, and
599+ // will just apply that local's values to ourselves, saving repeated
600+ // work.
601+ break ;
602+ }
603+ auto * next = Properties::getImmediateFallthrough (
604+ value, getPassOptions (), *getModule ());
605+ if (value == next) {
606+ break ;
607+ } else {
608+ value = next;
609+ }
610+ }
611+
612+ // Now that we know the value, check binary action counting limits (see
613+ // above).
614+ if (auto * binary = value->dynCast <Binary>()) {
615+ // The code below will stop calculating this binary once we pass
616+ // MaxBinaryActions operations on it. That is enough to prevent
617+ // unbounded work on this binary, however, we may end up reaching this
618+ // basic block an even larger number of times for other reasons, i.e.,
619+ // just because of a very complex CFG. That should be very rare, but can
620+ // happen. In debug builds we check we do not exceed a very high limit
621+ // there, intending to throw an assert rather than just hang in the case
622+ // of a bug (as assert is easier to diagnose, even if it happens after a
623+ // long delay).
624+ auto & count = binaryActionCounts[binary];
625+ #ifndef NDEBUG
626+ static const Index MaxBasicBlockActions = 1024 * 1024 ;
627+ assert (count < MaxBasicBlockActions);
628+ #endif
629+ count++;
630+ if (count >= MaxBinaryActions) {
631+ constraints.setProvesNothing (set->index );
632+ return ;
633+ }
634+ }
635+
605636 constraints.set (set->index , value);
606637 }
607638 }
0 commit comments