Skip to content

Using memory loads for large constant creation#16708

Closed
DanielVF wants to merge 1 commit into
argotorg:developfrom
DanielVF:memorymasking-07
Closed

Using memory loads for large constant creation#16708
DanielVF wants to merge 1 commit into
argotorg:developfrom
DanielVF:memorymasking-07

Conversation

@DanielVF

@DanielVF DanielVF commented May 12, 2026

Copy link
Copy Markdown
Contributor

Description

This is draft PR for discussion. It has been benchmarked against live transactions, but tests are still lacking.

This PR makes an approximately 5% bytecode size reduction for contracts compiled with the normal defaults of optimizer + runs 200. Gas usage is also reduced on average.

Bitmasking for stack cleanup currently makes up a double digit portion of solidity code. The current methods used by solidity either use large amounts of bytecode for raw push bytes, or use a 9 bytes, 18 gas sequence for in place computing for computing a large constant. This PR the cost of most large constants, not just for masks, reduce to only 4 bytes, 9 gas, with a PUSH1 MLOAD AND.

By adding a 32 bytes of 0xFF after the zero constant memory slot, we can create any byte aligned, right aligned constant by just selecting a memory region that contains the right amounts of 0x00's and 0xFF's.

000000000000FFFFFFFFFFFF
        |----------|
     |----------|

Tradeoffs and Decisions

The goal of this PR is to have an only positive effect on code bytecode size and gas usage.

  • This optimization is only enabled when the optimizer is on, and the optimizer runs setting is such that it will be used.
  • The worse case bytecode size penalty, when the code does not benefit from the optimization is five to six bytes depending on fork compiled for.
  • The worst case gas overhead is 15-18 gas, again depending on fork.
  • However, in return, the overall bytecode savings are substantial, > 5% on tested real world contracts.
  • This actually makes a few hundred gas savings on common defi contract transactions.

I've chosen not to enable this optimization for compiling constructor bytecode. It's a single line change to use it, but contracts without constructor code would be penalized, and that makes up a lot of contract deploys.

This is also turned off when compiling raw yul outside of solidity, since the memory may not have been setup.

This is currently assuming that well behave user assembly code will NOT write into memory that the solidity compiler has marked for itself by advancing the free memory pointer past. This is the core correctness assumption of this code.

Remaining Work

  • Docs
  • More tests
  • More benchmarks
  • Full understanding around memory safety

Checklist

  • I have read the contributing guidelines and the review checklist
  • I have personally reviewed, understood every change in this PR
  • I have tested every change in this PR (not to a state I would ship)

AI Disclosure

  • No AI tools were used
  • AI tools were used (details below)

Codex 5.5

@DanielVF

Copy link
Copy Markdown
Contributor Author

@cameel This PR is the new version of #16692.

@DanielVF

Copy link
Copy Markdown
Contributor Author

Closing this pull request, in favor of #16729.

While this one provides a bit more speed up and size reduction, it does change the "contract" about what users are allowed to do with memory from assembly, which would be a breaking change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant