Skip to content

perf(compiler): consume value-range tags in EVM bool/compare/bitwise lowering#534

Merged
zoowii merged 7 commits into
DTVMStack:mainfrom
abmcar:perf/evm-range-lowering-gaps
Jun 26, 2026
Merged

perf(compiler): consume value-range tags in EVM bool/compare/bitwise lowering#534
zoowii merged 7 commits into
DTVMStack:mainfrom
abmcar:perf/evm-range-lowering-gaps

Conversation

@abmcar

@abmcar abmcar commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Consume existing ValueRange tags in four EVM lowering paths so operands already proven to fit in u64 skip full 4-limb sequences. Overall fast-path hit rate rises 78.72% -> 80.02% on the EEST Cancun suite, with no measured performance regression and 21/21 differential fixtures passing.

What

The multipass JIT range analyzer already proves many operands fit in u64, but several lowering paths ignore that proof and emit full 4-limb sequences. This PR makes four lowerings consume the existing ValueRange tags:

  1. ISZERO: deferred zero-test operands now carry the base value's range and tag their 0/1 result as u64. Materialization folds only the limbs the range allows (u64 base -> single-limb test instead of a 4-limb OR-fold).
  2. JUMPI: a deferred zero-test condition is fused into the branch — no materialize-then-refold round trip — and non-deferred conditions fold only range-live limbs. The common LT; ISZERO; JUMPI loop-exit shape previously paid a full compare, a 4-limb OR-fold + cmp + select materialization, and a second 4-limb OR-fold + cmp + select at the branch.
  3. OR/XOR: new non-constant narrow paths. Both operands proven u64 -> a single i64 op with zeroed upper limbs (result tagged u64); exactly one side u64 -> low-limb op with the wide side's upper limbs passed through (identity), mirroring the existing const-u64 path.
  4. SLT/SGT vs a u64 constant: new fast paths (handleCompareSltRhsU64 / handleCompareSgtRhsU64). A u64 constant has zero upper limbs, so it is a non-negative signed-256 value; the compare reduces to sign-bit test + upper-limb OR + an unsigned limb0 compare, with the same three range tiers as the unsigned helpers. Both constant positions are dispatched (c <s x ⟺ x >s c).

Why

Real-mainnet-load profiling showed these ops taking the full path while their operands were already statically proven narrow: 58.5% of ISZERO full-path executions had a proven-u64 operand, 51.8% of OR full-path executions had at least one proven-u64 side, and 22.4% of SLT full-path executions compared against a u64 constant. These are lowering-side gaps — no new analysis precision is required to close them.

Soundness

  • All new paths only narrow the read width where a ValueRange tag already proves upper limbs are semantically zero; no new tag sources are introduced (change 5's tag is justified by the function's structural zero-fill).
  • SLT/SGT: operands with limb0 in [2^63, 2^64-1] are positive 256-bit values; the new paths use unsigned predicates on limb0 and decide negative inputs from limb3's sign bit. The truth tables are verified across the boundary set (2^63, 2^64, 2^128, 2^192, 2^255, -1, equal values, c=0, c>=2^63).
  • Builder result ranges remain equal to or wider than the analyzer's transfer rules for every touched op (no builder-narrower-than-truth state).
  • JUMPI now depends on the range-contract invariant (an over-narrow upstream tag would mis-branch rather than merely run slower); this is documented at the fold site.

Diff scope

