Skip to content

[WIP] Add local value numbering implementation in ZJIT#4

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/implement-local-value-numbering
Draft

[WIP] Add local value numbering implementation in ZJIT#4
Copilot wants to merge 2 commits intomasterfrom
copilot/implement-local-value-numbering

Conversation

Copy link

Copilot AI commented Feb 1, 2026

Implementation Plan for Local Value Numbering in ZJIT

Overview

Implement local value numbering (LVN) optimization to eliminate redundant computations within basic blocks. The Effect/AbstractHeap API already exists in the upstream codebase (zjit/src/hir_effect), so we'll use and potentially extend it as needed.

Implementation Checklist

  • Rebase on upstream ruby/ruby master
  • Explore existing Effect/AbstractHeap API
  • Implement local_value_numbering() optimization pass
    • Create InsnKey type for hashing instructions by operation and operands
    • Track pure expressions within each basic block using HashMap
    • Use Union-Find (make_equal_to) to deduplicate redundant computations
    • Leverage existing has_effects() method to identify pure operations
  • Add the pass to the optimize() pipeline
  • Create comprehensive tests for LVN
    • Test deduplication of pure arithmetic operations
    • Test preservation of side-effecting operations
    • Test interaction with constant folding and DCE
  • Run existing tests to ensure no regressions
  • Build and validate implementation

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

tekknolagi and others added 2 commits August 26, 2025 09:10
Copilot AI requested a review from tekknolagi February 1, 2026 19:48
tekknolagi pushed a commit that referenced this pull request Mar 24, 2026
When we call `asm.load`, many times we're passing in a VReg, and that
causes extra loads when we lower to machine code.  I'd like to only emit
a load in the case that the operand _isn't_ a VReg.

For example this code:

```ruby
class Foo
  def initialize
    @foo = 123
  end

  def foo
    @foo
  end
end

foo = Foo.new
5.times { foo.foo }
```

Before this patch, the machine code for `LoadField` looks like this:

```
  # Insn: v18 LoadField v17, :_shape_id@0x4
  # Load field id=_shape_id offset=4
  0x121308320: mov x1, x0
  0x121308324: ldur w1, [x1, #4]
```

Now it looks like this:

```
  # Insn: v18 LoadField v17, :_shape_id@0x4
  # Load field id=_shape_id offset=4
  0x12339c320: ldur w1, [x0, #4]
```

We were able to eliminate a reg-reg copy.
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