Skip to content

Commit e37dc8e

Browse files
committed
Address review comments
1 parent feba1bf commit e37dc8e

File tree

23 files changed

+108
-243
lines changed

23 files changed

+108
-243
lines changed

Changelog.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ Language Features:
44

55

66
Compiler Features:
7-
* Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (`:`) in the sequence string.
7+
* Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string.
8+
89

910
Bugfixes:
1011

@@ -21,7 +22,7 @@ Compiler Features:
2122
* Yul Optimizer: Simplify the starting offset of zero-length operations to zero.
2223

2324

24-
Bugfixes:`````
25+
Bugfixes:
2526
* Type Checker: Fix internal compiler error on tuple assignments with invalid left-hand side.
2627
* Yul IR Code Generation: Fix internal compiler error when accessing the ``.slot`` member of a mapping through a storage reference in inline assembly.
2728

docs/internals/optimizer.rst

+69-34
Original file line numberDiff line numberDiff line change
@@ -281,50 +281,85 @@ The following transformation steps are the main components:
281281
- Redundant Assign Eliminator
282282
- Full Inliner
283283

284+
.. _optimizer-steps:
285+
284286
Optimizer Steps
285287
---------------
286288

287289
This is a list of all steps the Yul-based optimizer sorted alphabetically. You can find more information
288290
on the individual steps and their sequence below.
289291

290-
- :ref:`block-flattener`.
291-
- :ref:`circular-reference-pruner`.
292-
- :ref:`common-subexpression-eliminator`.
293-
- :ref:`conditional-simplifier`.
294-
- :ref:`conditional-unsimplifier`.
295-
- :ref:`control-flow-simplifier`.
296-
- :ref:`dead-code-eliminator`.
297-
- :ref:`equal-store-eliminator`.
298-
- :ref:`equivalent-function-combiner`.
299-
- :ref:`expression-joiner`.
300-
- :ref:`expression-simplifier`.
301-
- :ref:`expression-splitter`.
302-
- :ref:`for-loop-condition-into-body`.
303-
- :ref:`for-loop-condition-out-of-body`.
304-
- :ref:`for-loop-init-rewriter`.
305-
- :ref:`expression-inliner`.
306-
- :ref:`full-inliner`.
307-
- :ref:`function-grouper`.
308-
- :ref:`function-hoister`.
309-
- :ref:`function-specializer`.
310-
- :ref:`literal-rematerialiser`.
311-
- :ref:`load-resolver`.
312-
- :ref:`loop-invariant-code-motion`.
313-
- :ref:`redundant-assign-eliminator`.
314-
- :ref:`reasoning-based-simplifier`.
315-
- :ref:`rematerialiser`.
316-
- :ref:`SSA-reverser`.
317-
- :ref:`SSA-transform`.
318-
- :ref:`structural-simplifier`.
319-
- :ref:`unused-function-parameter-pruner`.
320-
- :ref:`unused-pruner`.
321-
- :ref:`var-decl-initializer`.
292+
============ ===============================
293+
Abbreviation Full name
294+
============ ===============================
295+
``f`` :ref:`block-flattener`
296+
``l`` :ref:`circular-reference-pruner`
297+
``c`` :ref:`common-subexpression-eliminator`
298+
``C`` :ref:`conditional-simplifier`
299+
``U`` :ref:`conditional-unsimplifier`
300+
``n`` :ref:`control-flow-simplifier`
301+
``D`` :ref:`dead-code-eliminator`
302+
``E`` :ref:`equal-store-eliminator`
303+
``v`` :ref:`equivalent-function-combiner`
304+
``e`` :ref:`expression-inliner`
305+
``j`` :ref:`expression-joiner`
306+
``s`` :ref:`expression-simplifier`
307+
``x`` :ref:`expression-splitter`
308+
``I`` :ref:`for-loop-condition-into-body`
309+
``O`` :ref:`for-loop-condition-out-of-body`
310+
``o`` :ref:`for-loop-init-rewriter`
311+
``i`` :ref:`full-inliner`
312+
``g`` :ref:`function-grouper`
313+
``h`` :ref:`function-hoister`
314+
``F`` :ref:`function-specializer`
315+
``T`` :ref:`literal-rematerialiser`
316+
``L`` :ref:`load-resolver`
317+
``M`` :ref:`loop-invariant-code-motion`
318+
``r`` :ref:`redundant-assign-eliminator`
319+
``R`` :ref:`reasoning-based-simplifier` - highly experimental
320+
``m`` :ref:`rematerialiser`
321+
``V`` :ref:`SSA-reverser`
322+
``a`` :ref:`SSA-transform`
323+
``t`` :ref:`structural-simplifier`
324+
``p`` :ref:`unused-function-parameter-pruner`
325+
``u`` :ref:`unused-pruner`
326+
``d`` :ref:`var-decl-initializer`
327+
============ ===============================
328+
329+
Some steps depend on properties ensured by ``BlockFlattener``, ``FunctionGrouper``, ``ForLoopInitRewriter``.
330+
For this reason the Yul optimizer always applies them before applying any steps supplied by the user.
331+
332+
The ReasoningBasedSimplifier is an optimizer step that is currently not enabled
333+
in the default set of steps. It uses an SMT solver to simplify arithmetic expressions
334+
and boolean conditions. It has not received thorough testing or validation yet and can produce
335+
non-reproducible results, so please use with care!
322336

323337
Selecting Optimizations
324338
-----------------------
325339

326-
Detailed information regrading the optimization sequence as well a list of abbreviations is
327-
available in the :ref:`Yul optimizer docs <optimization-step-sequence>`.
340+
By default the optimizer applies its predefined sequence of optimization steps to the generated assembly.
341+
You can override this sequence and supply your own using the ``--yul-optimizations`` option:
342+
343+
.. code-block:: bash
344+
345+
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc'
346+
347+
The order of steps is significant and affects the quality of the output.
348+
Moreover, applying a step may uncover new optimization opportunities for others that were already applied,
349+
so repeating steps is often beneficial.
350+
351+
The sequence inside ``[...]`` will be applied multiple times in a loop until the Yul code
352+
remains unchanged or until the maximum number of rounds (currently 12) has been reached.
353+
Brackets (``[]``) may be used multiple times in a sequence, but can not be nested.
354+
355+
An important thing to note, is that there are some hardcoded steps that are always run before and after the
356+
user-supplied sequence, or the default sequence if one was not supplied by the user.
357+
358+
The cleanup sequence delimiter ``:`` is optional, and is used to supply a custom cleanup sequence
359+
in order to replace the default one. If omitted, the optimizer will simply apply the default cleanup
360+
sequence. In addition, the delimiter may be placed at the beginning of the user-supplied sequence,
361+
which will result in the optimization sequence being empty, whereas conversely, if placed at the end of
362+
the sequence, will be treated as an empty cleanup sequence.
328363

329364
Preprocessing
330365
-------------

docs/yul.rst

+2-66
Original file line numberDiff line numberDiff line change
@@ -1245,72 +1245,8 @@ In Solidity mode, the Yul optimizer is activated together with the regular optim
12451245
Optimization Step Sequence
12461246
--------------------------
12471247

1248-
By default the optimizer applies its predefined sequence of optimization steps to
1249-
the generated assembly. You can override this sequence and supply your own using
1250-
the ``--yul-optimizations`` option:
1251-
1252-
.. code-block:: bash
1253-
1254-
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc'
1255-
1256-
The sequence inside ``[...]`` will be applied multiple times in a loop until the Yul code
1257-
remains unchanged or until the maximum number of rounds (currently 12) has been reached.
1258-
1259-
An important thing to note, is that there are hardcoded sequences that are run before and after the
1260-
user-supplied sequence, or the default sequence if one was not supplied by the user.
1261-
1262-
The cleanup sequence delimiter ``:`` is optional, and is used to supply a custom cleanup sequence
1263-
in order to replace the default one. If omitted, the optimizer will simply apply the default cleanup
1264-
sequence. In addition, the delimiter may be placed at the beginning of the user-supplied sequence,
1265-
which will be treated as an empty optimization sequence, whereas conversely, if placed at the end of
1266-
the sequence, will be treated as an empty cleanup sequence.
1267-
1268-
1269-
The following optimization steps are available:
1270-
1271-
============ ===============================
1272-
Abbreviation Full name
1273-
============ ===============================
1274-
``f`` ``BlockFlattener``
1275-
``l`` ``CircularReferencesPruner``
1276-
``c`` ``CommonSubexpressionEliminator``
1277-
``C`` ``ConditionalSimplifier``
1278-
``U`` ``ConditionalUnsimplifier``
1279-
``n`` ``ControlFlowSimplifier``
1280-
``D`` ``DeadCodeEliminator``
1281-
``v`` ``EquivalentFunctionCombiner``
1282-
``e`` ``ExpressionInliner``
1283-
``j`` ``ExpressionJoiner``
1284-
``s`` ``ExpressionSimplifier``
1285-
``x`` ``ExpressionSplitter``
1286-
``I`` ``ForLoopConditionIntoBody``
1287-
``O`` ``ForLoopConditionOutOfBody``
1288-
``o`` ``ForLoopInitRewriter``
1289-
``i`` ``FullInliner``
1290-
``g`` ``FunctionGrouper``
1291-
``h`` ``FunctionHoister``
1292-
``F`` ``FunctionSpecializer``
1293-
``T`` ``LiteralRematerialiser``
1294-
``L`` ``LoadResolver``
1295-
``M`` ``LoopInvariantCodeMotion``
1296-
``r`` ``RedundantAssignEliminator``
1297-
``R`` ``ReasoningBasedSimplifier`` - highly experimental
1298-
``m`` ``Rematerialiser``
1299-
``V`` ``SSAReverser``
1300-
``a`` ``SSATransform``
1301-
``t`` ``StructuralSimplifier``
1302-
``u`` ``UnusedPruner``
1303-
``p`` ``UnusedFunctionParameterPruner``
1304-
``d`` ``VarDeclInitializer``
1305-
============ ===============================
1306-
1307-
Some steps depend on properties ensured by ``BlockFlattener``, ``FunctionGrouper``, ``ForLoopInitRewriter``.
1308-
For this reason the Yul optimizer always applies them before applying any steps supplied by the user.
1309-
1310-
The ReasoningBasedSimplifier is an optimizer step that is currently not enabled
1311-
in the default set of steps. It uses an SMT solver to simplify arithmetic expressions
1312-
and boolean conditions. It has not received thorough testing or validation yet and can produce
1313-
non-reproducible results, so please use with care!
1248+
Detailed information regrading the optimization sequence as well a list of abbreviations is
1249+
available in the :ref:`optimizer docs <optimizer-steps>`.
13141250

13151251
.. _erc20yul:
13161252

libsolidity/interface/StandardCompiler.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details
496496

497497
if (delimiterPos != string::npos)
498498
_cleanupSetting = fullSequence.substr(delimiterPos + 1);
499+
else
500+
solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps);
499501
}
500502
else
501503
return formatFatalError("JSONError", "\"settings.optimizer.details." + _name + "\" must be a string");

libyul/optimiser/Suite.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ void OptimiserSuite::run(
143143

144144
// Run the user-supplied clean up sequence
145145
suite.runSequence(_optimisationCleanupSequence, ast);
146+
// Hard-coded FunctionGrouper step is used to bring the AST into a canonical form required by the StackCompressor
147+
// and StackLimitEvader. This is hard-coded as the last step, as some previously executed steps may break the
148+
// aforementioned form, thus causing the StackCompressor/StackLimitEvader to throw.
146149
suite.runSequence("g", ast);
147150

148151
if (evmDialect)
@@ -318,7 +321,7 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations)
318321
case ':':
319322
++colonDelimiters;
320323
assertThrow(nestingLevel == 0, OptimizerException, "Cleanup sequence delimiter cannot be placed inside the brackets");
321-
assertThrow(colonDelimiters <=1, OptimizerException, "Too many cleanup sequence delimiters");
324+
assertThrow(colonDelimiters <= 1, OptimizerException, "Too many cleanup sequence delimiters");
322325
break;
323326
default:
324327
{

solc/CommandLineParser.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const
273273

274274
if (delimiterPos != string::npos)
275275
settings.yulOptimiserCleanupSteps = fullSequence.substr(delimiterPos + 1);
276+
else
277+
solAssert(settings.yulOptimiserCleanupSteps == OptimiserSettings::DefaultYulOptimiserCleanupSteps);
276278
}
277279

278280
return settings;

test/cmdlineTests/yul_optimizer_steps_invalid_nested_delimiter/args

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_invalid_nested_delimiter/err

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_invalid_nested_delimiter/exit

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_invalid_nested_delimiter/input.sol

-7
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_multiple_delimiters/args

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_multiple_delimiters/err

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_multiple_delimiters/exit

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_multiple_delimiters/input.sol

-7
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_cleanup_sequence/args

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_cleanup_sequence/input.sol

-8
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_cleanup_sequence/output

-34
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_empty_sequences/args

-1
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_empty_sequences/input.sol

-8
This file was deleted.

test/cmdlineTests/yul_optimizer_steps_with_empty_sequences/output

-42
This file was deleted.

0 commit comments

Comments
 (0)