{
let x := 42
let y := add(sload(42), calldataload(0))
....
let z := 42
....
f(42, add(sload(42), calldataload(0)))
}
---->
{
let x := 42
let y := add(sload(42), calldataload(0))
....
let z := x
...
f(x, y)
}
Arbitrarily complex expressions that we know to evaluate to a value currently in a yul variable can be replaced by a yul variable. This can happen through complex control flow (into branches, across loops, etc.) and across arbitrary distances.
Relevance
Very High. This is one of the main aspects of moving things around together with Rematerializing (see below). Especially when done in sequence, we loose a strict division between variable and value. For the optimizer the concepts fuse.
TODO: need to elaborate in more complex examples. There may appear to be simple solutions like only preserving the debugging info of the replaced expression, but in more complex examples it should become apparent that the distinction cannot be reasonably kept up across multiple optimizations.
Depends on #14969 and #15009.
(#15009 is just cherry-picked here and should be removed once merged)
See https://notes.ethereum.org/lznAP49lRj6zrLJdLpkqwg.
CommonSubExpressionEliminator
Effect
---->
Arbitrarily complex expressions that we know to evaluate to a value currently in a yul variable can be replaced by a yul variable. This can happen through complex control flow (into branches, across loops, etc.) and across arbitrary distances.
Relevance
Very High. This is one of the main aspects of moving things around together with Rematerializing (see below). Especially when done in sequence, we loose a strict division between variable and value. For the optimizer the concepts fuse. TODO: need to elaborate in more complex examples. There may appear to be simple solutions like only preserving the debugging info of the replaced expression, but in more complex examples it should become apparent that the distinction cannot be reasonably kept up across multiple optimizations.
Implementation
TBD.