From 3c09b1960d61760123bb8ef581a984cd0f1fd41d Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Thu, 26 Oct 2023 00:27:28 -0300 Subject: [PATCH] Update optimizer docs to include codegen-based optimizer section --- docs/internals/optimizer.rst | 67 +++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index b3e144e94744..741b6bbb93ce 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -5,8 +5,9 @@ The Optimizer ************* -The Solidity compiler uses two different optimizer modules: The "old" optimizer -that operates at the opcode level and the "new" optimizer that operates on Yul IR code. +The Solidity compiler uses three different optimizer modules: The "old" optimizer +that operates at the opcode level and two "new" optimizers, one that operates on Yul IR code +and another that removes unnecessary overflow checks of code generation of ``for`` loops. The opcode-based optimizer applies a set of `simplification rules `_ to opcodes. It also combines equal code sets and removes unused code. @@ -20,6 +21,9 @@ the function calls. Similarly, if a function is side-effect free and its result is multiplied by zero, you can remove the function call completely. +The codegen-based optimizer is a single step that makes the compiler use unchecked +arithmetic when generating code of a ``for`` loop counter variable increment. + Currently, the parameter ``--optimize`` activates the opcode-based optimizer for the generated bytecode and the Yul optimizer for the Yul code generated internally, for example for ABI coder v2. One can use ``solc --ir-optimized --optimize`` to produce an @@ -27,10 +31,11 @@ optimized Yul IR for a Solidity source. Similarly, one can use ``solc --strict-a for a stand-alone Yul mode. .. note:: - The `peephole optimizer `_ is always - enabled by default and can only be turned off via the :ref:`Standard JSON `. + The `peephole optimizer `_ and + the codegen-based optimizer are always enabled by default and can only be turned off + via the :ref:`Standard JSON `. -You can find more details on both optimizer modules and their optimization steps below. +You can find more details on the optimizer modules and their optimization steps below. Benefits of Optimizing Solidity Code ==================================== @@ -1382,3 +1387,55 @@ into } The LiteralRematerialiser should be run before this step. + +Codegen-Based Optimizer Module +============================== + +Currently, the codegen-based optimizer module consists of only one step, +which makes the compiler automatically generate unchecked arithmetic code that +increments the counter variable of a `for` loop. The single step of this module, +which is explained next, avoids wasting gas unnecessarily, by identifying some +conditions that guarantee that the counter variable cannot overflow. This eliminates +the need to use a explicit unchecked arithmetic block inside the loop body to +increment the counter variable + +Unchecked Loop Increment +------------------------ + +Introduced in solidity ``0.8.22``, this optimizer step is concerned with identifying +the conditions under which the code of a ``for`` loop counter can be incremented +without overflow checks. +The optimization is always turned on by default and can only +be turned off by setting the ``simpleCounterForLoopUncheckedIncrement`` flag to +false inside ``settings.optimizer.details`` in Standard JSON input. +It is not possible to disable it using the command-line interface. +This optimization is **only** applied to ``for`` loops which use built-in operators ``<`` in the +condition and (postfix/prefix) ``++`` in the lopp expression with the general form: + +.. code-block:: solidity + + for (uint i = 0; i < x; ++i) { + // variable i is not modified in the loop body + } + +In many cases, the comparison is guaranteed to ensure that the counter variable +never overflows. The precise conditions are listed and explained as follows: + + - The loop condition is a comparison of the form ``i < x``, for a local counter variable ``i`` and an expression ``x``. + - The built-in operator ``<`` is necessarily used in the loop condition. User-defined operators are **not** eligible. + - The loop expression is a prefix or postfix increment of the counter variable, i.e, ``i++`` or ``++i``. + - The loop counter is a local declared variable of a built-in integer type. + - The loop counter is **not** modified neither in the body nor in the condition. + - The comparison is performed on the same type of the loop counter, meaning that the type of the right-hand-side expression is implicitly convertible to the type of the counter, such that the latter is not implicitly widened before comparing. + +To clarify the last condition, consider the next example: + +.. code-block:: solidity + + for (uint8 i = 0; i < uint16(1000); i++) { + // ... + } + +In this case, the counter ``i`` has its type implicitly converted from ``uint8`` +to ``uint16`` before the comparison and the condition is in fact never false, so +the overflow check for the increment cannot be removed.