Skip to content

perf(compiler): strength-reduce EXP with a constant power-of-two base or trivial exponent#550

Open
abmcar wants to merge 1 commit into
DTVMStack:mainfrom
abmcar:opt/evm-exp-strength-reduction
Open

perf(compiler): strength-reduce EXP with a constant power-of-two base or trivial exponent#550
abmcar wants to merge 1 commit into
DTVMStack:mainfrom
abmcar:opt/evm-exp-strength-reduction

Conversation

@abmcar

@abmcar abmcar commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

What

Add three compile-time fast paths to handleExp for a constant base:

  • EXP(base, 0) -> 1, EXP(base, 1) -> base (dynamic base, constant exponent)
  • EXP(2^k, x) -> (k*x >= 256) ? 0 : 1 << (k*x) for any constant power-of-two base with a dynamic exponent

Previously every EXP whose operands were not both constant emitted the inline square-and-multiply loop. This covers the 2 ** x and 256 ** x forms (the latter is the Solidity storage-packing idiom).

Soundness

(2^k)^x = 2^(k*x) mod 2^256. For k >= 2, k*x wraps modulo 2^256 on large x, so the result is guarded by an explicit x >= ceil(256/k) -> 0 test rather than the shift primitive's own >= 256 check (which would see the wrapped product); below that threshold k*x is exact and < 256. EIP-160 dynamic gas depends only on the exponent and is charged by the unchanged general path, so gas is byte-for-byte identical.

Tests

