diff --git a/src/dataflow.py b/src/dataflow.py index e9697f4103c0ba03738856d4b483d2480d565c82..eb27e4cda186d3edbef27a4c0682555dc9957721 100644 --- a/src/dataflow.py +++ b/src/dataflow.py @@ -97,55 +97,102 @@ def generate_flow_graph(blocks): b.add_edge_to(blocks[i + 1]) -def generate_dominator_tree(nodes): - """Add dominator administration to the given flow graph nodes.""" - # Dominator of the start node is the start itself - nodes[0].dom = set([nodes[0]]) - - # For all other nodes, set all nodes as the dominators - for n in nodes[1:]: - n.dom = set(copy(nodes)) - - def pred(n, known=[]): - """Recursively find all predecessors of a node.""" - direct = filter(lambda x: x not in known, n.edges_from) - p = copy(direct) - - for ancestor in direct: - p += pred(ancestor, direct) - - return p - - # Iteratively eliminate nodes that are not dominators - changed = True - - while changed: - changed = False - - for n in nodes[1:]: - old_dom = n.dom - intersection = lambda p1, p2: p1.dom & p2.dom - n.dom = set([n]) | reduce(intersection, pred(n), set([])) - - if n.dom != old_dom: - changed = True - - def idom(d, n): - """Check if d immediately dominates n.""" - for b in n.dom: - if b != d and b != n and b in n.dom: - return False - - return True - - # Build tree using immediate dominators - for n in nodes: - for d in n.dom: - if idom(d, n): - d.set_dominates(n) - break - -# statements = parse_file(...) -# b = find_basic_blocks(statements) -# generate_flow_graph(b) # nodes now have edges -# generate_dominator_tree(b) # nodes now have dominators +#def generate_dominator_tree(nodes): +# """Add dominator administration to the given flow graph nodes.""" +# # Dominator of the start node is the start itself +# nodes[0].dom = set([nodes[0]]) +# +# # For all other nodes, set all nodes as the dominators +# for n in nodes[1:]: +# n.dom = set(copy(nodes)) +# +# def pred(n, known=[]): +# """Recursively find all predecessors of a node.""" +# direct = filter(lambda x: x not in known, n.edges_from) +# p = copy(direct) +# +# for ancestor in direct: +# p += pred(ancestor, direct) +# +# return p +# +# # Iteratively eliminate nodes that are not dominators +# changed = True +# +# while changed: +# changed = False +# +# for n in nodes[1:]: +# old_dom = n.dom +# intersection = lambda p1, p2: p1.dom & p2.dom +# n.dom = set([n]) | reduce(intersection, pred(n), set([])) +# +# if n.dom != old_dom: +# changed = True +# +# def idom(d, n): +# """Check if d immediately dominates n.""" +# for b in n.dom: +# if b != d and b != n and b in n.dom: +# return False +# +# return True +# +# # Build tree using immediate dominators +# for n in nodes: +# for d in n.dom: +# if idom(d, n): +# d.set_dominates(n) +# break + + +class Dag: + def __init__(self, block): + """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 diff --git a/src/statement.py b/src/statement.py index afac64171c09abb235afb0f12ac8c66a313ba841..87dea3ea134e9af73bab1151f570d0399e111575 100644 --- a/src/statement.py +++ b/src/statement.py @@ -21,7 +21,7 @@ class Statement: arguments.""" return self.stype == other.stype and self.name == other.name \ and self.args == other.args - + def __len__(self): return len(self.args) @@ -74,6 +74,14 @@ class Statement: return self.is_command() \ 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): """Get the jump target of this statement.""" if not self.is_jump(): @@ -123,7 +131,7 @@ class Block: replacement.""" if self.pointer == 0: raise Exception('No statement have been read yet.') - + if start == None: start = self.pointer - 1 diff --git a/tests/__init__.pyc b/tests/__init__.pyc index eac7ddb51628ddce201535c18f67f8b85646d16a..7ef5b56499b5cbfec327a19f91a44ca00ff2d827 100644 Binary files a/tests/__init__.pyc and b/tests/__init__.pyc differ diff --git a/tests/test_dataflow.py b/tests/test_dataflow.py index e3551121dc2817187f7c3dc619b371c9c569d54b..425dec91b8f100c0925829db7d089c555c40089b 100644 --- a/tests/test_dataflow.py +++ b/tests/test_dataflow.py @@ -2,7 +2,7 @@ import unittest from src.statement import Statement as S from src.dataflow import BasicBlock as B, find_leaders, find_basic_blocks, \ - generate_flow_graph + generate_flow_graph, Dag class TestDataflow(unittest.TestCase): @@ -44,3 +44,6 @@ class TestDataflow(unittest.TestCase): self.assertEqual(b2.edges_to, [b3]) self.assertIn(b1, b3.edges_from) self.assertIn(b2, b3.edges_from) + + def test_dag(self): + pass