Skip to content

Commit

Permalink
Merge pull request ethereum#13705 from ethereum/onlyCountVariables
Browse files Browse the repository at this point in the history
Only count variables if only variables are needed.
  • Loading branch information
chriseth authored Nov 25, 2022
2 parents bf1a2c7 + f1febf6 commit 826ada0
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 30 deletions.
7 changes: 3 additions & 4 deletions libyul/backends/evm/EVMCodeTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,10 +668,9 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, vector<Typed
holds_alternative<Assignment>(_statement)
)
{
ReferencesCounter referencesCounter{ReferencesCounter::CountWhat::OnlyVariables};
referencesCounter.visit(_statement);
auto isReferenced = [&referencesCounter](TypedName const& _returnVariable) {
return referencesCounter.references().count(_returnVariable.name);
map<YulString, size_t> references = VariableReferencesCounter::countReferences(_statement);
auto isReferenced = [&references](TypedName const& _returnVariable) {
return references.count(_returnVariable.name);
};
if (ranges::none_of(_returnVariables, isReferenced))
return false;
Expand Down
2 changes: 1 addition & 1 deletion libyul/optimiser/ExpressionJoiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void ExpressionJoiner::visit(Expression& _e)

ExpressionJoiner::ExpressionJoiner(Block& _ast)
{
m_references = ReferencesCounter::countReferences(_ast);
m_references = VariableReferencesCounter::countReferences(_ast);
}

void ExpressionJoiner::handleArguments(vector<Expression>& _arguments)
Expand Down
2 changes: 1 addition & 1 deletion libyul/optimiser/LoopInvariantCodeMotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ bool LoopInvariantCodeMotion::canBePromoted(
return false;
if (_varDecl.value)
{
for (auto const& ref: ReferencesCounter::countReferences(*_varDecl.value, ReferencesCounter::OnlyVariables))
for (auto const& ref: VariableReferencesCounter::countReferences(*_varDecl.value))
if (_varsDefinedInCurrentScope.count(ref.first) || !m_ssaVariables.count(ref.first))
return false;
SideEffectsCollector sideEffects{m_dialect, *_varDecl.value, &m_functionSideEffects};
Expand Down
54 changes: 43 additions & 11 deletions libyul/optimiser/NameCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,62 @@ void ReferencesCounter::operator()(Identifier const& _identifier)

void ReferencesCounter::operator()(FunctionCall const& _funCall)
{
if (m_countWhat == VariablesAndFunctions)
++m_references[_funCall.functionName.name];
++m_references[_funCall.functionName.name];
ASTWalker::operator()(_funCall);
}

map<YulString, size_t> ReferencesCounter::countReferences(Block const& _block, CountWhat _countWhat)
map<YulString, size_t> ReferencesCounter::countReferences(Block const& _block)
{
ReferencesCounter counter(_countWhat);
ReferencesCounter counter;
counter(_block);
return counter.references();
return std::move(counter.m_references);
}

map<YulString, size_t> ReferencesCounter::countReferences(FunctionDefinition const& _function, CountWhat _countWhat)
map<YulString, size_t> ReferencesCounter::countReferences(FunctionDefinition const& _function)
{
ReferencesCounter counter(_countWhat);
ReferencesCounter counter;
counter(_function);
return counter.references();
return std::move(counter.m_references);
}

map<YulString, size_t> ReferencesCounter::countReferences(Expression const& _expression, CountWhat _countWhat)
map<YulString, size_t> ReferencesCounter::countReferences(Expression const& _expression)
{
ReferencesCounter counter(_countWhat);
ReferencesCounter counter;
counter.visit(_expression);
return counter.references();
return std::move(counter.m_references);
}

void VariableReferencesCounter::operator()(Identifier const& _identifier)
{
++m_references[_identifier.name];
}

map<YulString, size_t> VariableReferencesCounter::countReferences(Block const& _block)
{
VariableReferencesCounter counter;
counter(_block);
return std::move(counter.m_references);
}

map<YulString, size_t> VariableReferencesCounter::countReferences(FunctionDefinition const& _function)
{
VariableReferencesCounter counter;
counter(_function);
return std::move(counter.m_references);
}

map<YulString, size_t> VariableReferencesCounter::countReferences(Expression const& _expression)
{
VariableReferencesCounter counter;
counter.visit(_expression);
return std::move(counter.m_references);
}

map<YulString, size_t> VariableReferencesCounter::countReferences(Statement const& _statement)
{
VariableReferencesCounter counter;
counter.visit(_statement);
return std::move(counter.m_references);
}

void AssignmentsSinceContinue::operator()(ForLoop const& _forLoop)
Expand Down
30 changes: 20 additions & 10 deletions libyul/optimiser/NameCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,33 @@ class NameCollector: public ASTWalker
class ReferencesCounter: public ASTWalker
{
public:
enum CountWhat { VariablesAndFunctions, OnlyVariables };
using ASTWalker::operator ();
void operator()(Identifier const& _identifier) override;
void operator()(FunctionCall const& _funCall) override;

explicit ReferencesCounter(CountWhat _countWhat = VariablesAndFunctions):
m_countWhat(_countWhat)
{}
static std::map<YulString, size_t> countReferences(Block const& _block);
static std::map<YulString, size_t> countReferences(FunctionDefinition const& _function);
static std::map<YulString, size_t> countReferences(Expression const& _expression);

private:
std::map<YulString, size_t> m_references;
};

/**
* Specific AST walker that counts all references to all variable declarations.
*/
class VariableReferencesCounter: public ASTWalker
{
public:
using ASTWalker::operator ();
void operator()(Identifier const& _identifier) override;
void operator()(FunctionCall const& _funCall) override;

static std::map<YulString, size_t> countReferences(Block const& _block, CountWhat _countWhat = VariablesAndFunctions);
static std::map<YulString, size_t> countReferences(FunctionDefinition const& _function, CountWhat _countWhat = VariablesAndFunctions);
static std::map<YulString, size_t> countReferences(Expression const& _expression, CountWhat _countWhat = VariablesAndFunctions);
static std::map<YulString, size_t> countReferences(Block const& _block);
static std::map<YulString, size_t> countReferences(FunctionDefinition const& _function);
static std::map<YulString, size_t> countReferences(Expression const& _expression);
static std::map<YulString, size_t> countReferences(Statement const& _statement);

std::map<YulString, size_t> const& references() const { return m_references; }
private:
CountWhat m_countWhat = CountWhat::VariablesAndFunctions;
std::map<YulString, size_t> m_references;
};

Expand Down
6 changes: 4 additions & 2 deletions libyul/optimiser/Rematerialiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Rematerialiser::Rematerialiser(
bool _onlySelectedVariables
):
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore),
m_referenceCounts(ReferencesCounter::countReferences(_ast)),
m_referenceCounts(VariableReferencesCounter::countReferences(_ast)),
m_varsToAlwaysRematerialize(std::move(_varsToAlwaysRematerialize)),
m_onlySelectedVariables(_onlySelectedVariables)
{
Expand Down Expand Up @@ -77,7 +77,9 @@ void Rematerialiser::visit(Expression& _e)
{
// update reference counts
m_referenceCounts[name]--;
for (auto const& ref: ReferencesCounter::countReferences(*value->value))
for (auto const& ref: VariableReferencesCounter::countReferences(
*value->value
))
m_referenceCounts[ref.first] += ref.second;
_e = (ASTCopier{}).translate(*value->value);
}
Expand Down
2 changes: 1 addition & 1 deletion libyul/optimiser/UnusedFunctionParameterPruner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ using namespace solidity::yul::unusedFunctionsCommon;

void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast)
{
map<YulString, size_t> references = ReferencesCounter::countReferences(_ast);
map<YulString, size_t> references = VariableReferencesCounter::countReferences(_ast);
auto used = [&](auto v) -> bool { return references.count(v.name); };

// Function name and a pair of boolean masks, the first corresponds to parameters and the second
Expand Down

0 comments on commit 826ada0

Please sign in to comment.