Inline each function separately.

This commit is contained in:
chriseth 2018-10-16 17:21:14 +02:00
parent a435a14e13
commit 2ab6430303
4 changed files with 29 additions and 69 deletions

View File

@ -50,7 +50,6 @@ FullInliner::FullInliner(Block& _ast):
assertThrow(m_ast.statements.at(i).type() == typeid(FunctionDefinition), OptimizerException, ""); assertThrow(m_ast.statements.at(i).type() == typeid(FunctionDefinition), OptimizerException, "");
FunctionDefinition& fun = boost::get<FunctionDefinition>(m_ast.statements.at(i)); FunctionDefinition& fun = boost::get<FunctionDefinition>(m_ast.statements.at(i));
m_functions[fun.name] = &fun; m_functions[fun.name] = &fun;
m_functionsToVisit.insert(&fun);
} }
} }
@ -59,17 +58,8 @@ void FullInliner::run()
assertThrow(m_ast.statements[0].type() == typeid(Block), OptimizerException, ""); assertThrow(m_ast.statements[0].type() == typeid(Block), OptimizerException, "");
handleBlock("", boost::get<Block>(m_ast.statements[0])); handleBlock("", boost::get<Block>(m_ast.statements[0]));
while (!m_functionsToVisit.empty()) for (auto const& fun: m_functions)
handleFunction(**m_functionsToVisit.begin()); handleBlock(fun.second->name, fun.second->body);
}
void FullInliner::handleFunction(FunctionDefinition& _fun)
{
if (!m_functionsToVisit.count(&_fun))
return;
m_functionsToVisit.erase(&_fun);
handleBlock(_fun.name, _fun.body);
} }
void FullInliner::handleBlock(string const& _currentFunctionName, Block& _block) void FullInliner::handleBlock(string const& _currentFunctionName, Block& _block)
@ -102,28 +92,27 @@ boost::optional<vector<Statement>> InlineModifier::tryInlineStatement(Statement&
), *e); ), *e);
if (funCall) if (funCall)
{ {
FunctionDefinition& fun = m_driver.function(funCall->functionName.name);
m_driver.handleFunction(fun);
// TODO: Insert good heuristic here. Perhaps implement that inside the driver. // TODO: Insert good heuristic here. Perhaps implement that inside the driver.
bool doInline = funCall->functionName.name != m_currentFunction; bool doInline = funCall->functionName.name != m_currentFunction;
if (doInline) if (doInline)
return performInline(_statement, *funCall, fun); return performInline(_statement, *funCall);
} }
} }
return {}; return {};
} }
vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall, FunctionDefinition& _function) vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall)
{ {
vector<Statement> newStatements; vector<Statement> newStatements;
map<string, string> variableReplacements; map<string, string> variableReplacements;
FunctionDefinition& function = m_driver.function(_funCall.functionName.name);
// helper function to create a new variable that is supposed to model // helper function to create a new variable that is supposed to model
// an existing variable. // an existing variable.
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) { auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
string newName = m_nameDispenser.newName(_function.name + "_" + _existingVariable.name); string newName = m_nameDispenser.newName(function.name + "_" + _existingVariable.name);
variableReplacements[_existingVariable.name] = newName; variableReplacements[_existingVariable.name] = newName;
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}}; VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
if (_value) if (_value)
@ -132,11 +121,11 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
}; };
for (size_t i = 0; i < _funCall.arguments.size(); ++i) for (size_t i = 0; i < _funCall.arguments.size(); ++i)
newVariable(_function.parameters[i], &_funCall.arguments[i]); newVariable(function.parameters[i], &_funCall.arguments[i]);
for (auto const& var: _function.returnVariables) for (auto const& var: function.returnVariables)
newVariable(var, nullptr); newVariable(var, nullptr);
Statement newBody = BodyCopier(m_nameDispenser, _function.name + "_", variableReplacements)(_function.body); Statement newBody = BodyCopier(m_nameDispenser, function.name + "_", variableReplacements)(function.body);
newStatements += std::move(boost::get<Block>(newBody).statements); newStatements += std::move(boost::get<Block>(newBody).statements);
boost::apply_visitor(GenericFallbackVisitor<Assignment, VariableDeclaration>{ boost::apply_visitor(GenericFallbackVisitor<Assignment, VariableDeclaration>{
@ -148,7 +137,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
{_assignment.variableNames[i]}, {_assignment.variableNames[i]},
make_shared<Expression>(Identifier{ make_shared<Expression>(Identifier{
_assignment.location, _assignment.location,
variableReplacements.at(_function.returnVariables[i].name) variableReplacements.at(function.returnVariables[i].name)
}) })
}); });
}, },
@ -160,7 +149,7 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
{std::move(_varDecl.variables[i])}, {std::move(_varDecl.variables[i])},
make_shared<Expression>(Identifier{ make_shared<Expression>(Identifier{
_varDecl.location, _varDecl.location,
variableReplacements.at(_function.returnVariables[i].name) variableReplacements.at(function.returnVariables[i].name)
}) })
}); });
} }

