Skip to content

ZJIT: Remove redundant PatchPoints within basic blocks - #16231

Merged
tekknolagi merged 2 commits into
ruby:masterfrom
Shopify:rwstauner/zjit-patchpoints
Feb 24, 2026
Merged

tekknolagi merged 2 commits into
ruby:masterfrom
Shopify:rwstauner/zjit-patchpoints

Conversation

@rwstauner

@rwstauner rwstauner commented Feb 24, 2026 •

Copy link
Copy Markdown
Contributor

Add a new optimization pass that deduplicates PatchPoint instructions
asserting the same invariant within a basic block when no intervening
instruction could invalidate it.

This is common in practice — e.g., 1 + 2 + 3 produces two identical
PatchPoint MethodRedefined(Integer, +, cme) because each + call
inserts one. The second is redundant since nothing between them can
redefine Integer#+.

The approach adds a PatchPoint leaf to the abstract heap DAG so the
effect system can distinguish instructions that could invalidate
invariants (writes to PatchPoint, e.g. Send/CCall) from those that
cannot (e.g. IncrCounter, Const). The pass maintains a HashSet of
seen invariants per block and skips duplicates, clearing the set when
an instruction writes to the PatchPoint heap.

Removed PatchPoints' orphaned Snapshot dependencies are cleaned up by
the subsequent DCE pass.

I added a new test with snapshots to zjit/src/hir/tests.rs in the first commit
so that you can see how the change affects it in the second commit:
88cf26b#diff-38be021d8d0035cca77d3eab5ccc530109e7832f4711a5beb4dfced7001787ae

closes Shopify#779

@matzbot
matzbot requested a review from a team February 24, 2026 00:51
Add a new optimization pass that deduplicates PatchPoint instructions
asserting the same invariant within a basic block when no intervening
instruction could invalidate it.

This is common in practice — e.g., `1 + 2 + 3` produces two identical
`PatchPoint MethodRedefined(Integer, +, cme)` because each `+` call
inserts one. The second is redundant since nothing between them can
redefine Integer#+.

The approach adds a `PatchPoint` leaf to the abstract heap DAG so the
effect system can distinguish instructions that could invalidate
invariants (writes to PatchPoint, e.g. Send/CCall) from those that
cannot (e.g. IncrCounter, Const). The pass maintains a HashSet of
seen invariants per block and skips duplicates, clearing the set when
an instruction writes to the PatchPoint heap.

Removed PatchPoints' orphaned Snapshot dependencies are cleaned up by
the subsequent DCE pass.
@rwstauner
rwstauner force-pushed the rwstauner/zjit-patchpoints branch from 26fd99d to 88cf26b Compare February 24, 2026 00:55

@tekknolagi tekknolagi 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.

This looks great! Thank you. Is there an ARM code size reduction?

@rwstauner

Copy link
Copy Markdown
Contributor Author

With a quick lobsters run I'm seeing

$ ./run_benchmarks.rb --chruby 'a::ruby-mdev --zjit-stats' --chruby 'b::ruby-claude --zjit-stats' lobsters --warmup 30 --bench 10 --out-path data/zjit-ab.json
$ misc/zjit_diff.rb data/zjit-ab.json/output_002.json -a| grep -E 'size|bytes'
    side_exit_size                          9,783,408 →      9,397,028 ▼   -3.9%
    code_region_bytes                      29,343,744 →     28,753,920 ▼   -2.0%
    total_mem_bytes                        79,537,171 →     78,347,249 ▼   -1.5%
    zjit_alloc_bytes                       50,193,427 →     49,593,329 ▼   -1.2%

@tekknolagi
tekknolagi merged commit 997ac19 into ruby:master Feb 24, 2026
91 checks passed
@tekknolagi
tekknolagi deleted the rwstauner/zjit-patchpoints branch February 24, 2026 03:06
@tekknolagi tekknolagi linked an issue Feb 25, 2026 that may be closed by this pull request
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.

ZJIT: Regression on structaref ZJIT: Add a phase to remove redundant patch points

2 participants