Skip to content

perf(vm): add peephole pass to elide dead Load; Pop pairs ✂️ - #163

Merged
timfennis merged 3 commits into
masterfrom
feature/peephole-optimization
May 29, 2026
Merged

perf(vm): add peephole pass to elide dead Load; Pop pairs ✂️#163
timfennis merged 3 commits into
masterfrom
feature/peephole-optimization

Conversation

@timfennis

Copy link
Copy Markdown
Owner

Context

First peephole-style optimization pass on the bytecode IR. Motivated less by raw speed gains and more by setting up a place for future passes to live — Constant; Pop and friends are the obvious starting case (dead expression-statement results).

Changes

  • New OptimizerIr::peephole() pass (ndc_vm/src/chunk.rs). Elides consecutive Constant | GetGlobal | GetLocal followed by Pop when neither instruction is a jump target. Runs to a fixed point so nested patterns ([Load, Load, Pop, Pop]) collapse fully.
  • Opt-in via Compiler::optimize: bool (default true). The fresh-compile path (Compiler::compile) and inner function compilation always optimize. Compiler::compile_resumable — the REPL's path — sets it to false. The REPL relies on halt_ip matching the position of Halt in the emitted chunk for resume-from-halt; peephole would shift instruction positions and invalidate that. Working around that requires either a frozen-prefix mechanism or reordering finish(), both of which proved tricky enough that opt-out for the REPL is the better trade.
  • Updated compiler_tests assertions and comments for the seven affected cases (test_statement, test_block_*, test_if_with_statement_*, test_while, test_assignment) to reflect the post-peephole opcode sequences.

Performance

Across a local Advent-of-Brian-style suite of ~22 puzzles: aggregate −1.0%. Mid-sized puzzles (10–100 ms) see 5–10% wins; large puzzles dominated by stdlib calls are flat. On the internal benches/ suite the standout wins are sieve (−17%) and string_concat (−13%) — both have hot loops with discarded expression values, which is exactly the pattern the pass targets.

🤖 PR description generated by Claude.

Runs to a fixed point over the IR, removing consecutive
`Constant|GetGlobal|GetLocal` followed by `Pop` when neither is a jump
target. Skipped on the REPL's resumable path so `halt_ip` stays stable
across resume-from-halt.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@timfennis
timfennis force-pushed the feature/peephole-optimization branch from 05963a7 to 76937fe Compare May 29, 2026 19:54
…es 🔬

Adds `Compiler::compile_unoptimized` and `Interpreter::compile_str_unoptimized`
so the existing compiler-tests crate can document the raw compiler output
again. Reverts the seven assertions that PR #163 updated for the post-peephole
form, and introduces `tests/optimizer.rs` with focused smoke tests for the
peephole pass itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cdd03bb1ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ndc_vm/src/compiler.rs Outdated
The nested `fn_compiler` was constructed with `Self::default()` and called
`peephole()` unconditionally, so function bodies were optimized even when the
caller used `compile_unoptimized` or `compile_str_unoptimized` for the
top-level. Inherit `self.optimize` and gate the call.

Adds `CompiledFunction::body()` as a public accessor so the new test can walk
the top-level constants table to inspect a nested function's raw vs optimized
bytecode.

Spotted by Codex on PR #163.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@timfennis
timfennis merged commit 38837bf into master May 29, 2026
1 check passed
@timfennis
timfennis deleted the feature/peephole-optimization branch May 29, 2026 20:24
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.

1 participant