Permalink
Browse files

Preserve liveness information across transformations.

  • Loading branch information...
1 parent c57a029 commit c070409790799c58d0cbdfa67a6a038648e9c563 @whitequark committed Aug 19, 2012
@@ -29,25 +29,20 @@ def code_to_cfg(options={})
Furnace::AVM2::Transform::SSAOptimize.new(idempotent: true),
Furnace::Transform::IterativeProcess.new([
- Furnace::AVM2::Transform::LivenessAnalysis.new,
Furnace::AVM2::Transform::DataflowInvariantCodeMotion.new,
Furnace::AVM2::Transform::PartialEvaluation.new,
Furnace::AVM2::Transform::SSAOptimize.new,
- Furnace::AVM2::Transform::LivenessAnalysis.new,
Furnace::AVM2::Transform::FoldBooleanShortcuts.new,
Furnace::AVM2::Transform::FoldTernaryOperators.new,
Furnace::AVM2::Transform::FoldIncrementDecrement.new,
Furnace::AVM2::Transform::SSAOptimize.new,
]),
- Furnace::AVM2::Transform::LivenessAnalysis.new(idempotent: true),
-
Furnace::AVM2::Transform::FoldPassthroughAssignments.new,
Furnace::AVM2::Transform::PropagateConstants.new,
Furnace::AVM2::Transform::ExpandUnreferencedSets.new,
-
Furnace::AVM2::Transform::UpdateExceptionVariables.new,
])
@@ -10,7 +10,6 @@ module Furnace::AVM2::Transform
require_relative "transform/refine_local_variable_barriers"
require_relative "transform/ssa_transform"
require_relative "transform/ssa_optimize"
-require_relative "transform/liveness_analysis"
require_relative "transform/dataflow_invariant_code_motion"
require_relative "transform/partial_evaluation"
require_relative "transform/propagate_constants"
@@ -65,9 +65,7 @@ def transform(cfg)
if do_move
block.insns.delete src_node
-
- block_meta.sets.delete id
- block_meta.set_map.delete id
+ block_meta.remove_set id
value = src_node.children.last
dst_node.update(value.type, value.children, value.metadata)
@@ -76,6 +74,7 @@ def transform(cfg)
dst_upper.metadata[key].merge src_node.metadata[key]
end
+ # TODO merge rnodes properly
target_meta.gets.delete id
target_meta.gets_map.delete id
target_meta.gets_upper.delete dst_node
@@ -88,9 +87,7 @@ def transform(cfg)
elsif targets.empty?
if src_node.nil? || src_node.metadata[:write_barrier].empty?
block.insns.delete src_node
-
- block_meta.sets.delete id
- block_meta.set_map.delete id
+ block_meta.remove_set id
block_changed = true
end
@@ -6,12 +6,12 @@ class FoldTernaryOperators
def transform(cfg)
changed = false
- cfg.nodes.each do |node|
- node_changed = false
+ cfg.nodes.each do |block|
+ block_changed = false
# Find a phi node.
- gets = node.metadata.gets_map.values.
+ gets = block.metadata.gets_map.values.
map(&:to_a).flatten.uniq
gets.select do |get|
@@ -22,7 +22,7 @@ def transform(cfg)
# id => source
sources = Hash[
phi.children.map do |id|
- [ id, node.sources.find { |source| source.metadata.sets.include?(id) } ]
+ [ id, block.sources.find { |source| source.metadata.sets.include?(id) } ]
end.select do |id, source|
source && source.sources.count == 1
end
@@ -82,23 +82,23 @@ def transform(cfg)
shared.metadata.merge! right.metadata
shared.metadata.remove_set right_id
- node.metadata.remove_get right_id
+ block.metadata.remove_get right_id
shared.metadata.set_map[left_id] = shared.cti
shared.cti = nil
- shared.target_labels = [ node.label ]
+ shared.target_labels = [ block.label ]
cfg.nodes.delete left
cfg.nodes.delete right
cfg.flush
reduce_phi_nodes(cfg, shared, right_id, left_id)
- changed = node_changed = true
+ changed = block_changed = true
end
- redo if node_changed
+ redo if block_changed
end
cfg if changed
@@ -1,94 +0,0 @@
-module Furnace::AVM2
- module Transform
- class LivenessAnalysis
- # Avoid creating too much literals.
- EMPTY_SET = Set[]
-
- def initialize(options={})
- @idempotent = options[:idempotent] || false
- end
-
- def transform(cfg)
- dom = cfg.dominators
- loops = cfg.identify_loops
-
- # Clear old data
- cfg.nodes.each do |block|
- block.metadata.live = nil
- block.metadata.dead = nil
- end
-
- dead_ends = Set[ cfg.exit ]
-
- # Search from the entry node, mark live variables
- worklist = Set[ cfg.entry, cfg.exit ]
- while worklist.any?
- block = worklist.first
- worklist.delete block
-
- if loops.include? block
- back_edged, sources = block.sources.partition do |source|
- dom[source].include? block
- end
- dead_ends.merge back_edged
- else
- if block.cti && block.cti.type == :throw
- dead_ends.add block
- end
-
- sources = block.sources
- end
-
- old_live = block.metadata.live
- block.metadata.live =
- block.metadata.sets +
- sources.map { |s| s.metadata.live || EMPTY_SET }.
- reduce(EMPTY_SET, :|)
-
- if block.metadata.live != old_live
- [ *block.targets, block.exception ].compact.
- each do |target|
- worklist.add target
- end
- end
- end
-
- # Search from the exit node, unmark dead variables
- worklist = dead_ends.dup
- while worklist.any?
- block = worklist.first
- worklist.delete block
-
- old_dead = block.metadata.dead
-
- if dead_ends.include? block
- block.metadata.dead =
- block.metadata.live -
- block.metadata.gets
- else
- block.metadata.dead =
- block.targets.map { |s| s.metadata.dead || EMPTY_SET }.
- reduce(:&) -
- block.metadata.gets
- end
-
- if block.metadata.dead != old_dead
- [ *block.sources, *block.exception_sources ].each do |source|
- worklist.add source
- end
- end
- end
-
- # Subtract dead from live
- cfg.nodes.each do |block|
- block.metadata.live.subtract block.metadata.dead
- block.metadata.dead = nil
- end
-
- # This transform does not change CFG in any way,
- # it just rebuilds the metadata.
- cfg if @idempotent
- end
- end
- end
-end
@@ -15,8 +15,11 @@ def transform(cfg)
# TODO add options for folding complex constants
if evaluator.immediate?(set_value)
- replace_r_nodes(cfg, block, id, set_value)
- block.metadata.remove_set(id)
+ replace_r_nodes(cfg, block, id, set_value) do |child_block|
+ child_block.metadata.live.delete id
+ end
+
+ block.metadata.remove_set id
block.insns.delete set
changed = true
Oops, something went wrong.

0 comments on commit c070409

Please sign in to comment.