Skip to content

perf: evmasm hasInstruction called unnecessarily #16292

@DaniPopes

Description

@DaniPopes

evmasm::AssemblyItem::operator== is pretty hot, especially in the peephole optimizer:

/// Shortcut that avoids constructing an AssemblyItem just to perform the comparison.
bool operator==(Instruction _instr) const
{
return hasInstruction() && instruction() == _instr;
}

This operator calls hasInstruction() twice, once in the actual operator, and the second time in the instruction() solAssert:

solAssert(hasInstruction());

This is enough to show up in profiles. The solAssert should either be a debug-only assert, or operator== should not repeat the check by using m_instruction directly. I would prefer the former since operator== is not the only hot callsite for hasInstruction().

This function (instruction() calling hasInstruction()) is BY FAR the most time consuming operation in the evmasm optimizer.

This should be a single line change for an estimated E2E 5-10% performance improvement in optimized compilations.


On solady:

~/github/solady main !1 ?3 ❯ hyperfine -w1 --prepare 'forge clean' 'SOLC=solcd forge b' 'SOLC=solcd2 forge b'        ✘ INT 18:34:21
Benchmark 1: SOLC=solcd forge b
  Time (mean ± σ):     18.934 s ±  0.425 s    [User: 17.609 s, System: 0.865 s]
  Range (min … max):   18.657 s … 19.703 s    10 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.

Benchmark 2: SOLC=solcd2 forge b
  Time (mean ± σ):     17.796 s ±  0.332 s    [User: 16.329 s, System: 0.834 s]
  Range (min … max):   17.639 s … 18.735 s    10 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.

Summary
  SOLC=solcd2 forge b ran
    1.06 ± 0.03 times faster than SOLC=solcd forge b

this is using a custom script as solc that uses the binary in the SOLC env var. this is the same as '--use X' in forge but i was using it for other profiling.

version 0.8.31-develop.2025.11.19+commit.08c4e0c6.mod.Darwin.appleclang (08c4e0c)

the diff for solcd and solcd2 is:

diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h
index dcb4bf3a7..59ebb7e15 100644
--- a/libevmasm/AssemblyItem.h
+++ b/libevmasm/AssemblyItem.h
@@ -215,7 +215,7 @@ public:
        /// @returns the instruction of this item (only valid if hasInstruction returns true)
        Instruction instruction() const
        {
-               solAssert(hasInstruction());
+               // solAssert(hasInstruction());
                return *m_instruction;
        }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions