perf: evmasm hasInstruction called unnecessarily
- Dominant language
- C++
- Stars
- 25.7k
- Forks
- 6.2k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 29
Description
evmasm::AssemblyItem::operator== is pretty hot, especially in the peephole optimizer:
https://github.com/argotorg/solidity/blob/08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532/libevmasm/AssemblyItem.h#L248-L252
This operator calls hasInstruction() twice, once in the actual operator, and the second time in the instruction() solAssert: https://github.com/argotorg/solidity/blob/08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532/libevmasm/AssemblyItem.h#L218
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 (08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532)
the diff for solcd and solcd2 is:
```diff
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;
}
```
Contributor guide
Research direction
Start in libevmasm/AssemblyItem.h at AssemblyItem::instruction() and operator==, then review the linked lines and existing optimizer checks. Use the solady hyperfine comparison described in the issue to verify the change; done means the redundant hasInstruction() cost is removed without changing instruction handling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, performance
- Issue type
- Refactor
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100