Method: Fisk::CFG.live_variables

Defined in:
lib/fisk/basic_block.rb

.live_variables(blocks) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/fisk/basic_block.rb', line 109

def self.live_variables blocks
  seen = Set.new

  blocks.each do |block|
    used = Set.new
    defd = Set.new

    block.insns.each do |insn|
      if insn.has_temp_registers?
        insn.temp_registers.each do |reg|
          defd << reg unless seen.include?(reg)
          used << reg unless defd.include?(reg)
          seen << reg
        end
      end
    end

    block.use = used.to_a
    block.def = defd.to_a
    block.in  = []
    block.out = []
  end

  worklist = blocks.dup
  while block = worklist.pop
    block.out = block.succ.inject([]) { |out_registers, succ_block|
      out_registers | succ_block.in
    }
    ins = block.in | block.use | (block.out - block.def)

    if ins == block.in
      # Done with this block!
      block.live.each do |live_register|
        live_register.end_point ||= block.end_point

        if live_register.start_point > block.start_point
          live_register.start_point = block.start_point
        end

        if live_register.end_point < block.end_point
          live_register.end_point = block.end_point
        end
      end
    else
      block.in = ins
      worklist.concat(block.pred)
    end
  end

  seen
end