Skip to content

Commit 7d014ec

Browse files
committed
Improve SSAValueTracker. Fix the bug.
1 parent 7c3bff0 commit 7d014ec

3 files changed

Lines changed: 49 additions & 1 deletion

File tree

libyul/optimiser/SSAValueTracker.cpp

Lines changed: 42 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,20 @@ 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.find(_funDef.name) == m_functionParameters.end(),
44+
"SSAValueTracker requires Disambiguator to run first"
45+
);
46+
47+
for (auto const& param: _funDef.parameters)
48+
m_functionParameters.insert(param.name);
49+
3850
for (auto const& var: _funDef.returnVariables)
3951
setValue(var.name, nullptr);
4052
ASTWalker::operator()(_funDef);
@@ -49,6 +61,36 @@ void SSAValueTracker::operator()(VariableDeclaration const& _varDecl)
4961
setValue(_varDecl.variables.front().name, _varDecl.value.get());
5062
}
5163

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