Skip to content

Commit 7168c27

Browse files
ekpyronchriseth
authored andcommitted
Relax inliner heuristics.
1 parent f08d349 commit 7168c27

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Language Features:
77

88
Compiler Features:
99
* LSP: Add rudimentary support for semantic highlighting.
10+
* Yul Optimizer: Improve inlining heuristics for via IR code generation and pure Yul compilation.
1011

1112

1213
Bugfixes:

libyul/optimiser/FullInliner.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
#include <libyul/optimiser/FullInliner.h>
2323

2424
#include <libyul/optimiser/ASTCopier.h>
25+
#include <libyul/optimiser/CallGraphGenerator.h>
26+
#include <libyul/optimiser/FunctionCallFinder.h>
2527
#include <libyul/optimiser/NameCollector.h>
2628
#include <libyul/optimiser/Metrics.h>
2729
#include <libyul/optimiser/SSAValueTracker.h>
2830
#include <libyul/optimiser/Semantics.h>
2931
#include <libyul/optimiser/CallGraphGenerator.h>
32+
#include <libyul/backends/evm/EVMDialect.h>
3033
#include <libyul/Exceptions.h>
3134
#include <libyul/AST.h>
3235
#include <libyul/Dialect.h>
@@ -46,8 +49,12 @@ void FullInliner::run(OptimiserStepContext& _context, Block& _ast)
4649
}
4750

4851
FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& _dialect):
49-
m_ast(_ast), m_nameDispenser(_dispenser), m_dialect(_dialect)
52+
m_ast(_ast),
53+
m_recursiveFunctions(CallGraphGenerator::callGraph(_ast).recursiveFunctions()),
54+
m_nameDispenser(_dispenser),
55+
m_dialect(_dialect)
5056
{
57+
5158
// Determine constants
5259
SSAValueTracker tracker;
5360
tracker(m_ast);
@@ -71,6 +78,15 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const&
7178
m_singleUse.emplace(fun.name);
7279
updateCodeSize(fun);
7380
}
81+
82+
// Check for memory guard.
83+
vector<FunctionCall*> memoryGuardCalls = FunctionCallFinder::run(
84+
_ast,
85+
"memoryguard"_yulstring
86+
);
87+
// We will perform less aggressive inlining, if no ``memoryguard`` call is found.
88+
if (!memoryGuardCalls.empty())
89+
m_hasMemoryGuard = true;
7490
}
7591

7692
void FullInliner::run(Pass _pass)
@@ -177,8 +193,20 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
177193
if (m_pass == Pass::InlineTiny)
178194
return false;
179195

180-
// Do not inline into already big functions.
181-
if (m_functionSizes.at(_callSite) > 45)
196+
bool aggressiveInlining = true;
197+
198+
if (
199+
EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&m_dialect);
200+
!evmDialect || !evmDialect->providesObjectAccess() || evmDialect->evmVersion() <= langutil::EVMVersion::homestead()
201+
)
202+
// No aggressive inlining with the old code transform.
203+
aggressiveInlining = false;
204+
205+
// No aggressive inlining, if we cannot perform stack-to-memory.
206+
if (!m_hasMemoryGuard || m_recursiveFunctions.count(_callSite))
207+
aggressiveInlining = false;
208+
209+
if (!aggressiveInlining && m_functionSizes.at(_callSite) > 45)
182210
return false;
183211

184212
if (m_singleUse.count(calledFunction->name))
@@ -196,7 +224,7 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
196224
break;
197225
}
198226

199-
return (size < 6 || (constantArg && size < 12));
227+
return (size < (aggressiveInlining ? 8 : 6) || (constantArg && size < (aggressiveInlining ? 16 : 12)));
200228
}
201229

202230
void FullInliner::tentativelyUpdateCodeSize(YulString _function, YulString _callSite)

libyul/optimiser/FullInliner.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ class FullInliner: public ASTModifier
111111
std::map<YulString, FunctionDefinition*> m_functions;
112112
/// Functions not to be inlined (because they contain the ``leave`` statement).
113113
std::set<YulString> m_noInlineFunctions;
114+
/// True, if the code contains a ``memoryguard`` and we can expect to be able to move variables to memory later.
115+
bool m_hasMemoryGuard = false;
116+
/// Set of recursive functions.
117+
std::set<YulString> m_recursiveFunctions;
114118
/// Names of functions to always inline.
115119
std::set<YulString> m_singleUse;
116120
/// Variables that are constants (used for inlining heuristic)

0 commit comments

Comments
 (0)