@@ -571,9 +571,11 @@ void ProgramMemoryState::assume(const Token* tok, bool b, bool isEmpty, const To
571571
572572ProgramMemoryState::FindChangedFn ProgramMemoryState::getCachedFindExpressionChanged (bool skipDeadCode) const
573573{
574- // The structural findExpressionChanged() is pure, so memoize it in changedCache (never
575- // invalidated). skipDeadCode gates it as a pre-filter for the dead-code walk, which needs state.
576- return [cache = changedCache, sp = &settings, statePtr = &state, skipDeadCode](const Token* expr, const Token* start, const Token* end) -> const Token* {
574+ // Structural findExpressionChanged() is pure, so memoize it in changedCache (never invalidated).
575+ // skipDeadCode adds the dead-code walk; it evaluates guards against a fixed state snapshot (so every
576+ // variable follows the same path) and memoizes those evals in evalCache for the closure's lifetime.
577+ using EvalCache = std::map<const Token*, std::vector<MathLib::bigint>>;
578+ return [cache = changedCache, sp = &settings, snapshot = (skipDeadCode ? state : ProgramMemory{}), skipDeadCode, evalCache = std::make_shared<EvalCache>()](const Token* expr, const Token* start, const Token* end) -> const Token* {
577579 const auto key = std::make_tuple (expr, start, end);
578580 const auto it = cache->find (key);
579581 const Token* modified = (it != cache->end ())
@@ -582,13 +584,17 @@ ProgramMemoryState::FindChangedFn ProgramMemoryState::getCachedFindExpressionCha
582584 if (!skipDeadCode || !modified)
583585 return modified;
584586 auto eval = [&](const Token* cond) -> std::vector<MathLib::bigint> {
585- ProgramMemory pm2 = *statePtr;
587+ const auto cit = evalCache->find (cond);
588+ if (cit != evalCache->end ())
589+ return cit->second ;
590+ ProgramMemory pm2 = snapshot;
586591 const auto result = execute (cond, pm2, *sp);
592+ std::vector<MathLib::bigint> r;
587593 if (isTrue (result))
588- return {1 };
589- if (isFalse (result))
590- return {0 };
591- return {} ;
594+ r = {1 };
595+ else if (isFalse (result))
596+ r = {0 };
597+ return evalCache-> emplace (cond, std::move (r)). first -> second ;
592598 };
593599 return findExpressionChangedSkipDeadCode (expr, start, end, *sp, eval);
594600 };
0 commit comments