diff options
Diffstat (limited to 'libjulia/optimiser/Rematerialiser.cpp')
-rw-r--r-- | libjulia/optimiser/Rematerialiser.cpp | 159 |
1 files changed, 9 insertions, 150 deletions
diff --git a/libjulia/optimiser/Rematerialiser.cpp b/libjulia/optimiser/Rematerialiser.cpp index bf7d7d16..eaa75e33 100644 --- a/libjulia/optimiser/Rematerialiser.cpp +++ b/libjulia/optimiser/Rematerialiser.cpp @@ -20,176 +20,35 @@ #include <libjulia/optimiser/Rematerialiser.h> +#include <libjulia/optimiser/Metrics.h> #include <libjulia/optimiser/ASTCopier.h> -#include <libjulia/optimiser/NameCollector.h> #include <libsolidity/inlineasm/AsmData.h> -#include <libjulia/optimiser/Semantics.h> - -#include <libdevcore/CommonData.h> - -#include <boost/range/adaptor/reversed.hpp> - using namespace std; using namespace dev; using namespace dev::julia; -void Rematerialiser::operator()(Assignment& _assignment) -{ - set<string> names; - for (auto const& var: _assignment.variableNames) - names.insert(var.name); - handleAssignment(names, _assignment.value.get()); -} - -void Rematerialiser::operator()(VariableDeclaration& _varDecl) -{ - set<string> names; - for (auto const& var: _varDecl.variables) - names.insert(var.name); - m_variableScopes.back().first += names; - handleAssignment(names, _varDecl.value.get()); -} - -void Rematerialiser::operator()(If& _if) -{ - ASTModifier::operator()(_if); - - Assignments ass; - ass(_if.body); - handleAssignment(ass.names(), nullptr); -} - -void Rematerialiser::operator()(Switch& _switch) -{ - boost::apply_visitor(*this, *_switch.expression); - set<string> assignedVariables; - for (auto& _case: _switch.cases) - { - (*this)(_case.body); - Assignments ass; - ass(_case.body); - assignedVariables += ass.names(); - // This is a little too destructive, we could retain the old replacements. - handleAssignment(ass.names(), nullptr); - } - handleAssignment(assignedVariables, nullptr); -} - -void Rematerialiser::operator()(FunctionDefinition& _fun) -{ - m_variableScopes.push_back(make_pair(set<string>(), true)); - for (auto const& parameter: _fun.parameters) - m_variableScopes.back().first.insert(parameter.name); - for (auto const& var: _fun.returnVariables) - m_variableScopes.back().first.insert(var.name); - ASTModifier::operator()(_fun); - m_variableScopes.pop_back(); -} - -void Rematerialiser::operator()(ForLoop& _for) -{ - // Special scope handling of the pre block. - m_variableScopes.push_back(make_pair(set<string>(), false)); - for (auto& statement: _for.pre.statements) - visit(statement); - - Assignments ass; - ass(_for.body); - ass(_for.post); - handleAssignment(ass.names(), nullptr); - - visit(*_for.condition); - (*this)(_for.body); - (*this)(_for.post); - - handleAssignment(ass.names(), nullptr); - - m_variableScopes.pop_back(); -} - -void Rematerialiser::operator()(Block& _block) -{ - size_t numScopes = m_variableScopes.size(); - m_variableScopes.push_back(make_pair(set<string>(), false)); - ASTModifier::operator()(_block); - m_variableScopes.pop_back(); - solAssert(numScopes == m_variableScopes.size(), ""); -} - -void Rematerialiser::handleAssignment(set<string> const& _variables, Expression* _value) -{ - MovableChecker movableChecker; - if (_value) - { - visit(*_value); - movableChecker.visit(*_value); - } - if (_variables.size() == 1) - { - string const& name = *_variables.begin(); - if (movableChecker.movable() && _value) - // TODO Plus heuristic about size of value - // TODO If _value is null, we could use zero. - m_substitutions[name] = _value; - else - m_substitutions.erase(name); - } - else - for (auto const& name: _variables) - m_substitutions.erase(name); - - // Disallow substitutions that use a variable that will be reassigned by this assignment. - for (auto const& name: _variables) - for (auto const& ref: m_referencedBy[name]) - m_substitutions.erase(ref); - // Update the fact which variables are referenced by the newly assigned variables - for (auto const& name: _variables) - { - for (auto const& ref: m_references[name]) - m_referencedBy[ref].erase(name); - m_references[name].clear(); - } - auto const& referencedVariables = movableChecker.referencedVariables(); - for (auto const& name: _variables) - { - m_references[name] = referencedVariables; - for (auto const& ref: referencedVariables) - m_referencedBy[ref].insert(name); - } -} - -bool Rematerialiser::inScope(string const& _variableName) const -{ - for (auto const& scope: m_variableScopes | boost::adaptors::reversed) - { - if (scope.first.count(_variableName)) - return true; - if (scope.second) - return false; - } - return false; -} - void Rematerialiser::visit(Expression& _e) { if (_e.type() == typeid(Identifier)) { Identifier& identifier = boost::get<Identifier>(_e); - if (m_substitutions.count(identifier.name)) + if (m_value.count(identifier.name)) { string name = identifier.name; - bool doSubstitute = true; + bool expressionValid = true; for (auto const& ref: m_references[name]) if (!inScope(ref)) { - doSubstitute = false; + expressionValid = false; break; } - if (doSubstitute) - _e = (ASTCopier{}).translate(*m_substitutions.at(name)); + solAssert(m_value.at(name), ""); + auto const& value = *m_value.at(name); + if (expressionValid && CodeSize::codeSize(value) <= 7) + _e = (ASTCopier{}).translate(value); } } - ASTModifier::visit(_e); + DataFlowAnalyzer::visit(_e); } |