diff options
Diffstat (limited to 'libyul/optimiser/Rematerialiser.cpp')
-rw-r--r-- | libyul/optimiser/Rematerialiser.cpp | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index 4180bfc3..56f6e99c 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -22,6 +22,7 @@ #include <libyul/optimiser/Metrics.h> #include <libyul/optimiser/ASTCopier.h> +#include <libyul/optimiser/NameCollector.h> #include <libyul/Exceptions.h> #include <libyul/AsmData.h> @@ -29,6 +30,17 @@ using namespace std; using namespace dev; using namespace yul; +void Rematerialiser::run(Dialect const& _dialect, Block& _ast) +{ + Rematerialiser{_dialect, _ast}(_ast); +} + +Rematerialiser::Rematerialiser(Dialect const& _dialect, Block& _ast): + DataFlowAnalyzer(_dialect), + m_referenceCounts(ReferencesCounter::countReferences(_ast)) +{ +} + void Rematerialiser::visit(Expression& _e) { if (_e.type() == typeid(Identifier)) @@ -37,12 +49,21 @@ void Rematerialiser::visit(Expression& _e) if (m_value.count(identifier.name)) { YulString name = identifier.name; - for (auto const& ref: m_references[name]) - assertThrow(inScope(ref), OptimizerException, ""); assertThrow(m_value.at(name), OptimizerException, ""); auto const& value = *m_value.at(name); - if (CodeSize::codeSize(value) <= 7) + size_t refs = m_referenceCounts[name]; + size_t cost = CodeCost::codeCost(value); + if (refs <= 1 || cost == 0 || (refs <= 5 && cost <= 1)) + { + assertThrow(m_referenceCounts[name] > 0, OptimizerException, ""); + for (auto const& ref: m_references[name]) + assertThrow(inScope(ref), OptimizerException, ""); + // update reference counts + m_referenceCounts[name]--; + for (auto const& ref: ReferencesCounter::countReferences(value)) + m_referenceCounts[ref.first] += ref.second; _e = (ASTCopier{}).translate(value); + } } } DataFlowAnalyzer::visit(_e); |