Skip to content

fix(compiler): materialize ADDMOD operand limbs before fast/slow branch#544

Merged
zoowii merged 1 commit into
DTVMStack:mainfrom
abmcar:fix/evm-addmod-cross-block-materialization
Jun 26, 2026
Merged

fix(compiler): materialize ADDMOD operand limbs before fast/slow branch#544
zoowii merged 1 commit into
DTVMStack:mainfrom
abmcar:fix/evm-addmod-cross-block-materialization

Conversation

@abmcar

@abmcar abmcar commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

ADDMOD miscompiles in multipass when an operand is a raw fast/slow tree; this materializes the operand limbs before the branch so each limb is defined in the dominating block.

Problem

handleAddMod extracts the raw tree IR of its Augend/Addend/Modulus limbs and then branches into FastBB/SlowBB. The low limbs are first referenced inside those two non-dominating successor blocks. The CgIR lowering memoizes each tree node's virtual register in a function-global map that is never cleared between blocks, so a shared limb lowered in the first-walked branch leaves the sibling path reading a virtual register defined in a block that does not dominate it — undefined on that execution path. The result is a silent multipass miscompile (wrong ADDMOD result, occasionally a crash).

This is the same cross-block materialization hazard fixed for handleDivModGeneral in #540. handleAddMod has the same structure but never received the #540 fix on the ADDMOD path.

Trigger

The hazard surfaces when an ADDMOD operand is the raw tree of a preceding inline fast/slow op (e.g. a MOD result). Minimal reproducer:

ORIGIN DUP1 DUP1 PUSH0 MOD ADDMOD

The interpreter returns 0; multipass returns an incorrect result before this fix.

Fix

Materialize all operand limbs with protectUnsafeValue before the branch, matching the #540 pattern. This forces immediate evaluation so each limb's virtual register is defined in the dominating block.

Tests

Adds EVMRegressionTest.AddModCrossBlockMaterialization, a differential interpreter-vs-multipass regression test over MOD-fed and DIV-fed ADDMOD inputs.

Validated locally: the new regression test passes; multipass evmone-unittests (223) and evmone-statetest -k fork_Cancun (2723) pass with the fix; tools/format.sh check clean.

Copilot AI review requested due to automatic review settings June 15, 2026 12:52

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.

Fixes a multipass miscompile in the EVM MIR compiler where ADDMOD operands could remain as raw tree IR across a fast/slow branch, leading to undefined virtual-register uses on one successor path.

Changes:

  • Materialize (protectUnsafeValue) all ADDMOD operand limbs before branching in handleAddMod.
  • Add regression tests that compare interpreter vs multipass output for ADDMOD fed by prior inline fast/slow ops (e.g., MOD, DIV).

Reviewed changes

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

File Description
src/compiler/evm_frontend/evm_mir_compiler.cpp Forces limb materialization before the fast/slow BrIf in handleAddMod to prevent cross-block hazards.
src/tests/evm_interp_tests.cpp Adds regression tests ensuring multipass output matches interpreter for crafted ADDMOD sequences.

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

Comment thread src/tests/evm_interp_tests.cpp Outdated
Comment thread src/tests/evm_interp_tests.cpp Outdated
Comment thread src/compiler/evm_frontend/evm_mir_compiler.cpp Outdated
@github-actions

