Skip to content

Skip unnecessary SLOAD for empty value-type array copy in IR#16575

Closed
tavian-dev wants to merge 2 commits into
argotorg:developfrom
tavian-dev:fix/skip-sload-empty-array-copy
Closed

Skip unnecessary SLOAD for empty value-type array copy in IR#16575
tavian-dev wants to merge 2 commits into
argotorg:developfrom
tavian-dev:fix/skip-sload-empty-array-copy

Conversation

@tavian-dev
Copy link
Copy Markdown
Contributor

Summary

Fixes #16307.

When copying a storage array of value types to another storage slot, the IR pipeline's copyValueArrayToStorageFunction unconditionally performs an sload on the source data area before entering the copy loop. For empty arrays (length 0), this SLOAD is wasted since the loop never executes.

This adds an early exit after resizeArray(dst, length) when length is zero, avoiding:

  • The unnecessary sload on the source data area
  • The keccak256 data slot computations for both source and destination
  • The fullSlots division and loop overhead

Generated Yul before:

<resizeArray>(dst, length)

let srcPtr := <srcDataLocation>(src)     // keccak256
let dstSlot := <dstDataLocation>(dst)    // keccak256
let fullSlots := div(length, <itemsPerSlot>)
let srcSlotValue := sload(srcPtr)        // <-- unnecessary when length=0

Generated Yul after:

<resizeArray>(dst, length)

if iszero(length) { leave }              // skip everything for empty arrays

let srcPtr := <srcDataLocation>(src)
let dstSlot := <dstDataLocation>(dst)
let fullSlots := div(length, <itemsPerSlot>)
let srcSlotValue := sload(srcPtr)

Test plan

  • Added semantic test array/copying/array_copy_empty_storage_push.sol exercising the exact pattern from the issue (array.push() = array.push())
  • All 232 array semantic tests pass
  • All 1637 semantic tests pass
  • Full build + style check pass locally

When isoltest updates test expectations for ASTJSON tests, it calls
printSource() to rewrite the .sol input file. The function was not
outputting the failAfter directive that was parsed and stored in
m_expectedFailAfter, causing the directive to be silently dropped.

Fixes argotorg#14093
When copying a storage array of value types to another storage location,
the generated Yul code unconditionally performs an SLOAD on the source
data area before entering the copy loop. For empty arrays (length 0),
this SLOAD is wasted since the loop body never executes.

Add an early exit after resizeArray when length is zero, avoiding the
unnecessary SLOAD as well as the keccak256 data slot computations.

Fixes argotorg#16307.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

Thank you for your contribution to the Solidity compiler! A team member will follow up shortly.

If you haven't read our contributing guidelines and our review checklist before, please do it now, this makes the reviewing process and accepting your contribution smoother.

If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the #solidity-dev channel on Matrix.

@nikola-matic
Copy link
Copy Markdown
Contributor

Closing this as the issuein question has not been triaged, and is thus not ready for development.

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.

Inefficient code generation for empty dynamic storage array assignment in IR pipeline

2 participants