Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix liveness analysis pass.

  • Loading branch information...
commit 9357dfbb08dd49396e08383525da923bbf8aea33 1 parent 24cb6e9
@whitequark authored
View
31 lib/furnace-avm2/transform/liveness_analysis.rb
@@ -5,22 +5,36 @@ class LivenessAnalysis
EMPTY_SET = Set[]
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 ]
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
+ sources = block.sources
+ end
+
old_live = block.metadata.live
block.metadata.live =
block.metadata.sets +
- block.sources.map { |s| s.metadata.live || EMPTY_SET }.
+ sources.map { |s| s.metadata.live || EMPTY_SET }.
reduce(EMPTY_SET, :|)
if block.metadata.live != old_live
@@ -31,19 +45,22 @@ def transform(cfg)
end
end
- cfg.exit.metadata.dead = cfg.exit.metadata.live
-
# Search from the exit node, unmark dead variables
- worklist = Set[ cfg.exit ]
+ worklist = dead_ends.dup
while worklist.any?
block = worklist.first
worklist.delete block
- unless block == cfg.exit
- old_dead = block.metadata.dead
+ 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(:&) -
+ reduce(:&) -
block.metadata.gets
end
View
3  lib/furnace-avm2/transform/ssa_transform.rb
@@ -20,12 +20,13 @@ def [](key)
end
def any?
- @sets.any? || @gets.any? || @live.any?
+ @sets.any? || @gets.any? || @live.any? || @dead
end
def inspect
str = "| sets: #{@sets.to_a.join(", ")} gets: #{@gets.to_a.join(", ")}\n"
str << "| live: #{@live.to_a.join(", ")}"
+ str << "\n| dead: #{@dead.to_a.join(", ")}" if @dead
#str << "\n| set_map: #{@set_map.pretty_inspect}"
#str << "| gets_map: #{@gets_map.pretty_inspect}"
#str << "| gets_upper: #{@gets_upper.pretty_inspect}"
Please sign in to comment.
Something went wrong with that request. Please try again.