Check out the Issue Explorer
Looking to fund some work? You can submit a new Funded Issue here.
The `RuleList.h` contains a list of simplification rules that can be applied to sequences (or rather expressions) of opcodes. Examples are simple arithmetics on constants or other simplifications that can be applied regardless of the context:
- `push1 7 push1 8 add` is reduced to `push1 15`
- `dup1 dup1 xor` which is reduced to `push1 0`
These rules are currently used in two places: The first one is the new optimizer that will be used on Solidity inline assembly, and the second one is the so-called "common subexpression eliminator" that uses these rules both to perform equality checks during symbolic execution and to actually perform the simplifications.
Since the common subexpression eliminator is a rather complex module and sometimes fails to run on certain code snippets, it makes sense to also run the simplification rules in the old optimizer just on sequences of opcodes prior to running the full subexpression eliminator.
Since the rule list can be proven correct, it might also make sense to run this module even if the optimizer is turned off (just like the current peephole optimizer).
This optimizer stage should be similar to the peephole optimizer: It takes a vector of assembly items and outputs a vector of assembly items.
There are two files called `SimplificationRules.h/cpp`, one for the yul optimizer and the other for the common subexpression eliminator. A third one should probably be created for this new module.
The concept of "match groups" should probably be ignored for the first iteration of solving this issue. They have two purposes: First, they are used to check that two "items" are identical (e.g. for the rule `xor(x, x) -> 0`) and secondly, they are used in the execution of the replacement pattern (e.g. for the rule `or(x, x) -> x`). This module should only do local replacements in the stream of opcodes. This means the xor-pattern above could result in `dup1 xor` -> `pop push1 0`, but (at least its initial version) should not perform replacements if it can be inferred that the two top-most stack elements are identical, but you would need non-local information to do that. Also note that the replacement above specifically uses `pop` instead of omitting the preceding opcode, because that opcode might have side-effects. There are other optimizer stages (even inside the peephole optimizer) that will remove the opcode preceding a pop if it does not have side-effects.