4444using namespace solidity ;
4545using namespace solidity ::yul;
4646
47+ namespace
48+ {
49+ bool isInSSAClosedSet (Expression const & _expression, std::map<YulName, Expression const *> const & _values)
50+ {
51+ if (auto const * functionCall = std::get_if<FunctionCall>(&_expression))
52+ {
53+ for (auto const & argument: functionCall->arguments )
54+ if (!isInSSAClosedSet (argument, _values))
55+ return false ;
56+
57+ return true ;
58+ }
59+ else if (auto const * identifier = std::get_if<Identifier>(&_expression))
60+ {
61+ auto const it = _values.find (identifier->name );
62+ if (it == _values.end ())
63+ return false ;
64+ return isInSSAClosedSet (*it->second , _values);
65+ }
66+ else
67+ {
68+ solAssert (std::holds_alternative<Literal>(_expression), " Impossible expression type" );
69+ return true ;
70+ }
71+ }
72+ }
73+
4774void UnusedStoreEliminator::run (OptimiserStepContext& _context, Block& _ast)
4875{
4976 std::map<FunctionHandle, SideEffects> functionSideEffects = SideEffectsPropagator::sideEffects (
@@ -54,8 +81,9 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
5481 SSAValueTracker ssaValues;
5582 ssaValues (_ast);
5683 std::map<YulName, AssignedValue> values;
57- for (auto const & [name, expression]: ssaValues.values ())
58- values[name] = AssignedValue{expression, {}};
84+ for (auto const & [variableName, expression]: ssaValues.values ())
85+ if (expression && isInSSAClosedSet (*expression, ssaValues.values ()))
86+ values[variableName] = AssignedValue{expression, {}};
5987
6088 bool const ignoreMemory = MSizeFinder::containsMSize (_context.dialect , _ast);
6189 UnusedStoreEliminator rse{
0 commit comments