Make full inliner more flexible.

This commit is contained in:
chriseth 2018-10-16 21:38:47 +02:00
parent 7609e2871e
commit b2725aa913
3 changed files with 12 additions and 13 deletions

View File

@ -40,12 +40,9 @@ using namespace dev;
using namespace dev::yul; using namespace dev::yul;
using namespace dev::solidity; using namespace dev::solidity;
FullInliner::FullInliner(Block& _ast): FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser):
m_ast(_ast), m_nameDispenser(_ast) m_ast(_ast), m_nameDispenser(_dispenser)
{ {
assertThrow(m_ast.statements.size() >= 1, OptimizerException, "");
assertThrow(m_ast.statements.front().type() == typeid(Block), OptimizerException, "");
// Determine constants // Determine constants
SSAValueTracker tracker; SSAValueTracker tracker;
tracker(m_ast); tracker(m_ast);
@ -54,10 +51,11 @@ FullInliner::FullInliner(Block& _ast):
m_constants.insert(ssaValue.first); m_constants.insert(ssaValue.first);
map<string, size_t> references = ReferencesCounter::countReferences(m_ast); map<string, size_t> references = ReferencesCounter::countReferences(m_ast);
for (size_t i = 1; i < m_ast.statements.size(); ++i) for (auto& statement: m_ast.statements)
{ {
assertThrow(m_ast.statements.at(i).type() == typeid(FunctionDefinition), OptimizerException, ""); if (statement.type() != typeid(FunctionDefinition))
FunctionDefinition& fun = boost::get<FunctionDefinition>(m_ast.statements.at(i)); continue;
FunctionDefinition& fun = boost::get<FunctionDefinition>(statement);
m_functions[fun.name] = &fun; m_functions[fun.name] = &fun;
// Always inline functions that are only called once. // Always inline functions that are only called once.
if (references[fun.name] == 1) if (references[fun.name] == 1)
@ -68,9 +66,10 @@ FullInliner::FullInliner(Block& _ast):
void FullInliner::run() void FullInliner::run()
{ {
assertThrow(m_ast.statements[0].type() == typeid(Block), OptimizerException, ""); for (auto& statement: m_ast.statements)
if (statement.type() == typeid(Block))
handleBlock("", boost::get<Block>(statement));
handleBlock("", boost::get<Block>(m_ast.statements[0]));
// TODO it might be good to determine a visiting order: // TODO it might be good to determine a visiting order:
// first handle functions that are called from many places. // first handle functions that are called from many places.
for (auto const& fun: m_functions) for (auto const& fun: m_functions)

View File

@ -71,7 +71,7 @@ class NameCollector;
class FullInliner: public ASTModifier class FullInliner: public ASTModifier
{ {
public: public:
explicit FullInliner(Block& _ast); explicit FullInliner(Block& _ast, NameDispenser& _dispenser);
void run(); void run();
@ -94,7 +94,7 @@ private:
/// Variables that are constants (used for inlining heuristic) /// Variables that are constants (used for inlining heuristic)
std::set<std::string> m_constants; std::set<std::string> m_constants;
std::map<std::string, size_t> m_functionSizes; std::map<std::string, size_t> m_functionSizes;
NameDispenser m_nameDispenser; NameDispenser& m_nameDispenser;
}; };
/** /**

View File

@ -131,7 +131,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
(FunctionGrouper{})(*m_ast); (FunctionGrouper{})(*m_ast);
NameDispenser nameDispenser(*m_ast); NameDispenser nameDispenser(*m_ast);
ExpressionSplitter{nameDispenser}(*m_ast); ExpressionSplitter{nameDispenser}(*m_ast);
FullInliner(*m_ast).run(); FullInliner(*m_ast, nameDispenser).run();
ExpressionJoiner::run(*m_ast); ExpressionJoiner::run(*m_ast);
} }
else if (m_optimizerStep == "mainFunction") else if (m_optimizerStep == "mainFunction")