Skip to content
Snippets Groups Projects
Commit 292754aa authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

Added functions for DAG creation.

parent 1ab45a98
No related branches found
No related tags found
No related merge requests found
...@@ -97,55 +97,102 @@ def generate_flow_graph(blocks): ...@@ -97,55 +97,102 @@ def generate_flow_graph(blocks):
b.add_edge_to(blocks[i + 1]) b.add_edge_to(blocks[i + 1])
def generate_dominator_tree(nodes): #def generate_dominator_tree(nodes):
"""Add dominator administration to the given flow graph nodes.""" # """Add dominator administration to the given flow graph nodes."""
# Dominator of the start node is the start itself # # Dominator of the start node is the start itself
nodes[0].dom = set([nodes[0]]) # nodes[0].dom = set([nodes[0]])
#
# For all other nodes, set all nodes as the dominators # # For all other nodes, set all nodes as the dominators
for n in nodes[1:]: # for n in nodes[1:]:
n.dom = set(copy(nodes)) # n.dom = set(copy(nodes))
#
def pred(n, known=[]): # def pred(n, known=[]):
"""Recursively find all predecessors of a node.""" # """Recursively find all predecessors of a node."""
direct = filter(lambda x: x not in known, n.edges_from) # direct = filter(lambda x: x not in known, n.edges_from)
p = copy(direct) # p = copy(direct)
#
for ancestor in direct: # for ancestor in direct:
p += pred(ancestor, direct) # p += pred(ancestor, direct)
#
return p # return p
#
# Iteratively eliminate nodes that are not dominators # # Iteratively eliminate nodes that are not dominators
changed = True # changed = True
#
while changed: # while changed:
changed = False # changed = False
#
for n in nodes[1:]: # for n in nodes[1:]:
old_dom = n.dom # old_dom = n.dom
intersection = lambda p1, p2: p1.dom & p2.dom # intersection = lambda p1, p2: p1.dom & p2.dom
n.dom = set([n]) | reduce(intersection, pred(n), set([])) # n.dom = set([n]) | reduce(intersection, pred(n), set([]))
#
if n.dom != old_dom: # if n.dom != old_dom:
changed = True # changed = True
#
def idom(d, n): # def idom(d, n):
"""Check if d immediately dominates n.""" # """Check if d immediately dominates n."""
for b in n.dom: # for b in n.dom:
if b != d and b != n and b in n.dom: # if b != d and b != n and b in n.dom:
return False # return False
#
return True # return True
#
# Build tree using immediate dominators # # Build tree using immediate dominators
for n in nodes: # for n in nodes:
for d in n.dom: # for d in n.dom:
if idom(d, n): # if idom(d, n):
d.set_dominates(n) # d.set_dominates(n)
break # break
# statements = parse_file(...)
# b = find_basic_blocks(statements) class Dag:
# generate_flow_graph(b) # nodes now have edges def __init__(self, block):
# generate_dominator_tree(b) # nodes now have dominators """Create the Directed Acyclic Graph of all binary operations in a
basic block."""
self.nodes = []
for s in block:
if s.is_command('move') or s.is_monop():
rd, rs = s
y = self.find_reg_node(rs)
self.find_op_node(s.name, rd, y)
elif s.is_binop():
rd, rs, rt = s
y = self.find_reg_node(rs)
z = self.find_reg_node(rt)
self.find_op_node(s.name, rd, y, z)
def find_reg_node(self, reg):
for n in self.nodes:
if reg in n.reg:
return n
node = DagLeaf(reg)
self.nodes.append(node)
return node
def find_op_node(self, op, rd, *args):
for n in self.nodes:
if n.op == op and n.nodes == args:
n.labels.append(rd)
return n
node = DagNode(op, rd, *args)
self.nodes.append(node)
return node
class DagNode:
def __init__(self, op, label, *args):
self.op = op
self.labels = [label]
self.nodes = args
class DagLeaf:
def __init__(self, reg):
self.reg = reg
...@@ -21,7 +21,7 @@ class Statement: ...@@ -21,7 +21,7 @@ class Statement:
arguments.""" arguments."""
return self.stype == other.stype and self.name == other.name \ return self.stype == other.stype and self.name == other.name \
and self.args == other.args and self.args == other.args
def __len__(self): def __len__(self):
return len(self.args) return len(self.args)
...@@ -74,6 +74,14 @@ class Statement: ...@@ -74,6 +74,14 @@ class Statement:
return self.is_command() \ return self.is_command() \
and re.match('^(add|sub|mult|div|abs|neg)(u|\.d)?$', self.name) and re.match('^(add|sub|mult|div|abs|neg)(u|\.d)?$', self.name)
def is_monop(self):
"""Check if the statement is an unary operation."""
return len(self) == 2 and self.is_arith()
def is_binop(self):
"""Check if the statement is an binary operation."""
return self.is_command() and len(self) == 3 and not self.is_jump()
def jump_target(self): def jump_target(self):
"""Get the jump target of this statement.""" """Get the jump target of this statement."""
if not self.is_jump(): if not self.is_jump():
...@@ -120,7 +128,7 @@ class Block: ...@@ -120,7 +128,7 @@ class Block:
replacement.""" replacement."""
if self.pointer == 0: if self.pointer == 0:
raise Exception('No statement have been read yet.') raise Exception('No statement have been read yet.')
if start == None: if start == None:
start = self.pointer - 1 start = self.pointer - 1
......
No preview for this file type
...@@ -2,7 +2,7 @@ import unittest ...@@ -2,7 +2,7 @@ import unittest
from src.statement import Statement as S from src.statement import Statement as S
from src.dataflow import BasicBlock as B, find_leaders, find_basic_blocks, \ from src.dataflow import BasicBlock as B, find_leaders, find_basic_blocks, \
generate_flow_graph generate_flow_graph, Dag
class TestDataflow(unittest.TestCase): class TestDataflow(unittest.TestCase):
...@@ -44,3 +44,6 @@ class TestDataflow(unittest.TestCase): ...@@ -44,3 +44,6 @@ class TestDataflow(unittest.TestCase):
self.assertEqual(b2.edges_to, [b3]) self.assertEqual(b2.edges_to, [b3])
self.assertIn(b1, b3.edges_from) self.assertIn(b1, b3.edges_from)
self.assertIn(b2, b3.edges_from) self.assertIn(b2, b3.edges_from)
def test_dag(self):
pass
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment