Merge pull request #6820 from ethereum/noRecursiveInline

Do not inline recursive functions.
This commit is contained in:
chriseth 2019-05-22 22:53:47 +02:00 committed by GitHub
commit a86a88f123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 19 deletions

View File

@ -14,6 +14,7 @@ Compiler Features:
* Metadata: Add IPFS hashes of source files. * Metadata: Add IPFS hashes of source files.
* Assembler: Encode the compiler version in the deployed bytecode. * Assembler: Encode the compiler version in the deployed bytecode.
* Yul Optimizer: Simplify single-run ``for`` loops to ``if`` statements. * Yul Optimizer: Simplify single-run ``for`` loops to ``if`` statements.
* Yul Optimizer: Do not inline recursive functions.
* Optimizer: Add rules for multiplication and division by left-shifted one. * Optimizer: Add rules for multiplication and division by left-shifted one.

View File

@ -79,16 +79,6 @@ void FullInliner::run()
} }
} }
void FullInliner::updateCodeSize(FunctionDefinition const& _fun)
{
m_functionSizes[_fun.name] = CodeSize::codeSize(_fun.body);
}
void FullInliner::handleBlock(YulString _currentFunctionName, Block& _block)
{
InlineModifier{*this, m_nameDispenser, _currentFunctionName}(_block);
}
bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite) bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
{ {
// No recursive inlining // No recursive inlining
@ -99,6 +89,9 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
if (!calledFunction) if (!calledFunction)
return false; return false;
if (recursive(*calledFunction))
return false;
// Inline really, really tiny functions // Inline really, really tiny functions
size_t size = m_functionSizes.at(calledFunction->name); size_t size = m_functionSizes.at(calledFunction->name);
if (size <= 1) if (size <= 1)
@ -131,6 +124,21 @@ void FullInliner::tentativelyUpdateCodeSize(YulString _function, YulString _call
m_functionSizes.at(_callSite) += m_functionSizes.at(_function); m_functionSizes.at(_callSite) += m_functionSizes.at(_function);
} }
void FullInliner::updateCodeSize(FunctionDefinition const& _fun)
{
m_functionSizes[_fun.name] = CodeSize::codeSize(_fun.body);
}
void FullInliner::handleBlock(YulString _currentFunctionName, Block& _block)
{
InlineModifier{*this, m_nameDispenser, _currentFunctionName}(_block);
}
bool FullInliner::recursive(FunctionDefinition const& _fun) const
{
map<YulString, size_t> references = ReferencesCounter::countReferences(_fun);
return references[_fun.name] > 0;
}
void InlineModifier::operator()(Block& _block) void InlineModifier::operator()(Block& _block)
{ {

View File

@ -93,6 +93,7 @@ public:
private: private:
void updateCodeSize(FunctionDefinition const& _fun); void updateCodeSize(FunctionDefinition const& _fun);
void handleBlock(YulString _currentFunctionName, Block& _block); void handleBlock(YulString _currentFunctionName, Block& _block);
bool recursive(FunctionDefinition const& _fun) const;
/// The AST to be modified. The root block itself will not be modified, because /// The AST to be modified. The root block itself will not be modified, because
/// we store pointers to functions. /// we store pointers to functions.

View File

@ -39,12 +39,7 @@
// let t_20 := 0 // let t_20 := 0
// t_20 := 2 // t_20 := 2
// mstore(7, t_20) // mstore(7, t_20)
// let x_1_21 := 10
// let x_14_23 := 1
// mstore(0, x_14_23)
// mstore(7, h())
// g(10) // g(10)
// mstore(1, x_14_23)
// mstore(1, x) // mstore(1, x)
// } // }
// function g(x_1) // function g(x_1)

View File

@ -8,10 +8,7 @@
// step: fullInliner // step: fullInliner
// ---- // ----
// { // {
// { // { f(mload(0)) }
// let a_4 := mload(0)
// f(1)
// }
// function f(a) // function f(a)
// { f(1) } // { f(1) }
// } // }