@@ -322,6 +322,7 @@ Abbreviation Full name
322
322
``a `` :ref: `SSA-transform `
323
323
``t `` :ref: `structural-simplifier `
324
324
``p `` :ref: `unused-function-parameter-pruner `
325
+ ``S `` :ref: `unused-store-eliminator `
325
326
``u `` :ref: `unused-pruner `
326
327
``d `` :ref: `var-decl-initializer `
327
328
============ ===============================
@@ -958,7 +959,7 @@ DeadCodeEliminator
958
959
This optimization stage removes unreachable code.
959
960
960
961
Unreachable code is any code within a block which is preceded by a
961
- leave, return, invalid, break, continue, selfdestruct or revert .
962
+ leave, return, invalid, break, continue, selfdestruct, revert or by a call to a user-defined function that recurses infinitely .
962
963
963
964
Function definitions are retained as they might be called by earlier
964
965
code and thus are considered reachable.
@@ -1121,6 +1122,52 @@ The step LiteralRematerialiser is not required for correctness. It helps deal wi
1121
1122
``function f(x) -> y { revert(y, y} } `` where the literal ``y `` will be replaced by its value ``0 ``,
1122
1123
allowing us to rewrite the function.
1123
1124
1125
+ .. index :: ! unused store eliminator
1126
+ .. _unused-store-eliminator :
1127
+
1128
+ UnusedStoreEliminator
1129
+ ^^^^^^^^^^^^^^^^^^^^^
1130
+
1131
+ Optimizer component that removes redundant ``sstore `` and memory store statements.
1132
+ In case of an ``sstore ``, if all outgoing code paths revert (due to an explicit ``revert() ``, ``invalid() ``, or infinite recursion) or
1133
+ lead to another ``sstore `` for which the optimizer can tell that it will overwrite the first store, the statement will be removed.
1134
+ However, if there is a read operation between the initial ``sstore `` and the revert, or the overwriting ``sstore ``, the statement
1135
+ will not be removed.
1136
+ Such read operations include: external calls, user-defined functions with any storage access, and ``sload `` of a slot that cannot be
1137
+ proven to differ from the slot written by the initial ``sstore ``.
1138
+
1139
+ For example, the following code
1140
+
1141
+ .. code-block :: yul
1142
+
1143
+ {
1144
+ let c := calldataload(0)
1145
+ sstore(c, 1)
1146
+ if c {
1147
+ sstore(c, 2)
1148
+ }
1149
+ sstore(c, 3)
1150
+ }
1151
+
1152
+ will be transformed into the code below after the Unused Store Eliminator step is run
1153
+
1154
+ .. code-block :: yul
1155
+
1156
+ {
1157
+ let c := calldataload(0)
1158
+ if c { }
1159
+ sstore(c, 3)
1160
+ }
1161
+
1162
+ For memory store operations, things are generally simpler, at least in the outermost yul block as all such
1163
+ statements will be removed if they are never read from in any code path.
1164
+ At function analysis level, however, the approach is similar to ``sstore ``, as we do not know whether the memory location will
1165
+ be read once we leave the function's scope, so the statement will be removed only if all code code paths lead to a memory overwrite.
1166
+
1167
+ Best run in SSA form.
1168
+
1169
+ Prerequisites: Disambiguator, ForLoopInitRewriter.
1170
+
1124
1171
.. _equivalent-function-combiner :
1125
1172
1126
1173
EquivalentFunctionCombiner
0 commit comments