From f1febf69d08aaffceea7c88985ce342216456d7b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Nov 2022 22:02:36 +0100 Subject: [PATCH] Only count variables if only variables are needed. --- libyul/backends/evm/EVMCodeTransform.cpp | 7 ++- libyul/optimiser/ExpressionJoiner.cpp | 2 +- libyul/optimiser/LoopInvariantCodeMotion.cpp | 2 +- libyul/optimiser/NameCollector.cpp | 54 +++++++++++++++---- libyul/optimiser/NameCollector.h | 30 +++++++---- libyul/optimiser/Rematerialiser.cpp | 6 ++- .../UnusedFunctionParameterPruner.cpp | 2 +- 7 files changed, 73 insertions(+), 30 deletions(-) diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index d5e25a1d1e85..8a268675c75a 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -668,10 +668,9 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, vector(_statement) ) { - ReferencesCounter referencesCounter{ReferencesCounter::CountWhat::OnlyVariables}; - referencesCounter.visit(_statement); - auto isReferenced = [&referencesCounter](TypedName const& _returnVariable) { - return referencesCounter.references().count(_returnVariable.name); + map references = VariableReferencesCounter::countReferences(_statement); + auto isReferenced = [&references](TypedName const& _returnVariable) { + return references.count(_returnVariable.name); }; if (ranges::none_of(_returnVariables, isReferenced)) return false; diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index dbb684007c64..645bb6c3ed44 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -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& _arguments) diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index fe8ddff97ed6..87454dc96db8 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -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}; diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index c2a82d494645..2664b8f6dda6 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -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 ReferencesCounter::countReferences(Block const& _block, CountWhat _countWhat) +map ReferencesCounter::countReferences(Block const& _block) { - ReferencesCounter counter(_countWhat); + ReferencesCounter counter; counter(_block); - return counter.references(); + return std::move(counter.m_references); } -map ReferencesCounter::countReferences(FunctionDefinition const& _function, CountWhat _countWhat) +map ReferencesCounter::countReferences(FunctionDefinition const& _function) { - ReferencesCounter counter(_countWhat); + ReferencesCounter counter; counter(_function); - return counter.references(); + return std::move(counter.m_references); } -map ReferencesCounter::countReferences(Expression const& _expression, CountWhat _countWhat) +map 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 VariableReferencesCounter::countReferences(Block const& _block) +{ + VariableReferencesCounter counter; + counter(_block); + return std::move(counter.m_references); +} + +map VariableReferencesCounter::countReferences(FunctionDefinition const& _function) +{ + VariableReferencesCounter counter; + counter(_function); + return std::move(counter.m_references); +} + +map VariableReferencesCounter::countReferences(Expression const& _expression) +{ + VariableReferencesCounter counter; + counter.visit(_expression); + return std::move(counter.m_references); +} + +map VariableReferencesCounter::countReferences(Statement const& _statement) +{ + VariableReferencesCounter counter; + counter.visit(_statement); + return std::move(counter.m_references); } void AssignmentsSinceContinue::operator()(ForLoop const& _forLoop) diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index 34dd5f9b3007..ad18e1e26bb3 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -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 countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); + +private: + std::map 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 countReferences(Block const& _block, CountWhat _countWhat = VariablesAndFunctions); - static std::map countReferences(FunctionDefinition const& _function, CountWhat _countWhat = VariablesAndFunctions); - static std::map countReferences(Expression const& _expression, CountWhat _countWhat = VariablesAndFunctions); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); + static std::map countReferences(Statement const& _statement); - std::map const& references() const { return m_references; } private: - CountWhat m_countWhat = CountWhat::VariablesAndFunctions; std::map m_references; }; diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index fb42e65935f8..02221a17d66d 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -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) { @@ -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); } diff --git a/libyul/optimiser/UnusedFunctionParameterPruner.cpp b/libyul/optimiser/UnusedFunctionParameterPruner.cpp index 8f45f8406308..1ada8224f9e0 100644 --- a/libyul/optimiser/UnusedFunctionParameterPruner.cpp +++ b/libyul/optimiser/UnusedFunctionParameterPruner.cpp @@ -43,7 +43,7 @@ using namespace solidity::yul::unusedFunctionsCommon; void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast) { - map references = ReferencesCounter::countReferences(_ast); + map 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