This diff includes the base-range plumbing (DeferredBaseRange) and the 1/2/4-limb narrow fold at materialization and JUMPI fusion. Two tags that previously sat here are excluded because they landed upstream independently: the context-size producer tag (now #532) and the U64 tag on the deferred zero-test result (now #524).

Verification

  • 21 new differential fixtures (tests/evm_asm/, committed) cover each new path's narrow and full sides with boundary values including 2^64, 2^128, 2^192, -1, high-sparse, and the limb0-MSB unsigned-predicate hard gate. A new EVMRangeNarrowingDifferentialTest suite asserts interpreter and multipass outputs match byte-for-byte and that multipass actually JIT-compiled: 21/21 pass.
  • multipass evmone-unittests: 223/223; multipass evmone-statetest -k fork_Cancun: 2723/2723; ctest: 11/11; golden .easm suite: 178/178 (no regressions); tools/format.sh check clean; no new build warnings.
  • Re-run on the rebased branch: differential 21/21, multipass evmone-unittests 223/223, statetest fork_Cancun 2723/2723.

Measurements

Fast-path hit rate, paired site-weighted measurement on the EEST Cancun suite (28,109 shared compiled sites, measured with an instrumentation-only tap branch not included in this PR). The EEST measurement predates the #522/#524/#530/#532 merges; the ADD row's 17 sites are attributable to the context-size tag landed as #532. Transition column reads as " sites: -> ".

op base this PR delta transitions
ISZERO 23.2% 85.9% +62.7pp 316 sites: full 4-limb -> single-limb u64
SGT 80.6% 95.0% +14.4pp 20 sites: full 4-limb -> u64-constant compare
SLT 61.5% 66.7% +5.2pp 9 sites: full 4-limb -> u64-constant compare
ADD 75.1% 75.6% +0.5pp 17 sites: full 4-limb -> u128 narrow
overall 78.72% 80.02% +1.29pp +364 sites, zero reverse transitions

Performance (evmone-bench, 27-bench sweep, multipass, vs upstream/main baseline): median delta -0.23%, within run-to-run variance (about ±2%). First-pass outliers re-measured with 15 repetitions all resolved to noise; the largest and most stable benchmark (snailtracer, cv 1.5%) improved consistently across two independent runs (-1.1% / -1.3%). No regressions.

Known limitation

With ZEN_ENABLE_EVM_STACK_SSA_LIFT=ON (default OFF, CI OFF), getOperandIdentityKey() in the lifted-stack path does not handle deferred operands; a live-out deferred zero-test can hit an assertion there. This exposure predates this PR (the lifter is untouched and deferred operand lifetimes are unchanged) and is noted in the change document for the stack-lift follow-up.

Change document: docs/changes/2026-06-10-evm-range-lowering-gaps/README.md.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 9, 2026 19:00
@abmcar abmcar force-pushed the perf/evm-range-lowering-gaps branch from d32f6dc to 4e9a276 Compare June 9, 2026 19:02
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

⚡ Performance Regression Check Results

✅ Performance Check Passed (interpreter)

Performance Benchmark Results (threshold: 25%)

Benchmark Baseline (us) Current (us) Change Status
total/main/blake2b_huff/8415nulls 3.73 3.76 +0.7% PASS
total/main/blake2b_huff/empty 0.06 0.06 +4.4% PASS
total/main/blake2b_shifts/8415nulls 20.91 20.88 -0.1% PASS
total/main/sha1_divs/5311 11.77 11.57 -1.7% PASS
total/main/sha1_divs/empty 0.15 0.14 -4.3% PASS
total/main/sha1_shifts/5311 9.02 8.89 -1.5% PASS
total/main/sha1_shifts/empty 0.08 0.08 -0.3% PASS
total/main/snailtracer/benchmark 110.70 109.54 -1.0% PASS
total/main/structarray_alloc/nfts_rank 1.40 1.40 -0.0% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.1% PASS
total/main/swap_math/received 0.01 0.01 -1.4% PASS
total/main/swap_math/spent 0.01 0.01 +0.3% PASS
total/main/weierstrudel/1 0.39 0.39 +1.0% PASS
total/main/weierstrudel/15 4.26 4.29 +0.6% PASS
total/micro/JUMPDEST_n0/empty 2.86 2.86 +0.0% PASS
total/micro/jump_around/empty 0.11 0.11 -3.0% PASS
total/micro/loop_with_many_jumpdests/empty 64.82 69.71 +7.5% PASS
total/micro/memory_grow_mload/by1 0.23 0.22 -2.3% PASS
total/micro/memory_grow_mload/by16 0.24 0.25 +3.7% PASS
total/micro/memory_grow_mload/by32 0.14 0.15 +2.1% PASS
total/micro/memory_grow_mload/nogrow 0.12 0.13 +6.2% PASS
total/micro/memory_grow_mstore/by1 0.24 0.24 -0.9% PASS
total/micro/memory_grow_mstore/by16 0.14 0.14 +2.9% PASS
total/micro/memory_grow_mstore/by32 0.28 0.28 +0.5% PASS
total/micro/memory_grow_mstore/nogrow 0.24 0.23 -2.5% PASS
total/micro/signextend/one 0.28 0.28 -1.0% PASS
total/micro/signextend/zero 0.48 0.48 -0.6% PASS
total/synth/ADD/b0 3.23 3.20 -0.7% PASS
total/synth/ADD/b1 5.96 6.04 +1.4% PASS
total/synth/ADDRESS/a0 6.68 6.56 -1.8% PASS
total/synth/ADDRESS/a1 5.34 5.15 -3.6% PASS
total/synth/AND/b0 2.87 2.95 +2.6% PASS
total/synth/AND/b1 5.18 5.36 +3.5% PASS
total/synth/BYTE/b0 6.06 6.15 +1.5% PASS
total/synth/BYTE/b1 8.44 8.35 -1.0% PASS
total/synth/CALLDATASIZE/a0 5.60 5.80 +3.6% PASS
total/synth/CALLDATASIZE/a1 3.68 3.41 -7.2% PASS
total/synth/CALLER/a0 6.67 6.83 +2.5% PASS
total/synth/CALLER/a1 6.85 6.82 -0.5% PASS
total/synth/CALLVALUE/a0 3.60 3.40 -5.5% PASS
total/synth/CALLVALUE/a1 6.22 6.28 +0.9% PASS
total/synth/CODESIZE/a0 6.96 6.70 -3.7% PASS
total/synth/CODESIZE/a1 6.58 6.40 -2.8% PASS
total/synth/DUP1/d0 2.00 1.96 -1.9% PASS
total/synth/DUP1/d1 2.10 2.06 -1.8% PASS
total/synth/DUP10/d0 1.98 1.97 -0.5% PASS
total/synth/DUP10/d1 2.18 2.34 +7.1% PASS
total/synth/DUP11/d0 1.11 1.31 +18.7% PASS
total/synth/DUP11/d1 2.32 2.08 -10.6% PASS
total/synth/DUP12/d0 2.01 2.02 +0.4% PASS
total/synth/DUP12/d1 1.65 1.47 -10.7% PASS
total/synth/DUP13/d0 1.98 2.02 +2.4% PASS
total/synth/DUP13/d1 2.12 2.27 +7.2% PASS
total/synth/DUP14/d0 1.11 1.13 +1.7% PASS
total/synth/DUP14/d1 2.14 2.08 -2.9% PASS
total/synth/DUP15/d0 1.99 2.07 +3.8% PASS
total/synth/DUP15/d1 1.65 1.65 +0.1% PASS
total/synth/DUP16/d0 2.03 1.98 -2.3% PASS
total/synth/DUP16/d1 2.16 2.09 -2.9% PASS
total/synth/DUP2/d0 1.10 1.31 +18.9% PASS
total/synth/DUP2/d1 2.17 2.29 +5.7% PASS
total/synth/DUP3/d0 1.96 1.96 +0.1% PASS
total/synth/DUP3/d1 1.65 1.65 +0.4% PASS
total/synth/DUP4/d0 2.05 2.00 -2.6% PASS
total/synth/DUP4/d1 2.15 2.16 +0.5% PASS
total/synth/DUP5/d0 1.10 1.11 +0.4% PASS
total/synth/DUP5/d1 2.17 2.10 -3.3% PASS
total/synth/DUP6/d0 2.00 1.96 -2.0% PASS
total/synth/DUP6/d1 1.65 1.65 -0.0% PASS
total/synth/DUP7/d0 1.98 2.01 +1.9% PASS
total/synth/DUP7/d1 2.06 2.12 +2.9% PASS
total/synth/DUP8/d0 1.23 1.31 +6.7% PASS
total/synth/DUP8/d1 2.18 2.05 -6.0% PASS
total/synth/DUP9/d0 2.01 1.98 -1.1% PASS
total/synth/DUP9/d1 1.65 1.65 -0.1% PASS
total/synth/EQ/b0 6.19 6.36 +2.8% PASS
total/synth/EQ/b1 6.33 6.34 +0.2% PASS
total/synth/GAS/a0 3.94 3.95 +0.1% PASS
total/synth/GAS/a1 7.51 7.60 +1.1% PASS
total/synth/GT/b0 6.35 6.36 +0.1% PASS
total/synth/GT/b1 6.52 6.55 +0.5% PASS
total/synth/ISZERO/u0 10.18 10.09 -0.9% PASS
total/synth/JUMPDEST/n0 2.86 2.86 -0.1% PASS
total/synth/LT/b0 6.35 6.19 -2.6% PASS
total/synth/LT/b1 5.41 5.41 +0.1% PASS
total/synth/MSIZE/a0 5.97 6.28 +5.2% PASS
total/synth/MSIZE/a1 6.15 6.19 +0.6% PASS
total/synth/MUL/b0 8.02 7.86 -1.9% PASS
total/synth/MUL/b1 5.92 5.94 +0.3% PASS
total/synth/NOT/u0 7.80 7.91 +1.5% PASS
total/synth/OR/b0 5.25 5.13 -2.4% PASS
total/synth/OR/b1 3.39 3.49 +2.8% PASS
total/synth/PC/a0 5.66 5.76 +1.7% PASS
total/synth/PC/a1 3.62 3.46 -4.4% PASS
total/synth/PUSH1/p0 2.29 2.39 +4.5% PASS
total/synth/PUSH1/p1 1.74 1.74 +0.2% PASS
total/synth/PUSH10/p0 2.24 2.28 +2.1% PASS
total/synth/PUSH10/p1 1.76 1.58 -10.6% PASS
total/synth/PUSH11/p0 2.30 2.29 -0.3% PASS
total/synth/PUSH11/p1 2.39 2.43 +1.8% PASS
total/synth/PUSH12/p0 1.33 1.31 -1.5% PASS
total/synth/PUSH12/p1 2.50 2.39 -4.4% PASS
total/synth/PUSH13/p0 2.27 2.29 +0.7% PASS
total/synth/PUSH13/p1 1.74 1.58 -8.9% PASS
total/synth/PUSH14/p0 2.93 2.66 -9.1% PASS
total/synth/PUSH14/p1 2.49 2.36 -5.1% PASS
total/synth/PUSH15/p0 1.32 1.31 -0.9% PASS
total/synth/PUSH15/p1 2.59 2.77 +6.6% PASS
total/synth/PUSH16/p0 2.14 2.32 +8.5% PASS
total/synth/PUSH16/p1 1.78 1.54 -13.4% PASS
total/synth/PUSH17/p0 2.32 2.28 -1.7% PASS
total/synth/PUSH17/p1 2.32 2.43 +4.9% PASS
total/synth/PUSH18/p0 1.32 1.29 -2.1% PASS
total/synth/PUSH18/p1 2.40 2.54 +5.9% PASS
total/synth/PUSH19/p0 2.42 2.26 -6.7% PASS
total/synth/PUSH19/p1 1.77 1.58 -10.8% PASS
total/synth/PUSH2/p0 2.33 2.32 -0.5% PASS
total/synth/PUSH2/p1 2.40 2.35 -1.8% PASS
total/synth/PUSH20/p0 2.35 2.29 -2.5% PASS
total/synth/PUSH20/p1 2.41 2.44 +1.1% PASS
total/synth/PUSH21/p0 1.32 1.30 -1.0% PASS
total/synth/PUSH21/p1 2.35 2.46 +4.4% PASS
total/synth/PUSH22/p0 2.27 2.30 +1.3% PASS
total/synth/PUSH22/p1 1.77 1.67 -6.0% PASS
total/synth/PUSH23/p0 2.29 2.17 -5.2% PASS
total/synth/PUSH23/p1 2.37 2.42 +1.9% PASS
total/synth/PUSH24/p0 1.33 1.32 -0.8% PASS
total/synth/PUSH24/p1 2.41 2.44 +0.9% PASS
total/synth/PUSH25/p0 2.31 2.21 -4.2% PASS
total/synth/PUSH25/p1 1.76 1.56 -11.4% PASS
total/synth/PUSH26/p0 2.34 2.36 +1.1% PASS
total/synth/PUSH26/p1 2.49 2.41 -3.5% PASS
total/synth/PUSH27/p0 1.32 1.32 -0.4% PASS
total/synth/PUSH27/p1 2.43 2.57 +6.1% PASS
total/synth/PUSH28/p0 2.35 2.47 +5.3% PASS
total/synth/PUSH28/p1 1.79 1.60 -10.8% PASS
total/synth/PUSH29/p0 2.22 2.35 +5.9% PASS
total/synth/PUSH29/p1 2.36 2.36 +0.0% PASS
total/synth/PUSH3/p0 1.32 1.31 -0.9% PASS
total/synth/PUSH3/p1 2.41 2.31 -4.0% PASS
total/synth/PUSH30/p0 1.56 1.46 -6.2% PASS
total/synth/PUSH30/p1 2.40 2.53 +5.3% PASS
total/synth/PUSH31/p0 2.28 2.25 -1.4% PASS
total/synth/PUSH31/p1 1.86 1.84 -1.1% PASS
total/synth/PUSH32/p0 2.51 2.38 -5.2% PASS
total/synth/PUSH32/p1 2.39 2.24 -6.4% PASS
total/synth/PUSH4/p0 2.23 2.22 -0.5% PASS
total/synth/PUSH4/p1 1.54 1.75 +13.5% PASS
total/synth/PUSH5/p0 2.34 2.20 -5.8% PASS
total/synth/PUSH5/p1 2.54 2.36 -7.0% PASS
total/synth/PUSH6/p0 1.32 1.31 -0.6% PASS
total/synth/PUSH6/p1 2.44 2.31 -5.3% PASS
total/synth/PUSH7/p0 2.25 2.33 +3.5% PASS
total/synth/PUSH7/p1 1.56 1.64 +4.8% PASS
total/synth/PUSH8/p0 2.34 2.37 +1.3% PASS
total/synth/PUSH8/p1 2.49 2.39 -4.1% PASS
total/synth/PUSH9/p0 1.32 1.30 -1.4% PASS
total/synth/PUSH9/p1 2.55 2.39 -6.3% PASS
total/synth/RETURNDATASIZE/a0 3.80 3.95 +3.7% PASS
total/synth/RETURNDATASIZE/a1 6.75 6.55 -2.9% PASS
total/synth/SAR/b0 3.94 3.93 -0.0% PASS
total/synth/SAR/b1 7.56 7.63 +0.9% PASS
total/synth/SGT/b0 5.81 5.75 -1.1% PASS
total/synth/SGT/b1 4.13 4.13 -0.2% PASS
total/synth/SHL/b0 7.09 6.98 -1.5% PASS
total/synth/SHL/b1 3.65 3.72 +2.1% PASS
total/synth/SHR/b0 7.29 7.34 +0.7% PASS
total/synth/SHR/b1 6.13 6.51 +6.2% PASS
total/synth/SIGNEXTEND/b0 3.36 3.36 -0.0% PASS
total/synth/SIGNEXTEND/b1 6.56 6.57 +0.2% PASS
total/synth/SLT/b0 4.30 4.30 -0.0% PASS
total/synth/SLT/b1 5.75 5.66 -1.4% PASS
total/synth/SUB/b0 5.88 5.57 -5.3% PASS
total/synth/SUB/b1 5.83 5.75 -1.4% PASS
total/synth/SWAP1/s0 3.52 3.47 -1.6% PASS
total/synth/SWAP10/s0 3.53 3.48 -1.3% PASS
total/synth/SWAP11/s0 3.45 3.52 +2.0% PASS
total/synth/SWAP12/s0 3.51 3.40 -2.9% PASS
total/synth/SWAP13/s0 3.54 3.49 -1.5% PASS
total/synth/SWAP14/s0 3.49 3.48 -0.4% PASS
total/synth/SWAP15/s0 3.48 3.47 -0.1% PASS
total/synth/SWAP16/s0 3.56 3.41 -4.1% PASS
total/synth/SWAP2/s0 3.41 3.42 +0.3% PASS
total/synth/SWAP3/s0 3.51 3.47 -1.1% PASS
total/synth/SWAP4/s0 3.53 3.48 -1.5% PASS
total/synth/SWAP5/s0 3.52 3.48 -1.1% PASS
total/synth/SWAP6/s0 3.54 3.41 -3.5% PASS
total/synth/SWAP7/s0 3.53 3.48 -1.4% PASS
total/synth/SWAP8/s0 3.49 3.44 -1.5% PASS
total/synth/SWAP9/s0 3.41 3.43 +0.4% PASS
total/synth/XOR/b0 4.99 5.17 +3.6% PASS
total/synth/XOR/b1 5.33 5.53 +3.9% PASS
total/synth/loop_v1 12.16 12.22 +0.5% PASS
total/synth/loop_v2 12.04 12.22 +1.5% PASS

Summary: 194 benchmarks, 0 regressions


✅ Performance Check Passed (multipass)

Performance Benchmark Results (threshold: 25%)

Benchmark Baseline (us) Current (us) Change Status
total/main/blake2b_huff/8415nulls 2.16 2.13 -1.2% PASS
total/main/blake2b_huff/empty 0.03 0.04 +3.9% PASS
total/main/blake2b_shifts/8415nulls 20.87 20.59 -1.3% PASS
total/main/sha1_divs/5311 12.13 11.41 -5.9% PASS
total/main/sha1_divs/empty 0.14 0.14 +0.5% PASS
total/main/sha1_shifts/5311 8.65 8.98 +3.8% PASS
total/main/sha1_shifts/empty 0.08 0.08 -1.6% PASS
total/main/snailtracer/benchmark 104.30 108.74 +4.3% PASS
total/main/structarray_alloc/nfts_rank 1.43 1.37 -4.2% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.9% PASS
total/main/swap_math/received 0.01 0.01 +5.4% PASS
total/main/swap_math/spent 0.01 0.01 -2.8% PASS
total/main/weierstrudel/1 0.38 0.38 +0.3% PASS
total/main/weierstrudel/15 4.34 4.28 -1.6% PASS
total/micro/JUMPDEST_n0/empty 0.00 0.00 -0.3% PASS
total/micro/jump_around/empty 0.07 0.08 +21.9% PASS
total/micro/loop_with_many_jumpdests/empty 0.01 0.01 -0.4% PASS
total/micro/memory_grow_mload/by1 0.02 0.02 -1.6% PASS
total/micro/memory_grow_mload/by16 0.02 0.02 -1.6% PASS
total/micro/memory_grow_mload/by32 0.01 0.01 +2.9% PASS
total/micro/memory_grow_mload/nogrow 0.01 0.01 +0.3% PASS
total/micro/memory_grow_mstore/by1 0.12 0.12 -3.7% PASS
total/micro/memory_grow_mstore/by16 0.08 0.08 +0.1% PASS
total/micro/memory_grow_mstore/by32 0.16 0.17 +1.2% PASS
total/micro/memory_grow_mstore/nogrow 0.12 0.13 +8.2% PASS
total/micro/signextend/one 0.07 0.07 -1.4% PASS
total/micro/signextend/zero 0.18 0.18 +0.7% PASS
total/synth/ADD/b0 0.00 0.00 -0.2% PASS
total/synth/ADD/b1 0.00 0.00 +1.3% PASS
total/synth/ADDRESS/a0 0.23 0.26 +12.9% PASS
total/synth/ADDRESS/a1 0.15 0.15 -0.8% PASS
total/synth/AND/b0 0.00 0.00 +0.2% PASS
total/synth/AND/b1 0.00 0.00 +0.3% PASS
total/synth/BYTE/b0 0.00 0.00 -0.9% PASS
total/synth/BYTE/b1 0.00 0.00 +0.6% PASS
total/synth/CALLDATASIZE/a0 0.12 0.12 -1.1% PASS
total/synth/CALLDATASIZE/a1 0.07 0.07 -0.1% PASS
total/synth/CALLER/a0 0.22 0.23 +3.8% PASS
total/synth/CALLER/a1 0.24 0.24 -2.2% PASS
total/synth/CALLVALUE/a0 0.19 0.19 -0.1% PASS
total/synth/CALLVALUE/a1 0.28 0.29 +3.7% PASS
total/synth/CODESIZE/a0 0.12 0.12 -1.1% PASS
total/synth/CODESIZE/a1 0.12 0.12 +0.0% PASS
total/synth/DUP1/d0 0.00 0.00 +1.0% PASS
total/synth/DUP1/d1 0.00 0.00 +0.7% PASS
total/synth/DUP10/d0 0.00 0.00 +0.4% PASS
total/synth/DUP10/d1 0.00 0.00 +0.6% PASS
total/synth/DUP11/d0 0.00 0.00 -1.1% PASS
total/synth/DUP11/d1 0.00 0.00 +0.9% PASS
total/synth/DUP12/d0 0.00 0.00 +0.6% PASS
total/synth/DUP12/d1 0.00 0.00 -0.9% PASS
total/synth/DUP13/d0 0.00 0.00 +1.0% PASS
total/synth/DUP13/d1 0.00 0.00 +0.8% PASS
total/synth/DUP14/d0 0.00 0.00 -0.8% PASS
total/synth/DUP14/d1 0.00 0.00 +0.3% PASS
total/synth/DUP15/d0 0.00 0.00 +0.6% PASS
total/synth/DUP15/d1 0.00 0.00 -0.2% PASS
total/synth/DUP16/d0 0.00 0.00 +1.0% PASS
total/synth/DUP16/d1 0.00 0.00 -0.0% PASS
total/synth/DUP2/d0 0.00 0.00 -1.7% PASS
total/synth/DUP2/d1 0.00 0.00 +0.1% PASS
total/synth/DUP3/d0 0.00 0.00 +1.2% PASS
total/synth/DUP3/d1 0.00 0.00 -0.7% PASS
total/synth/DUP4/d0 0.00 0.00 +1.2% PASS
total/synth/DUP4/d1 0.00 0.00 +0.8% PASS
total/synth/DUP5/d0 0.00 0.00 -1.2% PASS
total/synth/DUP5/d1 0.00 0.00 +0.4% PASS
total/synth/DUP6/d0 0.00 0.00 +0.2% PASS
total/synth/DUP6/d1 0.00 0.00 -0.1% PASS
total/synth/DUP7/d0 0.00 0.00 +0.4% PASS
total/synth/DUP7/d1 0.00 0.00 +0.7% PASS
total/synth/DUP8/d0 0.00 0.00 -1.0% PASS
total/synth/DUP8/d1 0.00 0.00 -0.8% PASS
total/synth/DUP9/d0 0.00 0.00 +0.1% PASS
total/synth/DUP9/d1 0.00 0.00 -0.5% PASS
total/synth/EQ/b0 0.00 0.00 +0.4% PASS
total/synth/EQ/b1 0.00 0.00 +1.0% PASS
total/synth/GAS/a0 0.77 0.77 -0.1% PASS
total/synth/GAS/a1 0.93 0.93 -0.3% PASS
total/synth/GT/b0 0.00 0.00 +0.9% PASS
total/synth/GT/b1 0.00 0.00 +1.2% PASS
total/synth/ISZERO/u0 0.00 0.00 +0.6% PASS
total/synth/JUMPDEST/n0 0.00 0.00 -1.4% PASS
total/synth/LT/b0 0.00 0.00 +1.1% PASS
total/synth/LT/b1 0.00 0.00 -0.9% PASS
total/synth/MSIZE/a0 0.00 0.00 +1.1% PASS
total/synth/MSIZE/a1 0.00 0.00 +1.0% PASS
total/synth/MUL/b0 0.00 0.00 +0.0% PASS
total/synth/MUL/b1 0.00 0.00 -0.6% PASS
total/synth/NOT/u0 0.00 0.00 +0.6% PASS
total/synth/OR/b0 0.00 0.00 +1.2% PASS
total/synth/OR/b1 0.00 0.00 -0.9% PASS
total/synth/PC/a0 0.00 0.00 +2.8% PASS
total/synth/PC/a1 0.00 0.00 -1.0% PASS
total/synth/PUSH1/p0 0.00 0.00 +0.1% PASS
total/synth/PUSH1/p1 0.00 0.00 -0.4% PASS
total/synth/PUSH10/p0 0.00 0.00 -1.0% PASS
total/synth/PUSH10/p1 0.00 0.00 -0.7% PASS
total/synth/PUSH11/p0 0.00 0.00 -3.5% PASS
total/synth/PUSH11/p1 0.00 0.00 +3.4% PASS
total/synth/PUSH12/p0 0.00 0.00 +0.0% PASS
total/synth/PUSH12/p1 0.00 0.00 -0.9% PASS
total/synth/PUSH13/p0 0.00 0.00 -0.0% PASS
total/synth/PUSH13/p1 0.00 0.00 +0.3% PASS
total/synth/PUSH14/p0 0.00 0.00 +0.3% PASS
total/synth/PUSH14/p1 0.00 0.00 +1.8% PASS
total/synth/PUSH15/p0 0.00 0.00 -0.4% PASS
total/synth/PUSH15/p1 0.00 0.00 +2.2% PASS
total/synth/PUSH16/p0 0.00 0.00 +0.0% PASS
total/synth/PUSH16/p1 0.00 0.00 +0.9% PASS
total/synth/PUSH17/p0 0.00 0.00 -4.0% PASS
total/synth/PUSH17/p1 0.00 0.00 -0.4% PASS
total/synth/PUSH18/p0 0.00 0.00 -0.4% PASS
total/synth/PUSH18/p1 0.00 0.00 +2.3% PASS
total/synth/PUSH19/p0 0.00 0.00 +2.0% PASS
total/synth/PUSH19/p1 0.00 0.00 +0.0% PASS
total/synth/PUSH2/p0 0.00 0.00 +1.1% PASS
total/synth/PUSH2/p1 0.00 0.00 -1.1% PASS
total/synth/PUSH20/p0 0.00 0.00 -4.5% PASS
total/synth/PUSH20/p1 0.00 0.00 -1.8% PASS
total/synth/PUSH21/p0 0.00 0.00 -0.7% PASS
total/synth/PUSH21/p1 0.00 0.00 -2.1% PASS
total/synth/PUSH22/p0 2.15 2.08 -3.2% PASS
total/synth/PUSH22/p1 1.72 1.57 -8.6% PASS
total/synth/PUSH23/p0 2.13 2.09 -1.7% PASS
total/synth/PUSH23/p1 2.24 2.30 +2.8% PASS
total/synth/PUSH24/p0 1.32 1.32 -0.1% PASS
total/synth/PUSH24/p1 2.24 2.21 -1.6% PASS
total/synth/PUSH25/p0 2.12 2.09 -1.4% PASS
total/synth/PUSH25/p1 1.57 1.80 +14.7% PASS
total/synth/PUSH26/p0 2.12 2.09 -1.7% PASS
total/synth/PUSH26/p1 2.18 2.26 +3.7% PASS
total/synth/PUSH27/p0 1.32 1.32 +0.3% PASS
total/synth/PUSH27/p1 2.18 2.29 +5.0% PASS
total/synth/PUSH28/p0 2.12 2.35 +11.0% PASS
total/synth/PUSH28/p1 1.57 1.75 +11.6% PASS
total/synth/PUSH29/p0 2.12 2.09 -1.6% PASS
total/synth/PUSH29/p1 2.25 2.27 +1.1% PASS
total/synth/PUSH3/p0 0.00 0.00 -0.1% PASS
total/synth/PUSH3/p1 0.00 0.00 +5.2% PASS
total/synth/PUSH30/p0 1.46 1.48 +1.6% PASS
total/synth/PUSH30/p1 2.16 2.18 +1.0% PASS
total/synth/PUSH31/p0 2.18 2.09 -3.9% PASS
total/synth/PUSH31/p1 1.83 1.96 +7.5% PASS
total/synth/PUSH32/p0 2.15 2.15 +0.2% PASS
total/synth/PUSH32/p1 2.24 2.28 +1.7% PASS
total/synth/PUSH4/p0 0.00 0.00 -2.3% PASS
total/synth/PUSH4/p1 0.00 0.00 +0.5% PASS
total/synth/PUSH5/p0 0.00 0.00 +0.2% PASS
total/synth/PUSH5/p1 0.00 0.00 +1.1% PASS
total/synth/PUSH6/p0 0.00 0.00 -0.7% PASS
total/synth/PUSH6/p1 0.00 0.00 +1.8% PASS
total/synth/PUSH7/p0 0.00 0.00 -4.1% PASS
total/synth/PUSH7/p1 0.00 0.00 -1.0% PASS
total/synth/PUSH8/p0 0.00 0.00 +2.3% PASS
total/synth/PUSH8/p1 0.00 0.00 +1.1% PASS
total/synth/PUSH9/p0 0.00 0.00 -1.2% PASS
total/synth/PUSH9/p1 0.00 0.00 -0.5% PASS
total/synth/RETURNDATASIZE/a0 0.03 0.03 +0.0% PASS
total/synth/RETURNDATASIZE/a1 0.06 0.06 +3.8% PASS
total/synth/SAR/b0 0.00 0.00 -1.1% PASS
total/synth/SAR/b1 0.00 0.00 +0.5% PASS
total/synth/SGT/b0 0.00 0.00 +0.5% PASS
total/synth/SGT/b1 0.00 0.00 -0.5% PASS
total/synth/SHL/b0 0.00 0.00 +1.3% PASS
total/synth/SHL/b1 0.00 0.00 +0.8% PASS
total/synth/SHR/b0 0.00 0.00 +0.5% PASS
total/synth/SHR/b1 0.00 0.00 +0.7% PASS
total/synth/SIGNEXTEND/b0 0.00 0.00 -0.6% PASS
total/synth/SIGNEXTEND/b1 0.00 0.00 +0.6% PASS
total/synth/SLT/b0 0.00 0.00 -0.8% PASS
total/synth/SLT/b1 0.00 0.00 +0.6% PASS
total/synth/SUB/b0 0.00 0.00 -0.2% PASS
total/synth/SUB/b1 0.00 0.00 +0.1% PASS
total/synth/SWAP1/s0 0.00 0.00 -1.2% PASS
total/synth/SWAP10/s0 0.00 0.00 -1.6% PASS
total/synth/SWAP11/s0 0.00 0.00 +0.6% PASS
total/synth/SWAP12/s0 0.00 0.00 -0.1% PASS
total/synth/SWAP13/s0 0.00 0.00 -0.7% PASS
total/synth/SWAP14/s0 0.00 0.00 +0.0% PASS
total/synth/SWAP15/s0 0.00 0.00 +1.7% PASS
total/synth/SWAP16/s0 0.00 0.00 -2.0% PASS
total/synth/SWAP2/s0 0.00 0.00 +0.7% PASS
total/synth/SWAP3/s0 0.00 0.00 -0.4% PASS
total/synth/SWAP4/s0 0.00 0.00 +0.1% PASS
total/synth/SWAP5/s0 0.00 0.00 +1.0% PASS
total/synth/SWAP6/s0 0.00 0.00 +1.3% PASS
total/synth/SWAP7/s0 0.00 0.00 -0.4% PASS
total/synth/SWAP8/s0 0.00 0.00 +1.7% PASS
total/synth/SWAP9/s0 0.00 0.00 +0.2% PASS
total/synth/XOR/b0 0.00 0.00 +0.1% PASS
total/synth/XOR/b1 0.00 0.00 +0.9% PASS
total/synth/loop_v1 11.54 11.76 +2.2% PASS
total/synth/loop_v2 11.63 11.75 +1.1% PASS

Summary: 194 benchmarks, 0 regressions


Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR improves EVM MIR lowering by consuming existing ValueRange tags to generate narrower (and sometimes fused) code paths for ISZERO/JUMPI, OR/XOR, and signed comparisons, and adds differential regression fixtures to ensure Multipass matches the interpreter.

Changes:

  • Propagate base range through deferred ISZERO operands and use it to narrow limb folding in ISZERO materialization and JUMPI condition evaluation (including deferred-zero-test fusion).
  • Add non-constant range-narrowed OR/XOR paths and u64-constant fast paths for SLT/SGT.
  • Add 21 adversarial EVM-asm fixtures plus a new parameterized differential test to validate interpreter vs. Multipass output.

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/evm_asm/xor_dyn_u64_wide.expected New expected output for XOR mixed wide/u64-range narrowing coverage
tests/evm_asm/xor_dyn_u64_wide.easm New adversarial XOR fixture (upper-limb passthrough)
tests/evm_asm/xor_dyn_u64_u64.expected New expected output for XOR u64/u64 fast path
tests/evm_asm/xor_dyn_u64_u64.easm New XOR fixture exercising both-fit-u64 path
tests/evm_asm/slt_dyn_neg_vs_const.expected New expected output for SLT signed fast path (negative vs const)
tests/evm_asm/slt_dyn_neg_vs_const.easm New SLT fixture for negative dynamic vs u64 const
tests/evm_asm/slt_dyn_msb64_vs_const.expected New expected output for SLT msb64 edge case
tests/evm_asm/slt_dyn_msb64_vs_const.easm New SLT fixture guarding against incorrect signed-i64 limb0 compare
tests/evm_asm/slt_dyn_highsparse_vs_const.expected New expected output for SLT highsparse dynamic vs const
tests/evm_asm/slt_dyn_highsparse_vs_const.easm New SLT fixture for upper-limb selection logic
tests/evm_asm/slt_dyn_eq_const.expected New expected output for SLT equality boundary
tests/evm_asm/slt_dyn_eq_const.easm New SLT fixture ensuring strict-less behavior
tests/evm_asm/slt_const_vs_dyn.expected New expected output for SLT const-vs-dyn swapped-dispatch case
tests/evm_asm/slt_const_vs_dyn.easm New SLT fixture exercising swapped dispatch
tests/evm_asm/sgt_dyn_neg_vs_const.expected New expected output for SGT negative vs const
tests/evm_asm/sgt_dyn_neg_vs_const.easm New SGT fixture for negative dynamic vs const
tests/evm_asm/sgt_dyn_msb64_vs_const.expected New expected output for SGT msb64 edge case
tests/evm_asm/sgt_dyn_msb64_vs_const.easm New SGT fixture guarding unsigned limb0 compare logic
tests/evm_asm/sgt_dyn_highsparse_vs_const.expected New expected output for SGT highsparse dynamic vs const
tests/evm_asm/sgt_dyn_highsparse_vs_const.easm New SGT fixture for upper-limb selection logic
tests/evm_asm/sgt_const_vs_dyn.expected New expected output for SGT const-vs-dyn swapped-dispatch case
tests/evm_asm/sgt_const_vs_dyn.easm New SGT fixture exercising swapped dispatch
tests/evm_asm/or_dyn_u64_wide.expected New expected output for OR mixed wide/u64-range narrowing coverage
tests/evm_asm/or_dyn_u64_wide.easm New adversarial OR fixture (upper-limb passthrough)
tests/evm_asm/or_dyn_u64_u64.expected New expected output for OR u64/u64 fast path
tests/evm_asm/or_dyn_u64_u64.easm New OR fixture exercising both-fit-u64 path
tests/evm_asm/jumpi_u64_cond_taken.expected New expected output for JUMPI with u64-tagged cond (taken)
tests/evm_asm/jumpi_u64_cond_taken.easm New JUMPI fixture exercising FoldLimbs=1 path
tests/evm_asm/jumpi_u64_cond_nottaken.expected New expected output for JUMPI with u64-tagged cond (not taken)
tests/evm_asm/jumpi_u64_cond_nottaken.easm New JUMPI fixture exercising FoldLimbs=1 path (zero)
tests/evm_asm/jumpi_iszero_iszero_fused.expected New expected output for double-ISZERO deferred fusion through JUMPI
tests/evm_asm/jumpi_iszero_iszero_fused.easm New fixture exercising deferred-zero-test negation flip + JUMPI fold
tests/evm_asm/jumpi_iszero_fused_taken.expected New expected output for deferred ISZERO fused into JUMPI (taken)
tests/evm_asm/jumpi_iszero_fused_taken.easm New fixture verifying ISZERO materialization elision in JUMPI
tests/evm_asm/jumpi_iszero_fused_nottaken_highsparse.expected New expected output for highsparse base in deferred ISZERO fusion (not taken)
tests/evm_asm/jumpi_iszero_fused_nottaken_highsparse.easm New adversarial fixture preventing limb0-only folding bugs
tests/evm_asm/iszero_dyn_u64_nonzero.expected New expected output for ISZERO on u64-tagged nonzero dynamic
tests/evm_asm/iszero_dyn_u64_nonzero.easm New ISZERO fixture exercising narrowed fold for u64
tests/evm_asm/iszero_dyn_highsparse.expected New expected output for ISZERO highsparse dynamic
tests/evm_asm/iszero_dyn_highsparse.easm New ISZERO fixture guarding against limb0-only fold
tests/evm_asm/iszero_calldatasize.expected New expected output for ISZERO(CALLDATASIZE)
tests/evm_asm/iszero_calldatasize.easm New fixture covering env-op producer tagging + ISZERO narrow fold
src/tests/evm_interp_tests.cpp Add parameterized differential test suite and instantiate it for new fixtures
src/compiler/evm_frontend/evm_mir_compiler.h Track deferred-zero-test base range; add SLT/SGT u64-const helper declarations; extend EQZ signature
src/compiler/evm_frontend/evm_mir_compiler.cpp Implement narrowed ISZERO fold, JUMPI fusion/narrow fold, OR/XOR range narrowing, SLT/SGT u64-const fast paths, and U64-tagging for single-instr u256 producers
docs/changes/2026-06-10-evm-range-lowering-gaps/README.md Design/change note describing the new range-consuming lowering paths and verification/measurements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/compiler/evm_frontend/evm_mir_compiler.cpp
@abmcar

abmcar commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

The differential test suite and its fixtures have moved out of this PR into #539, which consolidates the interp-vs-multipass differential coverage from all three optimization PRs into a dedicated test target. This PR is now code + docs only; #539 carries the tests and can merge independently in any order.

abmcar and others added 7 commits June 24, 2026 17:00
…lowering

Close lowering-side gaps where operands already proven u64 by the range
analyzer still took full 4-limb paths:

- ISZERO: deferred zero-test operands now carry the base value range and
  tag their 0/1 result as u64; materialization folds only the limbs the
  range allows (u64 base -> single-limb test).
- JUMPI: fuse deferred zero-test conditions into the branch (no
  materialize-then-refold round trip) and fold only range-live limbs of
  non-deferred conditions.
- OR/XOR: new non-constant narrow paths — both-u64 emits a single i64 op
  with zeroed upper limbs; one-sided u64 passes the wide side's upper
  limbs through (identity), mirroring the existing const-u64 path.
- SLT/SGT: new fast paths against u64 constants with the same three
  range tiers as the unsigned compare helpers; a u64 constant is a
  non-negative signed-256 value, so sign-bit + upper-or + unsigned
  limb0 compare decide the result.
- Context-size producers (PC/GAS/CALLDATASIZE/CODESIZE/MSIZE/
  RETURNDATASIZE): tag results u64 — limbs 1..3 are literal zeros by
  construction, closing a builder/analyzer SSOT divergence.

Add 21 adversarial differential fixtures (interp vs multipass, boundary
values incl. 2^64/2^128/2^192/-1/high-sparse and limb0 MSB cases) plus
an EVMRangeNarrowingDifferentialTest suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…after rebase

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e step

Set Status to Implemented. Reword the two references to repository paths
that ship with the separate mainnet-replay analysis-suite work and are
absent from this tree: the motivation's real-load analysis pointer and the
known-limitation re-measure step (formerly tools/run_real_load_profile.py).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The EVMRangeNarrowingDifferentialTest suite and its 21 evm_asm fixtures
relocate to the dedicated differential-suite change so optimization PRs stay
code-only and the shared evm_interp_tests file stops accumulating per-PR copies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Align the doc with the technical-writing rule: describe internal labels by behavior, remove who-reviewed and process narrative, and keep every count, flag, code anchor, and measurement. No code or runtime change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cen5bPpPEgkSkcxWWTSY7d
@abmcar abmcar force-pushed the perf/evm-range-lowering-gaps branch from b952a35 to 5e53858 Compare June 24, 2026 09:08
@zoowii zoowii merged commit 4d1776f into DTVMStack:main Jun 26, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants