aboutsummaryrefslogtreecommitdiffstats
path: root/libyul/optimiser/Rematerialiser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libyul/optimiser/Rematerialiser.cpp')
-rw-r--r--libyul/optimiser/Rematerialiser.cpp27
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);