Yul optimizer: Remove Yul constant optimizer#16738
Conversation
22ff1cb to
20189cd
Compare
|
Here is the diff from
|
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | +5.78% ❌ |
||
| colony | 0% |
||
| elementfi | +3.87% ❌ |
||
| ens | +5.65% ❌ |
||
| euler | |||
| gnosis | |||
| gp2 | +5.12% ❌ |
||
| pool-together | +5.57% ❌ |
||
| uniswap | +4% ❌ |
+3.57% ❌ |
+2.5% ❌ |
| yield_liquidator | +5.24% ❌ |
+4.99% ❌ |
-0.46% ✅ |
| zeppelin |
ir-optimize-evm+yul
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | +0.07% ❌ |
||
| colony | +0% |
||
| elementfi | +0.13% ❌ |
||
| ens | -0.81% ✅ |
-1.77% ✅ |
+0.02% ❌ |
| euler | +0.57% ❌ |
+0.66% ❌ |
+0.13% ❌ |
| gnosis | |||
| gp2 | -0.08% ✅ |
||
| pool-together | -0.25% ✅ |
||
| uniswap | -0.38% ✅ |
-0.42% ✅ |
-0.22% ✅ |
| yield_liquidator | -0.99% ✅ |
-0.99% ✅ |
+0.06% ❌ |
| zeppelin | -0.26% ✅ |
-0.07% ✅ |
-0.22% ✅ |
ir-optimize-evm-only
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | +0.06% ❌ |
||
| colony | 0% |
||
| elementfi | +0.11% ❌ |
||
| ens | +0.18% ❌ |
+0.07% ❌ |
+0% |
| euler | |||
| gnosis | |||
| gp2 | +0.12% ❌ |
||
| pool-together | +0.14% ❌ |
||
| uniswap | +0.04% ❌ |
+0.04% ❌ |
+0.02% ❌ |
| yield_liquidator | +0.07% ❌ |
+0.04% ❌ |
0% |
| zeppelin | +0.17% ❌ |
legacy-no-optimize
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | 0% |
||
| colony | 0% |
||
| elementfi | 0% |
||
| ens | 0% |
||
| euler | 0% |
+0% |
+0% |
| gnosis | 0% |
||
| gp2 | 0% |
||
| pool-together | 0% |
||
| uniswap | 0% |
-0% |
+0% |
| yield_liquidator | 0% |
-0% |
0% |
| zeppelin |
legacy-optimize-evm+yul
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | 0% |
||
| colony | +0% |
||
| elementfi | +0.01% ❌ |
||
| ens | +0.03% ❌ |
+0.04% ❌ |
-0% |
| euler | +0.04% ❌ |
+0.04% ❌ |
-0% |
| gnosis | +0.06% ❌ |
||
| gp2 | +0.11% ❌ |
||
| pool-together | +0.01% ❌ |
||
| uniswap | +0.02% ❌ |
+0.02% ❌ |
+0% |
| yield_liquidator | +0.05% ❌ |
+0.04% ❌ |
+0% |
| zeppelin | +0% |
+0.01% ❌ |
-0.03% ✅ |
legacy-optimize-evm-only
| project | bytecode_size | deployment_gas | method_gas |
|---|---|---|---|
| brink | 0% |
||
| colony | 0% |
||
| elementfi | 0% |
||
| ens | 0% |
+0% |
0% |
| euler | 0% |
-0% |
-0% |
| gnosis | 0% |
||
| gp2 | 0% |
||
| pool-together | 0% |
||
| uniswap | 0% |
+0% |
-0% |
| yield_liquidator | 0% |
0% |
0% |
| zeppelin |
!V = version mismatch
!B = no value in the "before" version
!A = no value in the "after" version
!T = one or both values were not numeric and could not be compared
-0 = very small negative value rounded to zero
+0 = very small positive value rounded to zero
|
The results on |
20189cd to
b73344d
Compare
|
Alternatively, maybe the code could be refactored to have a single implementation used in both places? That would avoid the regression and allay the concerns about implementation duplication. |
|
For the record, I've been discussing this with @blishko on the #solidty-dev channel, but I think this is a better place for such a discussion. Here's what was said so that it does not just disappear in the depths of ephemeral chats:
|
|
I haven't looked at the yul optimization steps in detail, but doesn't yul make inlining choices based on size? |
|
That's an interesting point. Technically, it does: solidity/libyul/optimiser/FullInliner.cpp Lines 201 to 204 in 2ca6163 The thing is though how the size is defined. It's based on our solidity/libyul/optimiser/Metrics.h Line 71 in 2ca6163 This probably makes sense, since ConstantOptimiser is a hard-coded step that only runs after the cleanup sequence, so while we're going through the sequence the literal is not yet in its final form. Any assumption the inliner might make about it would likely be wrong. The metric is rather meant to reflect some more abstract measure of size, in terms of the number of Yul statements. |
|
@cameel, thanks for pointing out your document. I will try to do a deep dive into the differences (though it will have to wait a few weeks). I agree that, for example, always analyzing both positive and negative form of the literal should be beneficial. |
This PR proposes to completely remove Yul constant optimizer.
Currently, there are two places in the compiler that attempt to optimize constants by replacing them by expressions that compute them. This is
ConstantOptimizerinlibyul/backends/evm, the other orConstantOptimizerinlibevmasm. Here "optimize" means optimizing for bytecode size. Constants can always be obtained byPUSH*instruction followed by the value, but the constant can be computed with a few instructions that together take less bytes.I believe that trying to solve the same problem in two different places can lead to unnecessary complexity.
As an example, a proposed optimization, such as #16729, would have to be implemented on both places.
Conceptually, I believe this optimization belongs to the evmasm optimizer.
Especially in the context of SSA-CFG, Yul should preserve the information about literals and let further stages down the codegen pipeline deal with this EVM-specific optimization.