Skip to content

Commit facc380

Browse files
authored
Merge pull request ethereum#14149 from ethereum/enable-minimal-yul-optimizations-by-default
Minimal Yul optimizations by default
2 parents 811b8e5 + 3aaa207 commit facc380

File tree

83 files changed

+1162
-937
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1162
-937
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Compiler Features:
1111
* Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use.
1212
* Standard JSON Interface: Add ``ast`` file-level output for Yul input.
1313
* Standard JSON Interface: Add ``irAst`` and ``irOptimizedAst`` contract-level outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR.
14+
* Yul Optimizer: Stack-to-memory mover is now enabled by default whenever possible for via IR code generation and pure Yul compilation.
1415

1516

1617
Bugfixes:

docs/using-the-compiler.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ Input Description
304304
// optimization-sequence:clean-up-sequence. For more information see
305305
// "The Optimizer > Selecting Optimizations".
306306
// This field is optional, and if not provided, the default sequences for both
307-
// optimization and clean-up are used. If only one of the options is provivded
307+
// optimization and clean-up are used. If only one of the sequences is provided
308308
// the other will not be run.
309309
// If only the delimiter ":" is provided then neither the optimization nor the clean-up
310310
// sequence will be run.

libsolidity/interface/OptimiserSettings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ struct OptimiserSettings
103103
case OptimisationPreset::Minimal: return minimal();
104104
case OptimisationPreset::Standard: return standard();
105105
case OptimisationPreset::Full: return full();
106-
default: solAssert(false, "");
107106
}
107+
util::unreachable();
108108
}
109109

110110
bool operator==(OptimiserSettings const& _other) const

libyul/YulStack.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <libyul/backends/evm/EVMObjectCompiler.h>
3131
#include <libyul/backends/evm/EVMMetrics.h>
3232
#include <libyul/ObjectParser.h>
33+
#include <libyul/optimiser/Semantics.h>
3334
#include <libyul/optimiser/Suite.h>
3435
#include <libevmasm/Assembly.h>
3536
#include <liblangutil/Scanner.h>
@@ -86,10 +87,14 @@ bool YulStack::parseAndAnalyze(std::string const& _sourceName, std::string const
8687

8788
void YulStack::optimize()
8889
{
89-
if (!m_optimiserSettings.runYulOptimiser)
90-
return;
91-
9290
yulAssert(m_analysisSuccessful, "Analysis was not successful.");
91+
yulAssert(m_parserResult);
92+
93+
if (
94+
!m_optimiserSettings.runYulOptimiser &&
95+
yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult)
96+
)
97+
return;
9398

9499
m_analysisSuccessful = false;
95100
yulAssert(m_parserResult, "");
@@ -159,13 +164,15 @@ void YulStack::optimize(Object& _object, bool _isCreation)
159164
unique_ptr<GasMeter> meter;
160165
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&dialect))
161166
meter = make_unique<GasMeter>(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment);
167+
162168
OptimiserSuite::run(
163169
dialect,
164170
meter.get(),
165171
_object,
166-
m_optimiserSettings.optimizeStackAllocation,
167-
m_optimiserSettings.yulOptimiserSteps,
168-
m_optimiserSettings.yulOptimiserCleanupSteps,
172+
// Defaults are the minimum necessary to avoid running into "Stack too deep" constantly.
173+
m_optimiserSettings.runYulOptimiser ? m_optimiserSettings.optimizeStackAllocation : true,
174+
m_optimiserSettings.runYulOptimiser ? m_optimiserSettings.yulOptimiserSteps : "u",
175+
m_optimiserSettings.runYulOptimiser ? m_optimiserSettings.yulOptimiserCleanupSteps : "",
169176
_isCreation ? nullopt : make_optional(m_optimiserSettings.expectedExecutionsPerDeployment),
170177
{}
171178
);
@@ -231,7 +238,15 @@ YulStack::assembleEVMWithDeployed(optional<string_view> _deployName) const
231238

232239
evmasm::Assembly assembly(m_evmVersion, true, {});
233240
EthAssemblyAdapter adapter(assembly);
234-
compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation);
241+
242+
// NOTE: We always need stack optimization when Yul optimizer is disabled (unless code contains
243+
// msize). It being disabled just means that we don't use the full step sequence. We still run
244+
// it with the minimal steps required to avoid "stack too deep".
245+
bool optimize = m_optimiserSettings.optimizeStackAllocation || (
246+
!m_optimiserSettings.runYulOptimiser &&
247+
!yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult)
248+
);
249+
compileEVM(adapter, optimize);
235250