github-actions Bot commented Jun 15, 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.84 3.78 -1.6% PASS
total/main/blake2b_huff/empty 0.06 0.06 +1.7% PASS
total/main/blake2b_shifts/8415nulls 20.63 23.40 +13.4% PASS
total/main/sha1_divs/5311 11.70 11.93 +2.0% PASS
total/main/sha1_divs/empty 0.15 0.15 +0.3% PASS
total/main/sha1_shifts/5311 9.31 9.46 +1.6% PASS
total/main/sha1_shifts/empty 0.08 0.08 -0.7% PASS
total/main/snailtracer/benchmark 108.36 107.73 -0.6% PASS
total/main/structarray_alloc/nfts_rank 1.38 1.47 +6.7% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 +2.2% PASS
total/main/swap_math/received 0.01 0.01 +0.2% PASS
total/main/swap_math/spent 0.01 0.01 +1.8% PASS
total/main/weierstrudel/1 0.40 0.39 -0.7% PASS
total/main/weierstrudel/15 4.33 4.33 +0.0% PASS
total/micro/JUMPDEST_n0/empty 2.86 2.93 +2.1% PASS
total/micro/jump_around/empty 0.12 0.12 +0.7% PASS
total/micro/loop_with_many_jumpdests/empty 64.40 63.76 -1.0% PASS
total/micro/memory_grow_mload/by1 0.22 0.23 +0.4% PASS
total/micro/memory_grow_mload/by16 0.24 0.24 -0.0% PASS
total/micro/memory_grow_mload/by32 0.14 0.15 +3.4% PASS
total/micro/memory_grow_mload/nogrow 0.12 0.12 -1.7% PASS
total/micro/memory_grow_mstore/by1 0.24 0.23 -2.7% PASS
total/micro/memory_grow_mstore/by16 0.14 0.14 +2.8% PASS
total/micro/memory_grow_mstore/by32 0.28 0.29 +2.5% PASS
total/micro/memory_grow_mstore/nogrow 0.24 0.22 -5.8% PASS
total/micro/signextend/one 0.28 0.29 +3.2% PASS
total/micro/signextend/zero 0.49 0.49 -1.5% PASS
total/synth/ADD/b0 3.24 3.23 -0.5% PASS
total/synth/ADD/b1 5.85 5.99 +2.5% PASS
total/synth/ADDRESS/a0 6.79 6.61 -2.6% PASS
total/synth/ADDRESS/a1 5.32 5.35 +0.6% PASS
total/synth/AND/b0 2.87 2.88 +0.0% PASS
total/synth/AND/b1 5.38 5.25 -2.4% PASS
total/synth/BYTE/b0 6.06 6.07 +0.2% PASS
total/synth/BYTE/b1 8.85 8.55 -3.4% PASS
total/synth/CALLDATASIZE/a0 5.47 5.50 +0.5% PASS
total/synth/CALLDATASIZE/a1 3.48 3.47 -0.4% PASS
total/synth/CALLER/a0 6.54 6.61 +1.0% PASS
total/synth/CALLER/a1 6.85 6.80 -0.8% PASS
total/synth/CALLVALUE/a0 3.49 3.59 +3.1% PASS
total/synth/CALLVALUE/a1 6.43 6.41 -0.3% PASS
total/synth/CODESIZE/a0 7.00 6.75 -3.4% PASS
total/synth/CODESIZE/a1 6.31 6.91 +9.6% PASS
total/synth/DUP1/d0 2.06 1.97 -4.2% PASS
total/synth/DUP1/d1 2.09 2.05 -1.8% PASS
total/synth/DUP10/d0 1.98 2.01 +1.7% PASS
total/synth/DUP10/d1 2.29 2.22 -3.3% PASS
total/synth/DUP11/d0 1.23 1.23 -0.0% PASS
total/synth/DUP11/d1 2.09 2.08 -0.5% PASS
total/synth/DUP12/d0 1.98 2.02 +1.9% PASS
total/synth/DUP12/d1 1.65 1.58 -4.3% PASS
total/synth/DUP13/d0 1.95 1.96 +0.7% PASS
total/synth/DUP13/d1 2.14 2.14 +0.0% PASS
total/synth/DUP14/d0 1.12 1.23 +10.1% PASS
total/synth/DUP14/d1 2.18 2.13 -2.0% PASS
total/synth/DUP15/d0 1.98 2.00 +1.1% PASS
total/synth/DUP15/d1 1.45 1.66 +14.4% PASS
total/synth/DUP16/d0 1.97 2.03 +3.3% PASS
total/synth/DUP16/d1 2.12 2.24 +5.8% PASS
total/synth/DUP2/d0 1.23 1.11 -9.8% PASS
total/synth/DUP2/d1 2.16 2.14 -1.1% PASS
total/synth/DUP3/d0 2.06 2.03 -1.4% PASS
total/synth/DUP3/d1 1.66 1.65 -0.1% PASS
total/synth/DUP4/d0 1.99 1.94 -2.8% PASS
total/synth/DUP4/d1 2.20 2.00 -8.8% PASS
total/synth/DUP5/d0 1.23 1.23 +0.1% PASS
total/synth/DUP5/d1 2.14 2.19 +2.4% PASS
total/synth/DUP6/d0 1.98 1.94 -2.0% PASS
total/synth/DUP6/d1 1.45 1.65 +13.6% PASS
total/synth/DUP7/d0 1.98 1.98 +0.1% PASS
total/synth/DUP7/d1 2.08 2.08 +0.2% PASS
total/synth/DUP8/d0 1.11 1.23 +11.4% PASS
total/synth/DUP8/d1 2.27 2.13 -6.1% PASS
total/synth/DUP9/d0 2.03 1.97 -2.9% PASS
total/synth/DUP9/d1 1.66 1.66 -0.1% PASS
total/synth/EQ/b0 6.04 6.07 +0.5% PASS
total/synth/EQ/b1 6.27 6.33 +1.0% PASS
total/synth/GAS/a0 3.93 3.94 +0.3% PASS
total/synth/GAS/a1 7.21 7.50 +4.1% PASS
total/synth/GT/b0 6.53 6.34 -2.9% PASS
total/synth/GT/b1 6.56 6.55 -0.1% PASS
total/synth/ISZERO/u0 10.12 10.06 -0.6% PASS
total/synth/JUMPDEST/n0 2.89 2.86 -0.9% PASS
total/synth/LT/b0 6.35 6.35 -0.1% PASS
total/synth/LT/b1 5.43 5.44 +0.0% PASS
total/synth/MSIZE/a0 6.01 5.92 -1.5% PASS
total/synth/MSIZE/a1 6.33 6.22 -1.7% PASS
total/synth/MUL/b0 7.82 7.79 -0.4% PASS
total/synth/MUL/b1 5.93 5.92 -0.2% PASS
total/synth/NOT/u0 8.42 7.87 -6.5% PASS
total/synth/OR/b0 5.27 5.09 -3.3% PASS
total/synth/OR/b1 3.70 3.41 -7.9% PASS
total/synth/PC/a0 5.39 5.41 +0.2% PASS
total/synth/PC/a1 3.68 3.67 -0.3% PASS
total/synth/PUSH1/p0 2.27 2.20 -3.3% PASS
total/synth/PUSH1/p1 1.74 1.74 +0.2% PASS
total/synth/PUSH10/p0 2.27 2.31 +1.9% PASS
total/synth/PUSH10/p1 1.76 1.77 +0.7% PASS
total/synth/PUSH11/p0 2.35 2.32 -1.0% PASS
total/synth/PUSH11/p1 2.57 2.53 -1.3% PASS
total/synth/PUSH12/p0 1.32 1.32 -0.4% PASS
total/synth/PUSH12/p1 2.44 2.51 +2.9% PASS
total/synth/PUSH13/p0 2.28 2.36 +3.4% PASS
total/synth/PUSH13/p1 1.75 1.72 -1.9% PASS
total/synth/PUSH14/p0 2.38 2.56 +7.5% PASS
total/synth/PUSH14/p1 2.44 2.49 +2.1% PASS
total/synth/PUSH15/p0 1.32 1.32 +0.1% PASS
total/synth/PUSH15/p1 2.67 2.59 -2.7% PASS
total/synth/PUSH16/p0 2.30 2.26 -1.6% PASS
total/synth/PUSH16/p1 1.54 1.75 +13.6% PASS
total/synth/PUSH17/p0 2.27 2.43 +7.4% PASS
total/synth/PUSH17/p1 2.38 2.41 +1.6% PASS
total/synth/PUSH18/p0 1.32 1.32 -0.2% PASS
total/synth/PUSH18/p1 2.46 2.33 -5.5% PASS
total/synth/PUSH19/p0 2.31 2.24 -3.0% PASS
total/synth/PUSH19/p1 1.78 1.56 -12.2% PASS
total/synth/PUSH2/p0 2.21 2.27 +2.7% PASS
total/synth/PUSH2/p1 2.36 2.44 +3.4% PASS
total/synth/PUSH20/p0 2.50 2.35 -5.9% PASS
total/synth/PUSH20/p1 2.34 2.35 +0.6% PASS
total/synth/PUSH21/p0 1.34 1.30 -3.2% PASS
total/synth/PUSH21/p1 2.40 2.45 +2.4% PASS
total/synth/PUSH22/p0 2.27 2.21 -2.5% PASS
total/synth/PUSH22/p1 1.79 1.77 -0.8% PASS
total/synth/PUSH23/p0 2.37 2.27 -4.1% PASS
total/synth/PUSH23/p1 2.51 2.45 -2.2% PASS
total/synth/PUSH24/p0 1.32 1.33 +0.8% PASS
total/synth/PUSH24/p1 2.39 2.49 +4.2% PASS
total/synth/PUSH25/p0 2.39 2.23 -6.7% PASS
total/synth/PUSH25/p1 1.76 1.75 -0.1% PASS
total/synth/PUSH26/p0 2.30 2.38 +3.9% PASS
total/synth/PUSH26/p1 2.48 2.63 +5.7% PASS
total/synth/PUSH27/p0 1.32 1.34 +1.1% PASS
total/synth/PUSH27/p1 2.51 2.40 -4.5% PASS
total/synth/PUSH28/p0 2.26 2.25 -0.3% PASS
total/synth/PUSH28/p1 1.58 1.77 +12.0% PASS
total/synth/PUSH29/p0 2.25 2.40 +6.4% PASS
total/synth/PUSH29/p1 2.42 2.40 -1.1% PASS
total/synth/PUSH3/p0 1.35 1.31 -3.3% PASS
total/synth/PUSH3/p1 2.35 2.48 +5.6% PASS
total/synth/PUSH30/p0 1.49 1.49 +0.4% PASS
total/synth/PUSH30/p1 2.63 2.65 +0.7% PASS
total/synth/PUSH31/p0 2.22 2.44 +9.9% PASS
total/synth/PUSH31/p1 1.86 1.86 +0.0% PASS
total/synth/PUSH32/p0 2.19 2.31 +5.5% PASS
total/synth/PUSH32/p1 2.37 2.41 +1.8% PASS
total/synth/PUSH4/p0 2.23 2.21 -0.9% PASS
total/synth/PUSH4/p1 1.75 1.73 -1.2% PASS
total/synth/PUSH5/p0 2.32 2.33 +0.4% PASS
total/synth/PUSH5/p1 2.33 2.63 +12.7% PASS
total/synth/PUSH6/p0 1.34 1.32 -1.7% PASS
total/synth/PUSH6/p1 2.38 2.59 +8.9% PASS
total/synth/PUSH7/p0 2.18 2.38 +9.2% PASS
total/synth/PUSH7/p1 1.79 1.76 -1.6% PASS
total/synth/PUSH8/p0 2.24 2.17 -2.9% PASS
total/synth/PUSH8/p1 2.45 2.50 +2.1% PASS
total/synth/PUSH9/p0 1.32 1.30 -1.9% PASS
total/synth/PUSH9/p1 2.42 2.43 +0.3% PASS
total/synth/RETURNDATASIZE/a0 3.57 3.80 +6.4% PASS
total/synth/RETURNDATASIZE/a1 6.52 6.74 +3.3% PASS
total/synth/SAR/b0 3.94 3.94 -0.0% PASS
total/synth/SAR/b1 7.66 7.26 -5.2% PASS
total/synth/SGT/b0 5.71 5.73 +0.4% PASS
total/synth/SGT/b1 4.15 4.13 -0.3% PASS
total/synth/SHL/b0 7.05 7.22 +2.4% PASS
total/synth/SHL/b1 3.65 3.65 +0.1% PASS
total/synth/SHR/b0 7.04 6.86 -2.5% PASS
total/synth/SHR/b1 6.36 6.13 -3.6% PASS
total/synth/SIGNEXTEND/b0 3.37 3.36 -0.2% PASS
total/synth/SIGNEXTEND/b1 6.66 6.37 -4.4% PASS
total/synth/SLT/b0 4.30 4.30 +0.1% PASS
total/synth/SLT/b1 5.63 5.82 +3.4% PASS
total/synth/SUB/b0 5.74 5.93 +3.4% PASS
total/synth/SUB/b1 6.17 5.98 -3.0% PASS
total/synth/SWAP1/s0 3.53 3.52 -0.0% PASS
total/synth/SWAP10/s0 3.54 3.54 -0.1% PASS
total/synth/SWAP11/s0 3.46 3.50 +1.1% PASS
total/synth/SWAP12/s0 3.49 3.49 +0.2% PASS
total/synth/SWAP13/s0 3.54 3.54 -0.1% PASS
total/synth/SWAP14/s0 3.52 3.54 +0.7% PASS
total/synth/SWAP15/s0 3.56 3.59 +0.9% PASS
total/synth/SWAP16/s0 3.55 3.55 -0.0% PASS
total/synth/SWAP2/s0 3.49 3.43 -1.6% PASS
total/synth/SWAP3/s0 3.50 3.46 -1.2% PASS
total/synth/SWAP4/s0 3.53 3.53 -0.1% PASS
total/synth/SWAP5/s0 3.47 3.41 -1.7% PASS
total/synth/SWAP6/s0 3.47 3.45 -0.4% PASS
total/synth/SWAP7/s0 3.54 3.53 -0.2% PASS
total/synth/SWAP8/s0 3.77 3.44 -8.6% PASS
total/synth/SWAP9/s0 3.46 3.51 +1.5% PASS
total/synth/XOR/b0 5.23 5.20 -0.5% PASS
total/synth/XOR/b1 5.23 5.26 +0.5% PASS
total/synth/loop_v1 12.11 11.99 -1.0% PASS
total/synth/loop_v2 12.70 12.64 -0.1% 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.37 2.30 -2.9% PASS
total/main/blake2b_huff/empty 0.04 0.04 -7.6% PASS
total/main/blake2b_shifts/8415nulls 20.51 20.48 -0.1% PASS
total/main/sha1_divs/5311 12.15 11.96 -1.6% PASS
total/main/sha1_divs/empty 0.14 0.14 +0.4% PASS
total/main/sha1_shifts/5311 9.13 8.56 -3.8% PASS
total/main/sha1_shifts/empty 0.08 0.08 +0.4% PASS
total/main/snailtracer/benchmark 111.09 106.74 -3.9% PASS
total/main/structarray_alloc/nfts_rank 1.38 1.38 -0.6% PASS
total/main/swap_math/insufficient_liquidity 0.00 0.00 -0.1% PASS
total/main/swap_math/received 0.01 0.01 -0.9% PASS
total/main/swap_math/spent 0.01 0.01 -0.8% PASS
total/main/weierstrudel/1 0.39 0.38 -2.5% PASS
total/main/weierstrudel/15 4.22 4.24 +0.5% PASS
total/micro/JUMPDEST_n0/empty 0.00 0.00 -0.3% PASS
total/micro/jump_around/empty 0.07 0.07 -0.1% PASS
total/micro/loop_with_many_jumpdests/empty 0.01 0.01 -1.2% PASS
total/micro/memory_grow_mload/by1 0.02 0.02 -2.0% PASS
total/micro/memory_grow_mload/by16 0.02 0.02 -16.9% PASS
total/micro/memory_grow_mload/by32 0.01 0.01 +0.0% PASS
total/micro/memory_grow_mload/nogrow 0.01 0.01 +0.3% PASS
total/micro/memory_grow_mstore/by1 0.13 0.13 +0.4% PASS
total/micro/memory_grow_mstore/by16 0.08 0.08 -1.1% PASS
total/micro/memory_grow_mstore/by32 0.17 0.17 -0.5% PASS
total/micro/memory_grow_mstore/nogrow 0.12 0.12 -0.7% PASS
total/micro/signextend/one 0.08 0.08 +2.2% PASS
total/micro/signextend/zero 0.19 0.19 +0.2% PASS
total/synth/ADD/b0 0.00 0.00 -0.2% PASS
total/synth/ADD/b1 0.00 0.00 +0.3% PASS
total/synth/ADDRESS/a0 0.23 0.23 -0.8% PASS
total/synth/ADDRESS/a1 0.15 0.15 +0.4% PASS
total/synth/AND/b0 0.00 0.00 +0.1% PASS
total/synth/AND/b1 0.00 0.00 +0.2% PASS
total/synth/BYTE/b0 0.00 0.00 -0.1% PASS
total/synth/BYTE/b1 0.00 0.00 -0.0% PASS
total/synth/CALLDATASIZE/a0 0.12 0.12 -2.7% PASS
total/synth/CALLDATASIZE/a1 0.07 0.07 -0.2% PASS
total/synth/CALLER/a0 0.22 0.22 -0.6% PASS
total/synth/CALLER/a1 0.22 0.23 +3.8% PASS
total/synth/CALLVALUE/a0 0.19 0.19 +0.3% PASS
total/synth/CALLVALUE/a1 0.32 0.30 -5.7% PASS
total/synth/CODESIZE/a0 0.12 0.12 +0.6% PASS
total/synth/CODESIZE/a1 0.12 0.12 -2.1% PASS
total/synth/DUP1/d0 0.00 0.00 -0.1% PASS
total/synth/DUP1/d1 0.00 0.00 +0.5% PASS
total/synth/DUP10/d0 0.00 0.00 +1.3% PASS
total/synth/DUP10/d1 0.00 0.00 +0.1% PASS
total/synth/DUP11/d0 0.00 0.00 +0.3% PASS
total/synth/DUP11/d1 0.00 0.00 +0.2% PASS
total/synth/DUP12/d0 0.00 0.00 +2.4% PASS
total/synth/DUP12/d1 0.00 0.00 -0.2% PASS
total/synth/DUP13/d0 0.00 0.00 +0.5% PASS
total/synth/DUP13/d1 0.00 0.00 +0.5% PASS
total/synth/DUP14/d0 0.00 0.00 -0.1% PASS
total/synth/DUP14/d1 0.00 0.00 +0.3% PASS
total/synth/DUP15/d0 0.00 0.00 -0.3% PASS
total/synth/DUP15/d1 0.00 0.00 -0.0% PASS
total/synth/DUP16/d0 0.00 0.00 -0.2% PASS
total/synth/DUP16/d1 0.00 0.00 +0.4% PASS
total/synth/DUP2/d0 0.00 0.00 +0.6% PASS
total/synth/DUP2/d1 0.00 0.00 +0.3% PASS
total/synth/DUP3/d0 0.00 0.00 +0.2% PASS
total/synth/DUP3/d1 0.00 0.00 +0.1% PASS
total/synth/DUP4/d0 0.00 0.00 -0.1% PASS
total/synth/DUP4/d1 0.00 0.00 -0.2% PASS
total/synth/DUP5/d0 0.00 0.00 -0.1% PASS
total/synth/DUP5/d1 0.00 0.00 -1.1% PASS
total/synth/DUP6/d0 0.00 0.00 -0.3% PASS
total/synth/DUP6/d1 0.00 0.00 +0.5% PASS
total/synth/DUP7/d0 0.00 0.00 -0.7% PASS
total/synth/DUP7/d1 0.00 0.00 +1.4% PASS
total/synth/DUP8/d0 0.00 0.00 +0.2% PASS
total/synth/DUP8/d1 0.00 0.00 +0.3% PASS
total/synth/DUP9/d0 0.00 0.00 +0.6% PASS
total/synth/DUP9/d1 0.00 0.00 -0.3% PASS
total/synth/EQ/b0 0.00 0.00 +0.2% PASS
total/synth/EQ/b1 0.00 0.00 +0.4% PASS
total/synth/GAS/a0 0.76 0.77 +0.3% PASS
total/synth/GAS/a1 0.90 0.93 +3.6% PASS
total/synth/GT/b0 0.00 0.00 +0.4% PASS
total/synth/GT/b1 0.00 0.00 -0.5% PASS
total/synth/ISZERO/u0 0.00 0.00 +3.0% PASS
total/synth/JUMPDEST/n0 0.00 0.00 -0.7% PASS
total/synth/LT/b0 0.00 0.00 +0.1% PASS
total/synth/LT/b1 0.00 0.00 -0.6% PASS
total/synth/MSIZE/a0 0.00 0.00 -2.0% PASS
total/synth/MSIZE/a1 0.00 0.00 +0.6% PASS
total/synth/MUL/b0 0.00 0.00 +0.1% PASS
total/synth/MUL/b1 0.00 0.00 -0.1% PASS
total/synth/NOT/u0 0.00 0.00 -0.1% PASS
total/synth/OR/b0 0.00 0.00 +0.2% PASS
total/synth/OR/b1 0.00 0.00 -0.8% PASS
total/synth/PC/a0 0.00 0.00 +0.7% PASS
total/synth/PC/a1 0.00 0.00 -0.1% PASS
total/synth/PUSH1/p0 0.00 0.00 -0.1% PASS
total/synth/PUSH1/p1 0.00 0.00 -1.1% PASS
total/synth/PUSH10/p0 0.00 0.00 +3.0% PASS
total/synth/PUSH10/p1 0.00 0.00 -2.4% PASS
total/synth/PUSH11/p0 0.00 0.00 +4.6% PASS
total/synth/PUSH11/p1 0.00 0.00 +7.0% PASS
total/synth/PUSH12/p0 0.00 0.00 +1.5% PASS
total/synth/PUSH12/p1 0.00 0.00 +3.6% PASS
total/synth/PUSH13/p0 0.00 0.00 -0.3% PASS
total/synth/PUSH13/p1 0.00 0.00 -0.8% PASS
total/synth/PUSH14/p0 0.00 0.00 -1.2% PASS
total/synth/PUSH14/p1 0.00 0.00 +2.4% PASS
total/synth/PUSH15/p0 0.00 0.00 -3.1% PASS
total/synth/PUSH15/p1 0.00 0.00 +1.0% PASS
total/synth/PUSH16/p0 0.00 0.00 -1.7% PASS
total/synth/PUSH16/p1 0.00 0.00 -0.5% PASS
total/synth/PUSH17/p0 0.00 0.00 +0.5% PASS
total/synth/PUSH17/p1 0.00 0.00 -1.1% PASS
total/synth/PUSH18/p0 0.00 0.00 -0.7% PASS
total/synth/PUSH18/p1 0.00 0.00 +2.4% PASS
total/synth/PUSH19/p0 0.00 0.00 +6.5% PASS
total/synth/PUSH19/p1 0.00 0.00 -0.3% PASS
total/synth/PUSH2/p0 0.00 0.00 +1.2% PASS
total/synth/PUSH2/p1 0.00 0.00 -1.3% PASS
total/synth/PUSH20/p0 0.00 0.00 +2.3% PASS
total/synth/PUSH20/p1 0.00 0.00 +0.7% PASS
total/synth/PUSH21/p0 0.00 0.00 +3.0% PASS
total/synth/PUSH21/p1 0.00 0.00 +1.3% PASS
total/synth/PUSH22/p0 2.16 2.15 +0.8% PASS
total/synth/PUSH22/p1 1.54 1.55 +1.0% PASS
total/synth/PUSH23/p0 2.12 2.14 +1.2% PASS
total/synth/PUSH23/p1 2.31 2.24 -3.3% PASS
total/synth/PUSH24/p0 1.32 1.32 -0.2% PASS
total/synth/PUSH24/p1 2.28 2.22 -2.7% PASS
total/synth/PUSH25/p0 2.12 2.14 +1.2% PASS
total/synth/PUSH25/p1 1.54 1.56 +1.4% PASS
total/synth/PUSH26/p0 2.13 2.21 +3.9% PASS
total/synth/PUSH26/p1 2.24 2.20 -1.7% PASS
total/synth/PUSH27/p0 1.33 1.33 -0.5% PASS
total/synth/PUSH27/p1 2.18 2.16 -1.1% PASS
total/synth/PUSH28/p0 2.14 2.17 +1.7% PASS
total/synth/PUSH28/p1 1.56 1.59 +1.9% PASS
total/synth/PUSH29/p0 2.12 2.15 +1.5% PASS
total/synth/PUSH29/p1 2.15 2.22 +3.0% PASS
total/synth/PUSH3/p0 0.00 0.00 -0.9% PASS
total/synth/PUSH3/p1 0.00 0.00 -1.1% PASS
total/synth/PUSH30/p0 1.47 1.45 -1.4% PASS
total/synth/PUSH30/p1 2.21 2.25 +1.9% PASS
total/synth/PUSH31/p0 2.12 2.13 +0.7% PASS
total/synth/PUSH31/p1 1.71 1.73 +0.8% PASS
total/synth/PUSH32/p0 2.21 2.11 -4.4% PASS
total/synth/PUSH32/p1 2.17 2.23 +2.8% PASS
total/synth/PUSH4/p0 0.00 0.00 +0.9% PASS
total/synth/PUSH4/p1 0.00 0.00 -0.8% PASS
total/synth/PUSH5/p0 0.00 0.00 +0.5% PASS
total/synth/PUSH5/p1 0.00 0.00 +0.2% PASS
total/synth/PUSH6/p0 0.00 0.00 +1.4% PASS
total/synth/PUSH6/p1 0.00 0.00 +3.8% PASS
total/synth/PUSH7/p0 0.00 0.00 +1.1% PASS
total/synth/PUSH7/p1 0.00 0.00 -2.4% PASS
total/synth/PUSH8/p0 0.00 0.00 +0.6% PASS
total/synth/PUSH8/p1 0.00 0.00 +3.6% PASS
total/synth/PUSH9/p0 0.00 0.00 +0.8% PASS
total/synth/PUSH9/p1 0.00 0.00 +2.3% PASS
total/synth/RETURNDATASIZE/a0 0.03 0.03 -0.1% PASS
total/synth/RETURNDATASIZE/a1 0.06 0.06 +2.9% PASS
total/synth/SAR/b0 0.00 0.00 +0.0% PASS
total/synth/SAR/b1 0.00 0.00 -0.9% PASS
total/synth/SGT/b0 0.00 0.00 +0.8% PASS
total/synth/SGT/b1 0.00 0.00 -0.3% PASS
total/synth/SHL/b0 0.00 0.00 +0.1% PASS
total/synth/SHL/b1 0.00 0.00 -0.0% PASS
total/synth/SHR/b0 0.00 0.00 +1.2% PASS
total/synth/SHR/b1 0.00 0.00 +0.5% 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.1% PASS
total/synth/SLT/b1 0.00 0.00 -1.4% PASS
total/synth/SUB/b0 0.00 0.00 +0.6% PASS
total/synth/SUB/b1 0.00 0.00 +0.2% PASS
total/synth/SWAP1/s0 0.00 0.00 -0.4% PASS
total/synth/SWAP10/s0 0.00 0.00 -0.5% PASS
total/synth/SWAP11/s0 0.00 0.00 +0.3% PASS
total/synth/SWAP12/s0 0.00 0.00 +0.7% PASS
total/synth/SWAP13/s0 0.00 0.00 +1.5% PASS
total/synth/SWAP14/s0 0.00 0.00 +0.3% PASS
total/synth/SWAP15/s0 0.00 0.00 -0.4% PASS
total/synth/SWAP16/s0 0.00 0.00 -1.4% PASS
total/synth/SWAP2/s0 0.00 0.00 +0.2% PASS
total/synth/SWAP3/s0 0.00 0.00 +0.2% PASS
total/synth/SWAP4/s0 0.00 0.00 -0.3% PASS
total/synth/SWAP5/s0 0.00 0.00 +1.3% PASS
total/synth/SWAP6/s0 0.00 0.00 +0.9% PASS
total/synth/SWAP7/s0 0.00 0.00 +0.1% PASS
total/synth/SWAP8/s0 0.00 0.00 +0.3% PASS
total/synth/SWAP9/s0 0.00 0.00 +0.7% PASS
total/synth/XOR/b0 0.00 0.00 +0.3% PASS
total/synth/XOR/b1 0.00 0.00 +2.5% PASS
total/synth/loop_v1 11.64 11.34 -2.6% PASS
total/synth/loop_v2 12.43 11.49 -7.6% PASS

Summary: 194 benchmarks, 0 regressions


handleAddMod extracts the raw tree IR of its Augend/Addend/Modulus limbs
and then branches into FastBB/SlowBB. The low limbs are first referenced
inside those two non-dominating successor blocks, so the CgIR lowering can
place a shared computation into only one branch, leaving the sibling path
with an undefined virtual register -- a silent multipass miscompile.

This is the same cross-block hazard fixed for handleDivModGeneral in DTVMStack#540;
handleAddMod is its untwinned sibling. It surfaces when an ADDMOD operand
is the raw tree of a preceding inline fast/slow op (e.g. a MOD result):
ORIGIN DUP1 DUP1 PUSH0 MOD ADDMOD returns 0 in the interpreter but garbage
in multipass before this fix.

Fix: protectUnsafeValue all operand limbs before the branch, matching the
DTVMStack#540 pattern.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@abmcar abmcar force-pushed the fix/evm-addmod-cross-block-materialization branch from 9eb47d6 to 0be4d8d Compare June 25, 2026 03:52
@zoowii zoowii merged commit f042d49 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