Class: Optimize::Passes::DeadStashElimPass

Inherits:
Optimize::Pass show all
Defined in:
lib/optimize/passes/dead_stash_elim_pass.rb

Overview

Peephole: drop adjacent ‘setlocal X; getlocal X` pairs where slot X has no other references at the matching level in the same function.

The producer that fed the setlocal has already pushed its value onto the operand stack; the getlocal was just reading it back. Dropping both leaves the value where subsequent instructions expect it.

Constant Summary collapse

SETLOCAL_OPCODES =
%i[setlocal setlocal_WC_0].freeze
GETLOCAL_OPCODES =
%i[getlocal getlocal_WC_0].freeze
LOCAL_OPCODES =
(SETLOCAL_OPCODES + GETLOCAL_OPCODES).freeze

Instance Method Summary collapse

Methods inherited from Optimize::Pass

#one_shot?

Instance Method Details

#apply(function, type_env:, log:, **_extras) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/optimize/passes/dead_stash_elim_pass.rb', line 21

def apply(function, type_env:, log:, **_extras)
  insts = function.instructions
  return unless insts && insts.size >= 2

  candidates = []
  i = 0
  while i < insts.size - 1
    a = insts[i]
    b = insts[i + 1]
    if matching_pair?(a, b) && slot_has_no_other_refs?(insts, i, a)
      candidates << i
      i += 2
    else
      i += 1
    end
  end

  return if candidates.empty?

  candidates.reverse_each do |idx|
    line = (function.instructions[idx]&.line) || function.first_lineno || 0
    function.splice_instructions!(idx..idx + 1, [])
    log.rewrite(
      pass: :dead_stash_elim, reason: :dead_stash_eliminated,
      file: function.path, line: line,
    )
  end
end

#nameObject



17
18
19
# File 'lib/optimize/passes/dead_stash_elim_pass.rb', line 17

def name
  :dead_stash_elim
end