New differential test evm_exp_strength_tests.cpp: the variable operand is fed via CALLDATALOAD so the analyzer cannot fold it and the fast path is taken. Output is checked against the interpreter and against an independent bit-placement 1 << x table (the interpreter's intx::exp folds power-of-two bases to the same shift, so the table is an independent reference). Coverage: bases 2 through 2^255, exponents straddling each k*x = 256 threshold, an overflow-guard case (base 256, x = 2^253 wraps 8*x to 0), and offset-free EIP-160 gas deltas across Cancun and pre-Spurious-Dragon.

Full suite: 223 multipass unit tests, 2723 state tests (-k fork_Cancun), 6 EXP tests, tools/format.sh check clean, 0 new compiler warnings.

Performance

EXP is not present in the standard evmone benchmark suite. On a targeted synthetic benchmark (50x EXP(2^k, x) on a dynamic exponent), the new path is constant-time (~7 ns/op) versus a square-and-multiply loop that scales with exponent byte width: per-execution speedup 3.3x–149x depending on exponent magnitude. Aggregate effect on real workloads is small (EXP is ~0.12% of opcodes on a mainnet sample, and most is already double-constant-folded).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 24, 2026 05:45

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

This PR adds compiler-side EXP strength-reduction fast paths in the EVM MIR builder to avoid emitting the square-and-multiply loop for common constant-base cases, while preserving EIP-160 dynamic gas behavior. It also introduces a focused differential test to validate both output and gas behavior across interpreter vs multipass JIT.

Changes:

  • Add EXP(base, 0) -> 1 and EXP(base, 1) -> base fast paths with explicit EIP-160 dynamic gas charging.
  • Add EXP(2^k, x) -> (x >= ceil(256/k) ? 0 : 1 << (k*x)) fast path for constant power-of-two bases with an overflow guard.
  • Add new multipass-only differential tests and wire them into the spec-test CMake targets, plus a light change proposal doc.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/compiler/evm_frontend/evm_mir_compiler.cpp Implements EXP strength-reduction fast paths and preserves dynamic gas charging semantics.
src/tests/evm_exp_strength_tests.cpp Adds differential tests covering correctness and EIP-160 gas deltas for the new fast paths.
src/tests/CMakeLists.txt Adds evmExpStrengthTests target and registers it under multipass spec tests.
docs/changes/2026-06-15-evm-exp-strength-reduction/README.md Documents the optimization, motivation, and test plan as a light change proposal.

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

Comment thread src/tests/evm_exp_strength_tests.cpp Outdated
Comment on lines +133 to +137
EXPECT_TRUE(Multi.JITCompiled) << "multipass did not JIT-compile: " << Label;
EXPECT_EQ(Interp.Status, EVMC_SUCCESS)
<< "interpreter did not succeed: " << Label;
EXPECT_EQ(Multi.Status, Interp.Status) << "status diverged: " << Label;
EXPECT_EQ(Multi.OutputHex, Interp.OutputHex) << "output diverged: " << Label;
@@ -0,0 +1,59 @@
# Change: Strength-reduce EXP for constant power-of-two bases

- **Status**: Proposed
Comment on lines +34 to +36
- EIP-160 dynamic gas unchanged: it depends only on the exponent and is charged
by the unchanged general path, so gas is byte-for-byte identical.
- No effect on other EXP forms or other opcodes.
@github-actions

github-actions Bot commented Jun 24, 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.81 3.80 -0.3% PASS
total/main/blake2b_huff/empty 0.06 0.06 +2.5% PASS
total/main/blake2b_shifts/8415nulls 20.61 20.77 +0.8% PASS
total/main/sha1_divs/5311 11.93 12.12 +1.6% PASS
total/main/sha1_divs/empty 0.15 0.15 +0.5% PASS
total/main/sha1_shifts/5311 9.27 9.09 -1.9% PASS
total/main/sha1_shifts/empty 0.08 0.08 +0.2% PASS
total/main/snailtracer/benchmark 111.39 107.91 -3.1% PASS
total/main/structarray_alloc/nfts_rank 1.40 1.47 +5.3% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.5% PASS
total/main/swap_math/received 0.01 0.01 -4.3% PASS
total/main/swap_math/spent 0.01 0.01 +1.4% PASS
total/main/weierstrudel/1 0.39 0.39 -0.3% PASS
total/main/weierstrudel/15 4.37 4.34 -0.6% PASS
total/micro/JUMPDEST_n0/empty 2.87 2.86 -0.2% PASS
total/micro/jump_around/empty 0.11 0.11 +1.4% PASS
total/micro/loop_with_many_jumpdests/empty 64.94 64.81 -0.2% PASS
total/micro/memory_grow_mload/by1 0.22 0.22 -0.1% PASS
total/micro/memory_grow_mload/by16 0.24 0.25 +1.5% PASS
total/micro/memory_grow_mload/by32 0.15 0.15 -1.4% PASS
total/micro/memory_grow_mload/nogrow 0.12 0.12 +0.9% PASS
total/micro/memory_grow_mstore/by1 0.24 0.24 -1.8% PASS
total/micro/memory_grow_mstore/by16 0.14 0.16 +12.5% PASS
total/micro/memory_grow_mstore/by32 0.28 0.27 -1.6% PASS
total/micro/memory_grow_mstore/nogrow 0.24 0.24 +2.1% PASS
total/micro/signextend/one 0.28 0.28 +0.1% PASS
total/micro/signextend/zero 0.47 0.48 +0.7% PASS
total/synth/ADD/b0 3.24 3.23 -0.2% PASS
total/synth/ADD/b1 5.98 5.65 -5.6% PASS
total/synth/ADDRESS/a0 6.51 6.65 +2.1% PASS
total/synth/ADDRESS/a1 5.21 5.35 +2.6% PASS
total/synth/AND/b0 2.88 2.87 -0.2% PASS
total/synth/AND/b1 5.40 5.28 -2.2% PASS
total/synth/BYTE/b0 6.08 6.08 -0.1% PASS
total/synth/BYTE/b1 8.37 8.33 -0.5% PASS
total/synth/CALLDATASIZE/a0 5.50 5.44 -1.1% PASS
total/synth/CALLDATASIZE/a1 3.49 3.69 +5.9% PASS
total/synth/CALLER/a0 6.74 6.77 +0.4% PASS
total/synth/CALLER/a1 7.02 6.83 -2.7% PASS
total/synth/CALLVALUE/a0 3.40 3.60 +5.9% PASS
total/synth/CALLVALUE/a1 6.29 6.52 +3.6% PASS
total/synth/CODESIZE/a0 6.99 6.66 -4.8% PASS
total/synth/CODESIZE/a1 6.67 7.02 +5.2% PASS
total/synth/DUP1/d0 1.98 1.98 +0.0% PASS
total/synth/DUP1/d1 2.07 2.06 -0.8% PASS
total/synth/DUP10/d0 2.00 2.01 +0.6% PASS
total/synth/DUP10/d1 2.14 2.15 +0.3% PASS
total/synth/DUP11/d0 1.11 1.23 +11.1% PASS
total/synth/DUP11/d1 2.08 2.11 +1.5% PASS
total/synth/DUP12/d0 1.97 2.01 +2.2% PASS
total/synth/DUP12/d1 1.66 1.66 -0.4% PASS
total/synth/DUP13/d0 1.98 2.01 +1.4% PASS
total/synth/DUP13/d1 2.12 2.06 -2.8% PASS
total/synth/DUP14/d0 1.21 1.23 +1.4% PASS
total/synth/DUP14/d1 2.11 2.18 +3.3% PASS
total/synth/DUP15/d0 1.99 2.00 +0.7% PASS
total/synth/DUP15/d1 1.62 1.66 +1.9% PASS
total/synth/DUP16/d0 1.99 1.93 -3.0% PASS
total/synth/DUP16/d1 2.13 2.27 +6.6% PASS
total/synth/DUP2/d0 1.11 1.23 +11.4% PASS
total/synth/DUP2/d1 2.10 2.08 -0.8% PASS
total/synth/DUP3/d0 1.98 2.05 +3.5% PASS
total/synth/DUP3/d1 1.66 1.65 -0.5% PASS
total/synth/DUP4/d0 1.95 2.03 +3.9% PASS
total/synth/DUP4/d1 2.07 2.06 -0.4% PASS
total/synth/DUP5/d0 1.23 1.11 -10.2% PASS
total/synth/DUP5/d1 2.15 2.08 -3.4% PASS
total/synth/DUP6/d0 2.06 1.97 -4.4% PASS
total/synth/DUP6/d1 1.66 1.45 -12.9% PASS
total/synth/DUP7/d0 1.96 2.03 +3.3% PASS
total/synth/DUP7/d1 2.16 2.13 -1.2% PASS
total/synth/DUP8/d0 1.23 1.23 +0.1% PASS
total/synth/DUP8/d1 2.12 2.11 -0.5% PASS
total/synth/DUP9/d0 1.98 1.97 -0.8% PASS
total/synth/DUP9/d1 1.66 1.45 -12.6% PASS
total/synth/EQ/b0 6.11 6.21 +1.6% PASS
total/synth/EQ/b1 6.32 6.36 +0.6% PASS
total/synth/GAS/a0 3.93 3.93 -0.1% PASS
total/synth/GAS/a1 7.48 7.32 -2.3% PASS
total/synth/GT/b0 6.34 6.30 -0.6% PASS
total/synth/GT/b1 6.56 6.51 -0.8% PASS
total/synth/ISZERO/u0 10.14 10.17 +0.2% PASS
total/synth/JUMPDEST/n0 2.87 2.87 -0.1% PASS
total/synth/LT/b0 6.22 6.28 +1.1% PASS
total/synth/LT/b1 5.44 5.42 -0.4% PASS
total/synth/MSIZE/a0 6.00 5.99 -0.1% PASS
total/synth/MSIZE/a1 6.47 6.16 -4.8% PASS
total/synth/MUL/b0 7.80 8.06 +3.3% PASS
total/synth/MUL/b1 5.93 5.92 -0.1% PASS
total/synth/NOT/u0 8.06 8.17 +1.4% PASS
total/synth/OR/b0 5.00 5.15 +2.9% PASS
total/synth/OR/b1 3.64 3.40 -6.6% PASS
total/synth/PC/a0 5.36 5.54 +3.5% PASS
total/synth/PC/a1 3.49 3.67 +5.2% PASS
total/synth/PUSH1/p0 2.19 2.27 +3.9% PASS
total/synth/PUSH1/p1 1.66 1.53 -7.8% PASS
total/synth/PUSH10/p0 2.40 2.30 -4.2% PASS
total/synth/PUSH10/p1 1.76 1.75 -0.4% PASS
total/synth/PUSH11/p0 2.39 2.84 +19.1% PASS
total/synth/PUSH11/p1 2.41 2.59 +7.2% PASS
total/synth/PUSH12/p0 1.32 1.30 -1.4% PASS
total/synth/PUSH12/p1 2.41 2.47 +2.6% PASS
total/synth/PUSH13/p0 2.19 2.29 +4.5% PASS
total/synth/PUSH13/p1 1.80 1.55 -14.1% PASS
total/synth/PUSH14/p0 2.39 2.38 -0.3% PASS
total/synth/PUSH14/p1 2.37 2.57 +8.2% PASS
total/synth/PUSH15/p0 1.32 1.32 +0.2% PASS
total/synth/PUSH15/p1 2.57 2.56 -0.4% PASS
total/synth/PUSH16/p0 2.28 2.29 +0.3% PASS
total/synth/PUSH16/p1 1.74 1.56 -10.5% PASS
total/synth/PUSH17/p0 2.25 2.36 +5.0% PASS
total/synth/PUSH17/p1 2.48 2.42 -2.5% PASS
total/synth/PUSH18/p0 1.32 1.32 -0.3% PASS
total/synth/PUSH18/p1 2.39 2.53 +5.9% PASS
total/synth/PUSH19/p0 2.42 2.22 -8.1% PASS
total/synth/PUSH19/p1 1.81 1.75 -3.3% PASS
total/synth/PUSH2/p0 2.34 2.24 -4.1% PASS
total/synth/PUSH2/p1 2.38 2.41 +1.4% PASS
total/synth/PUSH20/p0 2.21 2.30 +4.1% PASS
total/synth/PUSH20/p1 2.44 2.51 +2.9% PASS
total/synth/PUSH21/p0 1.32 1.32 -0.2% PASS
total/synth/PUSH21/p1 2.67 2.41 -9.7% PASS
total/synth/PUSH22/p0 2.82 2.28 -19.3% PASS
total/synth/PUSH22/p1 1.76 1.55 -11.8% PASS
total/synth/PUSH23/p0 2.62 2.26 -13.9% PASS
total/synth/PUSH23/p1 2.44 2.48 +1.5% PASS
total/synth/PUSH24/p0 1.35 1.32 -1.8% PASS
total/synth/PUSH24/p1 2.33 2.47 +6.3% PASS
total/synth/PUSH25/p0 2.27 2.37 +4.4% PASS
total/synth/PUSH25/p1 1.73 1.75 +0.9% PASS
total/synth/PUSH26/p0 2.26 2.34 +3.8% PASS
total/synth/PUSH26/p1 2.56 2.36 -7.6% PASS
total/synth/PUSH27/p0 1.32 1.32 +0.2% PASS
total/synth/PUSH27/p1 2.40 2.67 +11.4% PASS
total/synth/PUSH28/p0 2.30 2.36 +2.8% PASS
total/synth/PUSH28/p1 1.76 1.77 +0.4% PASS
total/synth/PUSH29/p0 2.28 2.32 +1.7% PASS
total/synth/PUSH29/p1 2.73 2.49 -8.8% PASS
total/synth/PUSH3/p0 1.32 1.32 -0.3% PASS
total/synth/PUSH3/p1 2.44 2.35 -3.7% PASS
total/synth/PUSH30/p0 1.44 1.41 -2.1% PASS
total/synth/PUSH30/p1 2.66 2.37 -10.8% PASS
total/synth/PUSH31/p0 2.29 2.39 +4.2% PASS
total/synth/PUSH31/p1 1.84 1.85 +0.6% PASS
total/synth/PUSH32/p0 2.19 2.23 +1.9% PASS
total/synth/PUSH32/p1 2.48 2.43 -2.0% PASS
total/synth/PUSH4/p0 2.30 2.40 +4.1% PASS
total/synth/PUSH4/p1 1.75 1.75 -0.2% PASS
total/synth/PUSH5/p0 2.26 2.22 -1.9% PASS
total/synth/PUSH5/p1 2.33 2.38 +2.1% PASS
total/synth/PUSH6/p0 1.34 1.32 -1.7% PASS
total/synth/PUSH6/p1 2.46 2.58 +5.1% PASS
total/synth/PUSH7/p0 2.33 2.34 +0.4% PASS
total/synth/PUSH7/p1 1.76 1.60 -9.2% PASS
total/synth/PUSH8/p0 2.19 2.36 +7.7% PASS
total/synth/PUSH8/p1 2.39 2.38 -0.3% PASS
total/synth/PUSH9/p0 1.32 1.32 -0.3% PASS
total/synth/PUSH9/p1 2.38 2.40 +0.4% PASS
total/synth/RETURNDATASIZE/a0 3.57 3.81 +6.8% PASS
total/synth/RETURNDATASIZE/a1 6.47 6.23 -3.7% PASS
total/synth/SAR/b0 3.94 3.94 -0.1% PASS
total/synth/SAR/b1 7.71 7.43 -3.7% PASS
total/synth/SGT/b0 5.65 5.74 +1.5% PASS
total/synth/SGT/b1 4.15 4.13 -0.4% PASS
total/synth/SHL/b0 7.18 7.28 +1.4% PASS
total/synth/SHL/b1 3.66 3.65 -0.4% PASS
total/synth/SHR/b0 7.08 6.95 -1.8% PASS
total/synth/SHR/b1 6.34 6.33 -0.2% PASS
total/synth/SIGNEXTEND/b0 3.37 3.37 +0.2% PASS
total/synth/SIGNEXTEND/b1 6.78 6.50 -4.1% PASS
total/synth/SLT/b0 4.31 4.29 -0.4% PASS
total/synth/SLT/b1 5.87 5.78 -1.6% PASS
total/synth/SUB/b0 5.73 5.67 -1.2% PASS
total/synth/SUB/b1 5.99 5.99 +0.0% PASS
total/synth/SWAP1/s0 3.52 3.52 -0.1% PASS
total/synth/SWAP10/s0 3.54 3.53 -0.2% PASS
total/synth/SWAP11/s0 3.46 3.46 +0.0% PASS
total/synth/SWAP12/s0 3.48 3.51 +0.7% PASS
total/synth/SWAP13/s0 3.54 3.54 -0.1% PASS
total/synth/SWAP14/s0 3.51 3.50 -0.2% PASS
total/synth/SWAP15/s0 3.52 3.54 +0.6% PASS
total/synth/SWAP16/s0 3.54 3.55 +0.3% PASS
total/synth/SWAP2/s0 3.46 3.45 -0.3% PASS
total/synth/SWAP3/s0 3.48 3.48 -0.2% PASS
total/synth/SWAP4/s0 3.53 3.52 -0.2% PASS
total/synth/SWAP5/s0 3.44 3.48 +1.1% PASS
total/synth/SWAP6/s0 3.46 3.47 +0.5% PASS
total/synth/SWAP7/s0 3.53 3.53 -0.1% PASS
total/synth/SWAP8/s0 3.51 3.44 -2.0% PASS
total/synth/SWAP9/s0 3.46 3.46 +0.0% PASS
total/synth/XOR/b0 5.15 5.10 -0.7% PASS
total/synth/XOR/b1 5.31 5.37 +1.1% PASS
total/synth/loop_v1 12.28 12.14 -0.9% PASS
total/synth/loop_v2 12.85 12.16 -5.4% 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.35 2.16 -8.3% PASS
total/main/blake2b_huff/empty 0.04 0.04 -4.4% PASS
total/main/blake2b_shifts/8415nulls 20.51 20.79 +1.4% PASS
total/main/sha1_divs/5311 11.55 11.85 +2.6% PASS
total/main/sha1_divs/empty 0.14 0.15 +3.5% PASS
total/main/sha1_shifts/5311 8.92 8.64 -3.1% PASS
total/main/sha1_shifts/empty 0.08 0.08 -0.0% PASS
total/main/snailtracer/benchmark 105.10 107.04 +1.8% PASS
total/main/structarray_alloc/nfts_rank 1.38 1.38 -0.2% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.4% PASS
total/main/swap_math/received 0.01 0.01 +0.2% PASS
total/main/swap_math/spent 0.01 0.01 +4.5% PASS
total/main/weierstrudel/1 0.39 0.39 -1.4% PASS
total/main/weierstrudel/15 4.27 4.26 -0.1% PASS
total/micro/JUMPDEST_n0/empty 0.00 0.00 +0.2% PASS
total/micro/jump_around/empty 0.07 0.07 +7.7% PASS
total/micro/loop_with_many_jumpdests/empty 0.01 0.01 +1.4% PASS
total/micro/memory_grow_mload/by1 0.02 0.02 -2.7% PASS
total/micro/memory_grow_mload/by16 0.02 0.02 -0.7% PASS
total/micro/memory_grow_mload/by32 0.01 0.01 -1.0% PASS
total/micro/memory_grow_mload/nogrow 0.01 0.01 -0.6% PASS
total/micro/memory_grow_mstore/by1 0.13 0.13 -0.3% PASS
total/micro/memory_grow_mstore/by16 0.08 0.08 +0.2% PASS
total/micro/memory_grow_mstore/by32 0.17 0.17 -0.4% PASS
total/micro/memory_grow_mstore/nogrow 0.13 0.13 -3.3% PASS
total/micro/signextend/one 0.08 0.08 +0.2% PASS
total/micro/signextend/zero 0.19 0.19 -1.7% PASS
total/synth/ADD/b0 0.00 0.00 +0.1% PASS
total/synth/ADD/b1 0.00 0.00 -0.1% PASS
total/synth/ADDRESS/a0 0.25 0.22 -11.9% PASS
total/synth/ADDRESS/a1 0.15 0.15 +0.4% PASS
total/synth/AND/b0 0.00 0.00 +0.4% PASS
total/synth/AND/b1 0.00 0.00 +0.3% PASS
total/synth/BYTE/b0 0.00 0.00 -0.2% PASS
total/synth/BYTE/b1 0.00 0.00 +0.4% PASS
total/synth/CALLDATASIZE/a0 0.12 0.12 -1.1% PASS
total/synth/CALLDATASIZE/a1 0.07 0.07 +0.2% PASS
total/synth/CALLER/a0 0.23 0.23 -0.0% PASS
total/synth/CALLER/a1 0.22 0.25 +10.8% PASS
total/synth/CALLVALUE/a0 0.19 0.19 -0.3% PASS
total/synth/CALLVALUE/a1 0.28 0.29 +3.5% PASS
total/synth/CODESIZE/a0 0.13 0.12 -8.6% PASS
total/synth/CODESIZE/a1 0.12 0.12 -0.1% PASS
total/synth/DUP1/d0 0.00 0.00 +0.4% PASS
total/synth/DUP1/d1 0.00 0.00 +0.2% PASS
total/synth/DUP10/d0 0.00 0.00 +0.1% PASS
total/synth/DUP10/d1 0.00 0.00 +0.2% PASS
total/synth/DUP11/d0 0.00 0.00 +0.4% PASS
total/synth/DUP11/d1 0.00 0.00 +0.2% PASS
total/synth/DUP12/d0 0.00 0.00 +0.0% PASS
total/synth/DUP12/d1 0.00 0.00 -0.0% PASS
total/synth/DUP13/d0 0.00 0.00 -0.7% PASS
total/synth/DUP13/d1 0.00 0.00 -0.2% PASS
total/synth/DUP14/d0 0.00 0.00 -0.1% PASS
total/synth/DUP14/d1 0.00 0.00 -0.5% PASS
total/synth/DUP15/d0 0.00 0.00 -0.1% PASS
total/synth/DUP15/d1 0.00 0.00 -0.5% PASS
total/synth/DUP16/d0 0.00 0.00 -0.3% PASS
total/synth/DUP16/d1 0.00 0.00 +0.7% PASS
total/synth/DUP2/d0 0.00 0.00 +0.3% PASS
total/synth/DUP2/d1 0.00 0.00 +0.2% PASS
total/synth/DUP3/d0 0.00 0.00 -0.7% PASS
total/synth/DUP3/d1 0.00 0.00 -0.2% PASS
total/synth/DUP4/d0 0.00 0.00 +0.9% PASS
total/synth/DUP4/d1 0.00 0.00 -0.1% PASS
total/synth/DUP5/d0 0.00 0.00 -0.0% PASS
total/synth/DUP5/d1 0.00 0.00 +0.6% PASS
total/synth/DUP6/d0 0.00 0.00 -0.6% PASS
total/synth/DUP6/d1 0.00 0.00 +0.2% PASS
total/synth/DUP7/d0 0.00 0.00 -0.0% PASS
total/synth/DUP7/d1 0.00 0.00 +0.7% PASS
total/synth/DUP8/d0 0.00 0.00 -0.1% PASS
total/synth/DUP8/d1 0.00 0.00 +0.2% PASS
total/synth/DUP9/d0 0.00 0.00 -0.4% PASS
total/synth/DUP9/d1 0.00 0.00 +0.2% PASS
total/synth/EQ/b0 0.00 0.00 +0.2% PASS
total/synth/EQ/b1 0.00 0.00 +0.6% PASS
total/synth/GAS/a0 0.76 0.76 +0.0% PASS
total/synth/GAS/a1 0.92 0.93 +0.7% PASS
total/synth/GT/b0 0.00 0.00 -0.2% PASS
total/synth/GT/b1 0.00 0.00 +0.5% PASS
total/synth/ISZERO/u0 0.00 0.00 -1.1% PASS
total/synth/JUMPDEST/n0 0.00 0.00 -0.0% PASS
total/synth/LT/b0 0.00 0.00 -0.5% PASS
total/synth/LT/b1 0.00 0.00 +0.1% PASS
total/synth/MSIZE/a0 0.00 0.00 -0.1% PASS
total/synth/MSIZE/a1 0.00 0.00 +0.0% PASS
total/synth/MUL/b0 0.00 0.00 +1.7% PASS
total/synth/MUL/b1 0.00 0.00 +0.1% PASS
total/synth/NOT/u0 0.00 0.00 +0.8% PASS
total/synth/OR/b0 0.00 0.00 -0.1% PASS
total/synth/OR/b1 0.00 0.00 -0.2% PASS
total/synth/PC/a0 0.00 0.00 +0.5% PASS
total/synth/PC/a1 0.00 0.00 +0.2% PASS
total/synth/PUSH1/p0 0.00 0.00 -1.2% PASS
total/synth/PUSH1/p1 0.00 0.00 -0.7% PASS
total/synth/PUSH10/p0 0.00 0.00 -4.3% PASS
total/synth/PUSH10/p1 0.00 0.00 -2.2% PASS
total/synth/PUSH11/p0 0.00 0.00 -0.1% PASS
total/synth/PUSH11/p1 0.00 0.00 +0.9% PASS
total/synth/PUSH12/p0 0.00 0.00 -1.3% PASS
total/synth/PUSH12/p1 0.00 0.00 -4.5% PASS
total/synth/PUSH13/p0 0.00 0.00 +0.5% PASS
total/synth/PUSH13/p1 0.00 0.00 +0.2% PASS
total/synth/PUSH14/p0 0.00 0.00 +3.8% PASS
total/synth/PUSH14/p1 0.00 0.00 +0.5% PASS
total/synth/PUSH15/p0 0.00 0.00 +0.7% PASS
total/synth/PUSH15/p1 0.00 0.00 -3.8% PASS
total/synth/PUSH16/p0 0.00 0.00 +3.2% PASS
total/synth/PUSH16/p1 0.00 0.00 +0.7% PASS
total/synth/PUSH17/p0 0.00 0.00 +2.7% PASS
total/synth/PUSH17/p1 0.00 0.00 +3.4% PASS
total/synth/PUSH18/p0 0.00 0.00 +1.3% PASS
total/synth/PUSH18/p1 0.00 0.00 -3.6% PASS
total/synth/PUSH19/p0 0.00 0.00 +0.2% PASS
total/synth/PUSH19/p1 0.00 0.00 +0.1% PASS
total/synth/PUSH2/p0 0.00 0.00 +0.2% PASS
total/synth/PUSH2/p1 0.00 0.00 -1.3% PASS
total/synth/PUSH20/p0 0.00 0.00 +0.7% PASS
total/synth/PUSH20/p1 0.00 0.00 +1.1% PASS
total/synth/PUSH21/p0 0.00 0.00 -0.8% PASS
total/synth/PUSH21/p1 0.00 0.00 +3.8% PASS
total/synth/PUSH22/p0 2.12 2.17 +2.3% PASS
total/synth/PUSH22/p1 1.74 1.75 +0.6% PASS
total/synth/PUSH23/p0 2.13 2.17 +2.1% PASS
total/synth/PUSH23/p1 2.22 2.26 +1.4% PASS
total/synth/PUSH24/p0 1.32 1.33 +1.0% PASS
total/synth/PUSH24/p1 2.29 2.27 -1.1% PASS
total/synth/PUSH25/p0 2.12 2.18 +2.6% PASS
total/synth/PUSH25/p1 1.72 1.76 +2.2% PASS
total/synth/PUSH26/p0 2.12 2.11 -0.4% PASS
total/synth/PUSH26/p1 2.24 2.20 -1.9% PASS
total/synth/PUSH27/p0 1.32 1.32 +0.5% PASS
total/synth/PUSH27/p1 2.24 2.27 +1.4% PASS
total/synth/PUSH28/p0 2.13 2.14 +0.5% PASS
total/synth/PUSH28/p1 1.75 1.66 -5.0% PASS
total/synth/PUSH29/p0 2.13 2.18 +2.4% PASS
total/synth/PUSH29/p1 2.18 2.25 +3.0% PASS
total/synth/PUSH3/p0 0.00 0.00 -0.2% PASS
total/synth/PUSH3/p1 0.00 0.00 -0.7% PASS
total/synth/PUSH30/p0 1.44 1.53 +6.8% PASS
total/synth/PUSH30/p1 2.19 2.22 +1.4% PASS
total/synth/PUSH31/p0 2.13 2.12 -0.7% PASS
total/synth/PUSH31/p1 1.84 1.74 -5.1% PASS
total/synth/PUSH32/p0 2.20 2.14 -3.0% PASS
total/synth/PUSH32/p1 2.22 2.25 +1.7% PASS
total/synth/PUSH4/p0 0.00 0.00 +1.1% PASS
total/synth/PUSH4/p1 0.00 0.00 -0.5% PASS
total/synth/PUSH5/p0 0.00 0.00 +3.0% PASS
total/synth/PUSH5/p1 0.00 0.00 -0.8% PASS
total/synth/PUSH6/p0 0.00 0.00 +0.7% PASS
total/synth/PUSH6/p1 0.00 0.00 +3.3% PASS
total/synth/PUSH7/p0 0.00 0.00 -0.3% PASS
total/synth/PUSH7/p1 0.00 0.00 +2.1% PASS
total/synth/PUSH8/p0 0.00 0.00 +3.4% PASS
total/synth/PUSH8/p1 0.00 0.00 +3.9% PASS
total/synth/PUSH9/p0 0.00 0.00 +1.7% PASS
total/synth/PUSH9/p1 0.00 0.00 +3.7% PASS
total/synth/RETURNDATASIZE/a0 0.03 0.03 -0.3% PASS
total/synth/RETURNDATASIZE/a1 0.06 0.06 +2.2% PASS
total/synth/SAR/b0 0.00 0.00 -0.7% PASS
total/synth/SAR/b1 0.00 0.00 +0.5% PASS
total/synth/SGT/b0 0.00 0.00 +1.3% PASS
total/synth/SGT/b1 0.00 0.00 +0.7% PASS
total/synth/SHL/b0 0.00 0.00 -0.2% PASS
total/synth/SHL/b1 0.00 0.00 -0.1% PASS
total/synth/SHR/b0 0.00 0.00 -0.5% PASS
total/synth/SHR/b1 0.00 0.00 +0.1% PASS
total/synth/SIGNEXTEND/b0 0.00 0.00 -0.1% PASS
total/synth/SIGNEXTEND/b1 0.00 0.00 +0.1% PASS
total/synth/SLT/b0 0.00 0.00 -0.2% PASS
total/synth/SLT/b1 0.00 0.00 -0.4% PASS
total/synth/SUB/b0 0.00 0.00 -0.8% PASS
total/synth/SUB/b1 0.00 0.00 -0.6% PASS
total/synth/SWAP1/s0 0.00 0.00 +0.5% PASS
total/synth/SWAP10/s0 0.00 0.00 -0.6% PASS
total/synth/SWAP11/s0 0.00 0.00 +0.1% PASS
total/synth/SWAP12/s0 0.00 0.00 -0.9% PASS
total/synth/SWAP13/s0 0.00 0.00 +0.1% PASS
total/synth/SWAP14/s0 0.00 0.00 +0.7% PASS
total/synth/SWAP15/s0 0.00 0.00 +0.2% PASS
total/synth/SWAP16/s0 0.00 0.00 -0.4% PASS
total/synth/SWAP2/s0 0.00 0.00 -0.1% PASS
total/synth/SWAP3/s0 0.00 0.00 -0.3% PASS
total/synth/SWAP4/s0 0.00 0.00 -0.1% PASS
total/synth/SWAP5/s0 0.00 0.00 +0.6% PASS
total/synth/SWAP6/s0 0.00 0.00 -0.1% PASS
total/synth/SWAP7/s0 0.00 0.00 +0.0% PASS
total/synth/SWAP8/s0 0.00 0.00 +0.4% PASS
total/synth/SWAP9/s0 0.00 0.00 +1.1% PASS
total/synth/XOR/b0 0.00 0.00 -0.0% PASS
total/synth/XOR/b1 0.00 0.00 +0.7% PASS
total/synth/loop_v1 11.51 11.55 +0.3% PASS
total/synth/loop_v2 11.37 11.73 +3.2% PASS

Summary: 194 benchmarks, 0 regressions


… or trivial exponent

handleExp emitted the full inline square-and-multiply loop for every EXP whose
operands were not both constant. Add three semantics- and EIP-160-gas-faithful
fast paths:

- EXP(base, 0) -> 1 (dynamic base, constant exponent 0; dynamic gas 0)
- EXP(base, 1) -> base (dynamic base, constant exponent 1; dynamic gas GasPerByte)
- EXP(2^k, x) -> (k*x >= 256) ? 0 : 1 << (k*x) for any constant power-of-two base
  with a dynamic exponent. For k == 1 this is 1 << x, where handleShift<BO_SHL>
  already wraps shift >= 256 to 0 and k*x cannot overflow. For k >= 2 the product
  k*x wraps modulo 2^256 for large x, so the result is guarded by an explicit
  x >= ceil(256/k) -> 0 test rather than handleShift's own >= 256 check (which
  would see the wrapped product); below that threshold k*x is exact and < 256.
  This covers the 256**x (k=8) storage-packing idiom. The EIP-160 dynamic gas
  depends only on the exponent and is charged by the unchanged general-path
  machinery, so gas is byte-for-byte identical.

Correctness was checked during development with a differential harness (multipass
output vs the interpreter and an independent 1<<x table, across power-of-two
bases, threshold-straddling exponents, the overflow-guard case, and EIP-160 gas
deltas); regression coverage relies on the EEST state-test corpus and the
multipass unit suite.

EXP is ~0.12% of opcodes on a mainnet sample and most is already double-constant-
folded, so the aggregate runtime effect stays below benchmark noise; the per-hit
win (one shift+select vs a square-and-multiply loop) is large on the 256**x sites
this now covers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@abmcar abmcar force-pushed the opt/evm-exp-strength-reduction branch from 562875a to 8f11147 Compare June 25, 2026 01:58
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.

2 participants