From 33abdfab766da674514f490904c351286b1784c1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 23 Nov 2017 17:42:06 +0100 Subject: Inlinable function filter. --- libjulia/optimiser/InlinableFunctionFilter.cpp | 68 ++++++++++++++++++++++++ libjulia/optimiser/InlinableFunctionFilter.h | 71 ++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 libjulia/optimiser/InlinableFunctionFilter.cpp create mode 100644 libjulia/optimiser/InlinableFunctionFilter.h (limited to 'libjulia/optimiser') diff --git a/libjulia/optimiser/InlinableFunctionFilter.cpp b/libjulia/optimiser/InlinableFunctionFilter.cpp new file mode 100644 index 00000000..db9f812d --- /dev/null +++ b/libjulia/optimiser/InlinableFunctionFilter.cpp @@ -0,0 +1,68 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * Optimiser component that identifies functions to be inlined. + */ + +#include + +#include + +#include + +using namespace std; +using namespace dev; +using namespace dev::julia; + +void InlinableFunctionFilter::operator()(Identifier const& _identifier) +{ + checkAllowed(_identifier.name); + ASTWalker::operator()(_identifier); +} + +void InlinableFunctionFilter::operator()(FunctionCall const& _funCall) +{ + checkAllowed(_funCall.functionName.name); + ASTWalker::operator()(_funCall); +} + +void InlinableFunctionFilter::operator()(FunctionDefinition const& _function) +{ + if (_function.returnVariables.size() == 1 && _function.body.statements.size() == 1) + { + string const& retVariable = _function.returnVariables.front().name; + Statement const& bodyStatement = _function.body.statements.front(); + if (bodyStatement.type() == typeid(Assignment)) + { + Assignment const& assignment = boost::get(bodyStatement); + if (assignment.variableNames.size() == 1 && assignment.variableNames.front().name == retVariable) + { + // We cannot overwrite previous settings, because this function definition + // would not be valid here if we were searching inside a functionally inlinable + // function body. + solAssert(m_disallowedIdentifiers.empty() && !m_foundDisallowedIdentifier, ""); + m_disallowedIdentifiers = set{retVariable, _function.name}; + boost::apply_visitor(*this, *assignment.value); + if (!m_foundDisallowedIdentifier) + m_inlinableFunctions[_function.name] = &_function; + m_disallowedIdentifiers.clear(); + m_foundDisallowedIdentifier = false; + } + } + } + ASTWalker::operator()(_function.body); +} diff --git a/libjulia/optimiser/InlinableFunctionFilter.h b/libjulia/optimiser/InlinableFunctionFilter.h new file mode 100644 index 00000000..e0265059 --- /dev/null +++ b/libjulia/optimiser/InlinableFunctionFilter.h @@ -0,0 +1,71 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * Optimiser component that identifies functions to be inlined. + */ + +#pragma once + +#include +#include + +#include + +#include + +namespace dev +{ +namespace julia +{ + +/** + * Optimiser component that finds functions that can be + * inlined inside functional expressions, i.e. functions that + * - have a single return parameter r + * - have a body like r := + * - neither reference themselves nor r in the right hand side + * + * This component can only be used on sources with unique names. + */ +class InlinableFunctionFilter: public ASTWalker +{ +public: + + std::map const& inlinableFunctions() const + { + return m_inlinableFunctions; + } + + using ASTWalker::operator(); + virtual void operator()(Identifier const& _identifier) override; + virtual void operator()(FunctionCall const& _funCall) override; + virtual void operator()(FunctionDefinition const& _function) override; + +private: + void checkAllowed(std::string const& _name) + { + if (m_disallowedIdentifiers.count(_name)) + m_foundDisallowedIdentifier = true; + } + + bool m_foundDisallowedIdentifier = false; + std::set m_disallowedIdentifiers; + std::map m_inlinableFunctions; +}; + +} +} -- cgit