22
22
#include < libyul/optimiser/FullInliner.h>
23
23
24
24
#include < libyul/optimiser/ASTCopier.h>
25
+ #include < libyul/optimiser/CallGraphGenerator.h>
26
+ #include < libyul/optimiser/FunctionCallFinder.h>
25
27
#include < libyul/optimiser/NameCollector.h>
26
28
#include < libyul/optimiser/Metrics.h>
27
29
#include < libyul/optimiser/SSAValueTracker.h>
28
30
#include < libyul/optimiser/Semantics.h>
29
31
#include < libyul/optimiser/CallGraphGenerator.h>
32
+ #include < libyul/backends/evm/EVMDialect.h>
30
33
#include < libyul/Exceptions.h>
31
34
#include < libyul/AST.h>
32
35
#include < libyul/Dialect.h>
@@ -46,8 +49,12 @@ void FullInliner::run(OptimiserStepContext& _context, Block& _ast)
46
49
}
47
50
48
51
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)
50
56
{
57
+
51
58
// Determine constants
52
59
SSAValueTracker tracker;
53
60
tracker (m_ast);
@@ -71,6 +78,15 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const&
71
78
m_singleUse.emplace (fun.name );
72
79
updateCodeSize (fun);
73
80
}
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 ;
74
90
}
75
91
76
92
void FullInliner::run (Pass _pass)
@@ -177,8 +193,20 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
177
193
if (m_pass == Pass::InlineTiny)
178
194
return false ;
179
195
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 )
182
210
return false ;
183
211
184
212
if (m_singleUse.count (calledFunction->name ))
@@ -196,7 +224,7 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite)
196
224
break ;
197
225
}
198
226
199
- return (size < 6 || (constantArg && size < 12 ));
227
+ return (size < (aggressiveInlining ? 8 : 6 ) || (constantArg && size < (aggressiveInlining ? 16 : 12 ) ));
200
228
}
201
229
202
230
void FullInliner::tentativelyUpdateCodeSize (YulString _function, YulString _callSite)
0 commit comments