Comments (2)
I can confirm this. I see that in the optimized Yul code the loop is identical in both cases and the difference is only visible in assembly. This means that it must be the effect of the optimized Yul->EVM transform. We fall back to the legacy transform if the assembly blocks are not memory-safe.
Honestly, I'm not sure if this is something we'll be able to fix. I think it's likely to not be a result of a bug that can be simply "fixed", but rather a trade-off that might affect other cases. We're generally working on improving the transform, so this may also improve as a result of the upcoming changes and might not make sense to target specifically. Need @ekpyron's opinion here.
Details
The stack shuffling issue is specific to the two
staticcalls
to the SHA-256 precompile that follow. In particular, if you remove any of them, the problem is no longer observed and you get the expected behaviour of code withmemory-safe
assembly tags being slightly more performant than potentially memory unsafe assembly.
Interesting. I expected that this would be caused by stuff being optimized out without the calls, but no. When I comment out the staticcall
s the loop is still there, and still the same in both cases, just processed differently by the transform.
(Also on an unrelated note, I noticed that it is compiling
sub(shift, 6)
asadd(shift, 0xffff...ffa
which is 31 more code bytes and also seems like a minor bug...)
Maybe we should reconsider #6765 after all. I think it happens because Yul optimizer always converts sub()
to add()
and in this form this leaves the constant optimizer only the choice between add(shift, not(5))
(which is more space-efficient and chosen for lower runs
values) and add(shift, 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa)
(which is cheaper to execute). Converting it back to sub(shift, 6)
would be a much better alternative, since it's both cheaper and more space-efficient.
Workaround
I would not necessarily recommend it as a general solution, but as of 0.8.25 we still support the stackAllocation
option in Standard JSON, which lets you select the old Yul->EVM transform. Keep in mind though that we're going to deprecate it eventually.
Repro
CLI repro using Foundry. Assumes that the contract from the issue description is in a file called base64-safe.sol
.
export seed="grace crime cat remove spice bean concert lawsuit render horse collect vocal"
anvil --mnemonic "$seed"
export key=0x60b139825a56a987d58b20f0145e05dc45bed12df72cb92812b5ea988383c987
function benchmark_contract {
solc "$1".sol --via-ir --optimize --optimize-runs 100000 --bin |
sed -e '/^=======.*=======$/d' -e '/^Binary:$/d' -e '/^\s*$/d' > "$1".bin
local address
address=$(
cast send --json --private-key "$key" --create "$(cat "$1".bin)" |
jq --raw-output .contractAddress
)
gas=$(
cast send --json --private-key "$key" "$address" "bench()" |
jq --raw-output .gasUsed
)
echo "$((gas - 21000))"
}
benchmark_contract base64-safe
sed -e 's/("memory-safe")//g' base64-safe.sol > base64-unsafe.sol
benchmark_contract base64-unsafe
5104
4486
from solidity.
Thanks for the detailed response.
Another possible work around would be to split the code into separate functions, one with the loop and another with the static calls, and force the loop to not be optimized somehow (we can achieve this by having an additional external function that calls the loop function). I verified it with the above code and it had the desired effect.
Is there a better way to tell the Yul optimizer "please don't inline this function" without changing the ABI of the contract?
from solidity.
Related Issues (20)
- `Assembly exception for bytecode` occurs when compiling with via-ir
- Overflow operations are not detected when enabling via-ir compilation HOT 1
- SMTChecker: Z3 in CHC engine incorrectly determines assertion as safe, when it should report possible violation
- Unknown EVM memory space while function returns a memory array. HOT 1
- Public function is not visible outside of the contract. HOT 4
- Adjust documentation webpage layout to be compatible with RTD addons HOT 2
- smart contracts need to process AI related processing on chain and also on contract
- Signed int256 addition optimization HOT 1
- No Documentation Available for compiling from source on ARM machine HOT 1
- Poor optimization of `call` and `staticcall` with `--via-ir` HOT 3
- Stack too deep compiler error when no variable are pushed to the stack.
- `Assembly exception for bytecode` occurs when code contains immutable state variables
- Unclear documentation for bytes encoding HOT 2
- SMT logic error: sorts are incompatible HOT 2
- Refine and Stabilize EOF Support
- FundsFreeze.sol
- White error output is invisible on white terminals
- type().max min should work with user defined types that are mapped to scalar types
- User defined value type with operators and/or forward references or aliases for types in libraries
- for loop i=9;i>=0;i-- execution reverted: arithmetic underflow or overflow HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from solidity.