View File

@ -75,9 +75,6 @@ public:
void run(); void run();
/// Perform inlining operations inside the given function.
void handleFunction(FunctionDefinition& _function);
FunctionDefinition& function(std::string _name) { return *m_functions.at(_name); } FunctionDefinition& function(std::string _name) { return *m_functions.at(_name); }
private: private:
@ -87,7 +84,6 @@ private:
/// we store pointers to functions. /// we store pointers to functions.
Block& m_ast; Block& m_ast;
std::map<std::string, FunctionDefinition*> m_functions; std::map<std::string, FunctionDefinition*> m_functions;
std::set<FunctionDefinition*> m_functionsToVisit;
NameDispenser m_nameDispenser; NameDispenser m_nameDispenser;
}; };
@ -108,7 +104,7 @@ public:
private: private:
boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement); boost::optional<std::vector<Statement>> tryInlineStatement(Statement& _statement);
std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall, FunctionDefinition& _function); std::vector<Statement> performInline(Statement& _statement, FunctionCall& _funCall);
std::string newName(std::string const& _prefix); std::string newName(std::string const& _prefix);

View File

@ -14,10 +14,7 @@
// let g_b := f_x // let g_b := f_x
// let g_c := _1 // let g_c := _1
// let g_y // let g_y
// let g_f_a_1 := g_b // g_y := mul(mload(g_c), f(g_b))
// let g_f_x_1
// g_f_x_1 := add(g_f_a_1, g_f_a_1)
// g_y := mul(mload(g_c), g_f_x_1)
// let y_1 := g_y // let y_1 := g_y
// } // }
// function f(a) -> x // function f(a) -> x

View File

@ -27,23 +27,11 @@
// { // {
// { // {
// { // {
// let f_x_1 := 100 // let f_x := 100
// mstore(0, f_x_1) // mstore(0, f_x)
// let f_h_t // mstore(7, h())
// f_h_t := 2 // g(10)
// mstore(7, f_h_t) // mstore(1, f_x)
// let f__5 := 10
// let f_g_x_1 := f__5
// let f_g_f_x := 1
// let
// mstore()
// let f_g_f_ := h()
// let
// mstore()
// let
// g(f__5)
// mstore(1, f_g_f_x)
// mstore(1, f_x_1)
// } // }
// } // }
// function f(x) // function f(x)
@ -52,30 +40,20 @@
// let h_t // let h_t
// h_t := 2 // h_t := 2
// mstore(7, h_t) // mstore(7, h_t)
// let _5 := 10 // let g_x_1 := 10
// let g_x_1 := _5 // f(1)
// let g_f_x := 1
// let
// mstore()
// let g_f_ := h()
// let
// mstore()
// let
// g(_5)
// mstore(1, g_f_x)
// mstore(1, x) // mstore(1, x)
// } // }
// function g(x_1) // function g(x_1)
// { // {
// let f_x := 1 // let f_x_1 := 1
// let // mstore(0, f_x_1)
// mstore() // let f_h_t
// let f_ := h() // f_h_t := 2
// let // mstore(7, f_h_t)
// mstore() // let f_g_x_1 := 10
// let // f(1)
// g(_5) // mstore(1, f_x_1)
// mstore(1, f_x)
// } // }
// function h() -> t // function h() -> t
// { // {