236251
assembly.optimise(evmasm::Assembly::OptimiserSettings::translateSettings(m_optimiserSettings, m_evmVersion));
237252

libyul/optimiser/Semantics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast)
9494
return finder.m_msizeFound;
9595
}
9696

97+
bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object)
98+
{
99+
if (containsMSize(_dialect, *_object.code))
100+
return true;
101+
102+
for (shared_ptr<ObjectNode> const& node: _object.subObjects)
103+
if (auto const* object = dynamic_cast<Object const*>(node.get()))
104+
if (containsMSize(_dialect, *object))
105+
return true;
106+
107+
return false;
108+
}
109+
97110
void MSizeFinder::operator()(FunctionCall const& _functionCall)
98111
{
99112
ASTWalker::operator()(_functionCall);

libyul/optimiser/Semantics.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121

2222
#pragma once
2323

24-
#include <libyul/optimiser/ASTWalker.h>
24+
#include <libyul/AST.h>
25+
#include <libyul/Object.h>
2526
#include <libyul/SideEffects.h>
27+
#include <libyul/optimiser/ASTWalker.h>
2628
#include <libyul/optimiser/CallGraphGenerator.h>
27-
#include <libyul/AST.h>
2829

2930
#include <set>
3031

@@ -143,6 +144,7 @@ class MSizeFinder: public ASTWalker
143144
{
144145
public:
145146
static bool containsMSize(Dialect const& _dialect, Block const& _ast);
147+
static bool containsMSize(Dialect const& _dialect, Object const& _object);
146148

147149
using ASTWalker::operator();
148150
void operator()(FunctionCall const& _funCall) override;

test/cmdlineTests/inline_assembly_function_name_clash/output

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,171 +5,201 @@
55
{
66
"function-debug-runtime":
77
{
8-
"abi_decode_tuple_":
8+
"abi_decode":
99
{
10-
"entryPoint": 117,
10+
"entryPoint": 80,
1111
"parameterSlots": 2,
1212
"returnSlots": 0
1313
},
14-
"abi_encode_t_uint256_to_t_uint256_fromStack":
14+
"abi_encode_uint256":
1515
{
16-
"entryPoint": 149,
16+
"entryPoint": 111,
1717
"parameterSlots": 2,
18-
"returnSlots": 0
18+
"returnSlots": 1
1919
},
20-
"abi_encode_tuple_t_uint256__to_t_uint256__fromStack":
20+
"abi_encode_uint256_to_uint256":
2121
{
22-
"entryPoint": 164,
22+
"entryPoint": 98,
2323
"parameterSlots": 2,
24-
"returnSlots": 1
24+
"returnSlots": 0
2525
},
2626
"allocate_unbounded":
2727
{
28-
"entryPoint": 100,
28+
"entryPoint": 66,
2929
"parameterSlots": 0,
3030
"returnSlots": 1
3131
},
32-
"cleanup_t_uint256":
32+
"cleanup_uint256":
3333
{
34-
"entryPoint": 140,
34+
"entryPoint": 95,
3535
"parameterSlots": 1,
3636
"returnSlots": 1
3737
},
38-
"convert_t_uint256_to_t_uint256":
38+
"convert_uint256_to_uint256":
3939
{
40-
"entryPoint": 398,
40+
"entryPoint": 276,
4141
"parameterSlots": 1,
4242
"returnSlots": 1
4343
},
44-
"external_fun_f_25":
44+
"external_fun_f":
4545
{
46-
"entryPoint": 189,
46+
"entryPoint": 132,
4747
"parameterSlots": 0,
4848
"returnSlots": 0
4949
},
50-
"external_fun_g_36":
50+
"external_fun_g":
5151
{
52-
"entryPoint": 247,
52+
"entryPoint": 185,
5353
"parameterSlots": 0,
5454
"returnSlots": 0
5555
},
56-
"fun_f_25":
56+
"fun_f":
5757
{
58-
"entryPoint": 653,
58+
"entryPoint": 442,
5959
"id": 25,
6060
"parameterSlots": 0,
6161
"returnSlots": 1
6262
},
63-
"fun_f_25_inner":
63+
"fun_f_inner":
6464
{
65-
"entryPoint": 621,
65+
"entryPoint": 430,
6666
"parameterSlots": 1,
6767
"returnSlots": 1
6868
},
69-
"fun_g_36":
69+
"fun_g":
7070
{
71-
"entryPoint": 858,
71+
"entryPoint": 564,
7272
"id": 36,
7373
"parameterSlots": 0,
7474
"returnSlots": 1
7575
},
76-
"fun_g_36_inner":
76+
"fun_g_inner":
7777
{
78-
"entryPoint": 826,
78+
"entryPoint": 552,
7979
"parameterSlots": 1,
8080
"returnSlots": 1
8181
},
8282
"identity":
8383
{
84-
"entryPoint": 389,
84+
"entryPoint": 273,
8585
"parameterSlots": 1,
8686
"returnSlots": 1
8787
},
88-
"modifier_m_17":
88+
"modifier_m":
8989
{
90-
"entryPoint": 475,
90+
"entryPoint": 509,
9191
"id": 14,
9292
"parameterSlots": 1,
9393
"returnSlots": 1
9494
},
95-
"modifier_m_19":
95+
"modifier_m_17":
9696
{
97-
"entryPoint": 548,
97+
"entryPoint": 344,
9898
"id": 14,
9999
"parameterSlots": 1,
100100
"returnSlots": 1
101101
},
102-
"modifier_m_28":
102+
"modifier_m_19":
103103
{
104-
"entryPoint": 680,
104+
"entryPoint": 387,
105105
"id": 14,
106106
"parameterSlots": 1,
107107
"returnSlots": 1
108108
},
109-
"modifier_m_30":
109+
"modifier_m_28":
110110
{
111-
"entryPoint": 753,
111+
"entryPoint": 466,
112112
"id": 14,
113113
"parameterSlots": 1,
114114
"returnSlots": 1
115115
},
116-
"prepare_store_t_uint256":
116+
"prepare_store_uint256":
117117
{
118-
"entryPoint": 431,
118+
"entryPoint": 304,
119119
"parameterSlots": 1,
120120
"returnSlots": 1
121121
},
122122
"revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74":
123123
{
124-
"entryPoint": 305,
124+
"entryPoint": 238,
125125
"parameterSlots": 0,
126126
"returnSlots": 0
127127
},
128128
"revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb":
129129
{
130-
"entryPoint": 109,
130+
"entryPoint": 72,
131131
"parameterSlots": 0,
132132
"returnSlots": 0
133133
},
134134
"revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b":
135135
{
136-
"entryPoint": 113,
136+
"entryPoint": 76,
137137
"parameterSlots": 0,
138138
"returnSlots": 0
139139
},
140-
"shift_left_0":
140+
"shift_left":
141141
{
142-
"entryPoint": 313,
142+
"entryPoint": 246,
143143
"parameterSlots": 1,
144144
"returnSlots": 1
145145
},
146-
"shift_right_224_unsigned":
146+
"shift_right_unsigned":
147147
{
148-
"entryPoint": 88,
148+
"entryPoint": 60,
149149
"parameterSlots": 1,
150150
"returnSlots": 1
151151
},
152-
"update_byte_slice_32_shift_0":
152+
"update_byte_slice_shift":
153153
{
154-
"entryPoint": 324,
154+
"entryPoint": 251,
155155
"parameterSlots": 2,
156156
"returnSlots": 1
157157
},
158-
"update_storage_value_offset_0t_uint256_to_t_uint256":
158+
"update_storage_value_offsett_uint256_to_uint256":
159159
{
160-
"entryPoint": 440,
160+
"entryPoint": 307,
161161
"parameterSlots": 2,
162162
"returnSlots": 0
163163
},
164164
"usr$f":
165165
{
166-
"entryPoint": 496,
166+
"entryPoint": 339,
167+
"parameterSlots": 0,
168+
"returnSlots": 1
169+
},
170+
"usr$f_17":
171+
{
172+
"entryPoint": 382,
173+
"parameterSlots": 0,
174+
"returnSlots": 1
175+
},
176+
"usr$f_22":
177+
{
178+
"entryPoint": 425,
179+
"parameterSlots": 0,
180+
"returnSlots": 1
181+
},
182+
"usr$f_26":
183+
{
184+
"entryPoint": 461,
185+
"parameterSlots": 0,
186+
"returnSlots": 1
187+
},
188+
"usr$f_32":
189+
{
190+
"entryPoint": 504,
191+
"parameterSlots": 0,
192+
"returnSlots": 1
193+
},
194+
"usr$f_37":
195+
{
196+
"entryPoint": 547,
167197
"parameterSlots": 0,
168198
"returnSlots": 1
169199
},
170-
"zero_value_for_split_t_uint256":
200+
"zero_value_for_split_uint256":
171201
{
172-
"entryPoint": 309,
202+
"entryPoint": 242,
173203
"parameterSlots": 0,
174204
"returnSlots": 1
175205
}

0 commit comments

Comments
 (0)