Title: EIP-3855: PUSH0 instruction - EIPs core - Fellowship of Ethereum Magicians Description: This is the discussion topic for Keywords: No keywords Text content: EIP-3855: PUSH0 instruction - EIPs core - Fellowship of Ethereum Magicians Loading Fellowship of Ethereum Magicians EIP-3855: PUSH0 instruction EIPs EIPs core shanghai-candidate, evm, opcodes axic September 6, 2021, 9:09pm 1 This is the discussion topic for Ethereum Improvement Proposals EIP-3855: PUSH0 instruction Introduce a new instruction which pushes the constant value 0 onto the stack 6 Likes Arachnid September 6, 2021, 10:53pm 2 Thank you for putting this forward! I was thinking about the need for a push0 instruction just the other day. Based on your stats, the impact of it is even larger than I expected! Out of curiosity, did you collect stats on any other small numbers, such as 1, 2, and 32? 2 Likes axic September 7, 2021, 12:25am 3 Arachnid: Out of curiosity, did you collect stats on any other small numbers, such as 1, 2, and 32? We haven’t, but we could do that. Would take a couple of days though. Instead of a special “PUSH 1”, I think something like INC/DEC would be a more interesting instruction, as that has multiple uses, especially around loops and rounding. I think 2 and 32 may be more common, though Solidity does rounding using both 31 and 32, which can also be optimised to a combination of shits. 1 Like axic September 7, 2021, 1:35pm 4 In the EIP we reason for this opcode: 0x5f means it is in a “contiguous” space with the rest of the PUSH implementations and potentially could share the implementation. If this argument is not strong enough, then 0x5c seems like a good alternative choice. Arachnid September 7, 2021, 8:16pm 5 axic: Instead of a special “PUSH 1”, I think something like INC/DEC would be a more interesting instruction So we can do PUSH0 INC instead of PUSH1 1? axic: I think 2 and 32 may be more common, though Solidity does rounding using both 31 and 32, which can also be optimised to a combination of shits. A combination of whatnow? axic September 7, 2021, 10:18pm 6 Arachnid: axic: Instead of a special “PUSH 1”, I think something like INC/DEC would be a more interesting instruction So we can do PUSH0 INC instead of PUSH1 1? Yes, isn’t that so much nicer?! In fairness my hunch is that the constant 1 is mostly used for loops, in the form of PUSH1 1 ADD, so instead of that INC seems better. That is if we are willing to go into the direction of CISC. (PUSH0 is still inspired by the constant 0 register in RISC machines.) Arachnid: axic: I think 2 and 32 may be more common, though Solidity does rounding using both 31 and 32, which can also be optimised to a combination of shits. A combination of whatnow? EVM hardcore mode Discounting the typo, I meant “combination of shifts and other bitwise instructions”. ricmoo September 8, 2021, 4:34pm 7 Love the idea, but maybe we should use a different mnemonic, like IPUSH0 (for immediate) so that if we add others, we have room to grow? 1 Like hugo-dc September 8, 2021, 9:30pm 8 I have posted the results here: https://gist.github.com/hugo-dc/1ca4682d60098282d7e499bdd0b01fca Includes analysis of: Occurrences of PUSHn opcodes pushing the values 1, 2, 8, 31, and 32. Occurrences of pushing the specific values 1, 2, 8, 31, and 32, by any of the PUSH opcodes. A comparison between PUSH1 for the specific values 1, 2, 8, 31, and 32 vs any other values. 1 Like axic September 13, 2021, 3:49pm 9 My hunch is that the majority of cases using the constant 1 are for-loops. And likely a large number of the uses of the constant 32 is for such loops too, which operate on word sizes. (Though a significant number of occurrences should be for memory operations.) And for these use cases I think this is a better direction to go: axic: In fairness my hunch is that the constant 1 is mostly used for loops, in the form of PUSH1 1 ADD, so instead of that INC seems better. That is if we are willing to go into the direction of CISC. (PUSH0 is still inspired by the constant 0 register in RISC machines.) dankrad September 17, 2021, 3:17pm 10 My intuition is that saving a 1 byte is a very marginal improvement and needs a pretty strong justification for actually reserving an opcode for it (which are after all limited)? axic September 17, 2021, 3:56pm 11 dankrad: My intuition is that saving a 1 byte is a very marginal improvement It is not only about saving 1 byte. The main motivation is runtime cost and avoiding that contracts use weird optimisations because they have no better option, and that optimisation limiting us in introducing other features. Please read the motivation in the EIP and if it is fails to present convincing points, then we need to improve it. dankrad: and needs a pretty strong justification for actually reserving an opcode for it (which are after all limited)? They are not limited, one can have extension bytes and two-byte opcodes, but even if someone mentally limits it to one byte, then we still have over 100 of them left. Technically speaking all the PUSHn opcodes are not one byte opcodes 1 Like gcolvin September 22, 2021, 5:38pm 12 These stats are taken from a histogram of several thousand blocks at the end of last year’s chain. One-byte pushes account for almost half of the pushes and over 10% of the instructions. So from @hugo-dc’s numbers about 4% of instructions are PUSH1 0, and about 6% are a push of 1, 2, or 32. OP Count % All PUSH 78,137,163 22.94% PUSH1 37,886,773 11.12% ekpyron February 3, 2022, 7:38pm 13 FYI - this would save us some headache for solidity code generation - for once, in some situations we have to create stack balance between branches (we sometimes choose an awkward codesize for doing so…), and apart from that we constantly have to seek balance between keeping zeroes on stack or repushing them, both of which would be made easier, simpler and cleaner using a PUSH0. I’ve even had a draft for an optimizer step once that analysed which code paths are only executed prior to any external call and replaced zeroes with returndatasize in those paths - and considered something similar with callvalue for non-payable functions after their callvalue check - all of which is extremely awkward and it’d be nice to be able to drop crazy ideas like that with this EIP. Not that it’s crucial for us, but definitely a nice-to-have. 1 Like wjmelements February 9, 2022, 6:59pm 14 All PUSH, DUP, and SWAP operations should cost base gas. It’s weird that they don’t. axic February 9, 2022, 10:40pm 15 We have some benchmarks about them, and it is not as clear cut. We do plan to share these with some recommendations, but I do not think this strictly is related to this EIP. poojaranjan April 8, 2022, 2:22pm 16 PEEPanEIP-3855: PUSH0 instruction with @axic @chfast @hugo-dc 2 Likes wjmelements April 13, 2022, 8:30pm 17 axic: We have some benchmarks about them, and it is not as clear cut. We do plan to share these with some recommendations, but I do not think this strictly is related to this EIP. It’s related to the motivation, because people are only using those opcodes instead of PUSH0 because they are cheaper. SKYBITDev3 September 7, 2023, 9:17am 18 PUSH0 has been enabled by default in Solidity since 0.8.20, but most blockchains still haven’t implemented it, causling “invalid opcode” error if developers use the latest compiler. So we’re stuck with using an older version. The best we can do for the moment to work with the latest Solidity compiler is to set evmVersion to the previous version: solidity: { compilers: [ { version: `0.8.21`, settings: { optimizer: { enabled: true, runs: 15000 }, evmVersion: `paris` } }, ], }, Polygon announced just days ago that they’ve just implemented PUSH0 on their zkEVM blockchain. I’ve tested the testnet and it works. zkEVM mainnet will work in 4 days. We need the many other blockchains to do so too. SKYBITDev3 September 18, 2023, 7:59am 19 Hardhat v2.17.3 was released last week and reverted the default evmVersion back to paris. They should have made such a change in a better way. I created an issue about it: Automatic downgrade of default EVM version may not be welcome · Issue #4391 · NomicFoundation/hardhat · GitHub I think it’s now best just to explicity set evmVersion in hardhat.config.js: evmVersion: 'shanghai' if it works on the blockchains you currently use evmVersion: 'paris' if you get the invalid opcode error radek December 15, 2023, 1:17pm 20 Crafting the byte-exact CREATE3 factory I wonder whether there is any adoption dashboard of PUSH0 among chains? next page → Home Categories Guidelines Terms of Service Privacy Policy Powered by Discourse, best viewed with JavaScript enabled