Skip to content
This repository has been archived by the owner on Nov 2, 2019. It is now read-only.

Commit

Permalink
Implement loop identification.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Apr 7, 2012
1 parent 3eac6ba commit 3279ddf
Showing 1 changed file with 64 additions and 18 deletions.
82 changes: 64 additions & 18 deletions lib/furnace/cfg/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,33 +69,79 @@ def merge_redundant!
# Shamelessly stolen from
# http://www.cs.colostate.edu/~mstrout/CS553/slides/lecture04.pdf
def dominators
# values of β will give rise to dom!
dom = { @entry => Set[@entry] }
unless @dominators
# values of β will give rise to dom!
dom = { @entry => Set[@entry] }

@nodes.each do |node|
next if node == @entry
dom[node] = @nodes.dup
end

change = true
while change
change = false
@nodes.each do |node|
next if node == @entry
dom[node] = @nodes.dup
end

pred = node.sources.map do |source|
dom[source]
end.reduce(:&)
change = true
while change
change = false
@nodes.each do |node|
next if node == @entry

# Key Idea
# If a node dominates all
# predecessors of node n, then it
# also dominates node n.
pred = node.sources.map do |source|
dom[source]
end.reduce(:&)

current = Set[node].merge(pred)
if current != dom[node]
dom[node] = current
change = true
end
end
end

@dominators = dom
end

current = Set[node].merge(pred)
if current != dom[node]
dom[node] = current
change = true
@dominators
end

# See also {#dominators} for references.
def identify_loops
loops = Hash.new { |h,k| h[k] = Set.new }

dom = dominators
@nodes.each do |node|
node.targets.each do |target|
# Back edges
# A back edge of a natural loop is one whose
# target dominates its source.
if dom[node].include? target
loops[target].add node
end
end
end

dom
# At this point, +loops+ contains a list of all nodes
# which have a back edge to the loop header. Expand
# it to the list of all nodes in the loop.
loops.each do |header, nodes|
# Natural loop
# The natural loop of a back edge (m→n), where
# n dominates m, is the set of nodes x such that n
# dominates x and there is a path from x to m not
# containing n.
pre_header = dom[header]
all_nodes = Set[]

nodes.each do |node|
all_nodes.merge(dom[node] - pre_header)
end

nodes.replace all_nodes
end

loops
end

def source_map
Expand Down

0 comments on commit 3279ddf

Please sign in to comment.