Skip to content

Commit e2b8aae

Browse files
Improve SSAValueTracker. Fix the bug.
Co-authored-by: Nikola Matić <nikola.matic@ethereum.org>
1 parent 1d54746 commit e2b8aae

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

libyul/optimiser/SSAValueTracker.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include <libyul/optimiser/SSAValueTracker.h>
2424

25+
#include <liblangutil/Exceptions.h>
26+
2527
#include <libyul/AST.h>
2628

2729
using namespace solidity;
@@ -31,10 +33,18 @@ void SSAValueTracker::operator()(Assignment const& _assignment)
3133
{
3234
for (auto const& var: _assignment.variableNames)
3335
m_values.erase(var.name);
36+
37+
for (auto const& var: _assignment.variableNames)
38+
m_functionParameters.erase(var.name);
3439
}
3540

3641
void SSAValueTracker::operator()(FunctionDefinition const& _funDef)
3742
{
43+
solAssert(!m_functionParameters.contains(_funDef.name), "SSAValueTracker requires Disambiguator to run first");
44+
45+
for (auto const& param: _funDef.parameters)
46+
m_functionParameters.insert(param.name);
47+
3848
for (auto const& var: _funDef.returnVariables)
3949
setValue(var.name, nullptr);
4050
ASTWalker::operator()(_funDef);
@@ -49,6 +59,35 @@ void SSAValueTracker::operator()(VariableDeclaration const& _varDecl)
4959
setValue(_varDecl.variables.front().name, _varDecl.value.get());
5060
}
5161

62+
bool SSAValueTracker::isSSAWithDependencies(Expression const* _expression) const
63+
{
64+
if (_expression == nullptr)
65+
return true;
66+
67+
if (auto const* functionCall = std::get_if<FunctionCall>(_expression))
68+
{
69+
for (auto const& argument: functionCall->arguments)
70+
if (!isSSAWithDependencies(&argument))
71+
return false;
72+
73+
return true;
74+
}
75+
else if (auto const* identifier = std::get_if<Identifier>(_expression))
76+
{
77+
if (m_functionParameters.contains(identifier->name))
78+
return true;
79+
80+
auto const it = m_values.find(identifier->name);
81+
if (it == m_values.end())
82+
return false;
83+
return isSSAWithDependencies(it->second);
84+
}
85+
else
86+
solAssert(std::holds_alternative<Literal>(*_expression), "Impossible expression type");
87+
88+
return true;
89+
}
90+
5291
std::set<YulName> SSAValueTracker::ssaVariables(Block const& _ast)
5392
{
5493
SSAValueTracker t;

libyul/optimiser/SSAValueTracker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,18 @@ class SSAValueTracker: public ASTWalker
5252

5353
static std::set<YulName> ssaVariables(Block const& _ast);
5454

55+
/// Determines whether the given expression and all of its identifier
56+
/// dependencies are in Static Single Assignment (SSA) form.
57+
bool isSSAWithDependencies(Expression const* _expression) const;
58+
5559
private:
5660
void setValue(YulName _name, Expression const* _value);
5761

5862
/// Special expression whose address will be used in m_values.
5963
/// YulName does not need to be reset because SSAValueTracker is short-lived.
6064
Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0})}};
6165
std::map<YulName, Expression const*> m_values;
66+
std::set<YulName> m_functionParameters;
6267
};
6368

6469
}

libyul/optimiser/UnusedStoreEliminator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
5555
ssaValues(_ast);
5656
std::map<YulName, AssignedValue> values;
5757
for (auto const& [name, expression]: ssaValues.values())
58-
values[name] = AssignedValue{expression, {}};
58+
if (ssaValues.isSSAWithDependencies(expression))
59+
values[name] = AssignedValue{expression, {}};
5960

6061
bool const ignoreMemory = MSizeFinder::containsMSize(_context.dialect, _ast);
6162
UnusedStoreEliminator rse{

0 commit comments

Comments
 (0)