Quellcode durchsuchen

Separated liveness, reaching definitions and dominator tree from dataflow.py.

Taddeus Kroes vor 14 Jahren
Ursprung
Commit
6924b53cc7
9 geänderte Dateien mit 423 neuen und 326 gelöschten Zeilen
  1. 50 0
      src/dag.py
  2. 0 189
      src/dataflow.py
  3. 50 0
      src/dominator.py
  4. 20 0
      src/liveness.py
  5. 74 0
      src/reaching_definitions.py
  6. 65 0
      tests/test_dag.py
  7. 1 137
      tests/test_dataflow.py
  8. 63 0
      tests/test_liveness.py
  9. 100 0
      tests/test_reaching_definitions.py

+ 50 - 0
src/dag.py

@@ -0,0 +1,50 @@
+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 not isinstance(n, DagLeaf) and 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

+ 0 - 189
src/dataflow.py

@@ -9,10 +9,6 @@ class BasicBlock(Block):
 
         self.dominates = []
         self.dominated_by = []
-        self.in_set = set([])
-        self.out_set = set([])
-        self.gen_set = set([])
-        self.kill_set = set([])
 
     def add_edge_to(self, block):
         if block not in self.edges_to:
@@ -24,90 +20,6 @@ class BasicBlock(Block):
             self.dominates.append(block)
             block.dominated_by.append(self)
 
-    def create_gen_kill(self, defs):
-        used = set()
-        self_defs = {}
-
-        # Get the last of each definition series and put in in the `def' set
-        self.gen_set = set()
-
-        for s in reversed(self):
-            for reg in s.get_def():
-                if reg not in self_defs:
-                    self_defs[reg] = s.sid
-                    self.gen_set.add(s.sid)
-
-        # Generate kill set
-        self.kill_set = set()
-
-        for reg, statement_ids in defs.iteritems():
-            if reg in self_defs:
-                self.kill_set |= statement_ids - set([self_defs[reg]])
-
-
-def get_defs(blocks):
-    # Collect definitions of all registers
-    defs = {}
-
-    for b in blocks:
-        for s in b:
-            for reg in s.get_def():
-                if reg not in defs:
-                    defs[reg] = set([s.sid])
-                else:
-                    defs[reg].add(s.sid)
-
-    return defs
-
-
-def reaching_definitions(blocks):
-    """Generate the `in' and `out' sets of the given blocks using the iterative
-    algorithm from the lecture slides."""
-    # Generate flow graph
-    generate_flow_graph(blocks)
-
-    # Create gen/kill sets
-    defs = get_defs(blocks)
-    print 'defs:', defs
-
-    for b in blocks:
-        b.create_gen_kill(defs)
-        b.out_set = b.gen_set
-
-    change = True
-
-    while change:
-        change = False
-
-        for b in blocks:
-            print 'block:', b
-            b.in_set = set()
-
-            for pred in b.edges_from:
-                print 'pred:      ', pred
-                b.in_set |= pred.out_set
-
-            print 'b.in_set:  ', b.in_set
-            print 'b.out_set: ', b.out_set
-            new_out = b.gen_set | (b.in_set - b.kill_set)
-            print 'new_out:   ', new_out
-
-            if new_out != b.out_set:
-                print 'changed'
-                b.out_set = new_out
-                change = True
-
-
-def pred(n, known=[]):
-    """Recursively find all predecessors of a node."""
-    direct = filter(lambda b: b not in known, n.edges_from)
-    p = copy(direct)
-
-    for ancestor in direct:
-        p += pred(ancestor, direct)
-
-    return p
-
 
 def find_leaders(statements):
     """Determine the leaders, which are:
@@ -169,104 +81,3 @@ def generate_flow_graph(blocks):
                 b.add_edge_to(blocks[i + 1])
         elif i < len(blocks) - 1:
             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
-
-
-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 not isinstance(n, DagLeaf) and 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

+ 50 - 0
src/dominator.py

@@ -0,0 +1,50 @@
+from copy import copy
+
+
+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

+ 20 - 0
src/liveness.py

@@ -0,0 +1,20 @@
+def create_gen_kill(block):
+    # Get the last of each definition series and put in in the `def' set
+    block.live_gen = set()
+    block.live_kill = set()
+    print 'block:', block
+
+    for s in block:
+        # If a register is used without having been defined in this block,
+        # yet, put it in the `gen' set
+        for reg in s.get_use():
+            if reg not in block.live_kill:
+                print '  add:', reg
+                block.live_gen.add(reg)
+
+        for reg in s.get_def():
+            block.live_kill.add(reg)
+
+
+def create_in_out(blocks):
+    pass

+ 74 - 0
src/reaching_definitions.py

@@ -0,0 +1,74 @@
+from dataflow import BasicBlock as B, generate_flow_graph
+
+
+def get_defs(blocks):
+    """Collect definitions of all registers."""
+    defs = {}
+
+    for b in blocks:
+        for s in b:
+            for reg in s.get_def():
+                if reg not in defs:
+                    defs[reg] = set([s.sid])
+                else:
+                    defs[reg].add(s.sid)
+
+    return defs
+
+
+def create_gen_kill(block, global_defs):
+    block_defs = {}
+
+    # Get the last of each definition series and put in in the `def' set
+    block.reach_gen = set()
+
+    for s in reversed(block):
+        for reg in s.get_def():
+            if reg not in block_defs:
+                block_defs[reg] = s.sid
+                block.reach_gen.add(s.sid)
+
+    # Generate kill set
+    block.reach_kill = set()
+
+    for reg, statement_ids in global_defs.iteritems():
+        if reg in block_defs:
+            block.reach_kill |= statement_ids - set([block_defs[reg]])
+
+
+def create_in_out(blocks):
+    """Generate the `in' and `out' sets of the given blocks using the iterative
+    algorithm from the lecture slides."""
+    # Generate flow graph
+    generate_flow_graph(blocks)
+
+    # Create gen/kill sets
+    defs = get_defs(blocks)
+    print 'defs:', defs
+
+    for b in blocks:
+        create_gen_kill(b, defs)
+        b.reach_out = b.reach_gen
+
+    change = True
+
+    while change:
+        change = False
+
+        for b in blocks:
+            print 'block:', b
+            b.reach_in = set()
+
+            for pred in b.edges_from:
+                print 'pred:      ', pred
+                b.reach_in |= pred.reach_out
+
+            print 'b.reach_in:  ', b.reach_in
+            print 'b.reach_out: ', b.reach_out
+            new_out = b.reach_gen | (b.reach_in - b.reach_kill)
+            print 'new_out:   ', new_out
+
+            if new_out != b.reach_out:
+                print 'changed'
+                b.reach_out = new_out
+                change = True

+ 65 - 0
tests/test_dag.py

@@ -0,0 +1,65 @@
+import unittest
+
+from src.statement import Statement as S
+from src.dataflow import BasicBlock as B
+from src.dag import Dag, DagNode, DagLeaf
+
+
+class TestDag(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_dag_unary(self):
+        dag = Dag(B([S('command', 'neg.d', '$rd', '$rs')]))
+        expect = Dag([])
+        expect.nodes = [DagLeaf('$rs'), DagNode('neg.d', '$rd', \
+                        DagLeaf('$rs'))]
+
+        self.assertEqualDag(dag, expect)
+
+    def test_dag_binary(self):
+        dag = Dag(B([S('command', 'addu', '$rd', '$r1', '$r2')]))
+        expect = Dag([])
+        expect.nodes = [DagLeaf('$r1'),
+                        DagLeaf('$r2'),
+                        DagNode('addu', '$rd', DagLeaf('$r1'), DagLeaf('$r2'))]
+
+        self.assertEqualDag(dag, expect)
+
+#    def test_dag_combinednode(self):
+#        dag = Dag(B([S('command', 'mult', '$rd1', '$r1', '$r2'),
+#                     S('command', 'mult', '$rd2', '$r1', '$r2')]))
+#        expect = Dag([])
+#        multnode = DagNode('mult',
+#                           DagLeaf('$r1'),
+#                           DagLeaf('$r2'))
+#        multnode.labels = ['$rd1', '$rd2']
+#        expect.nodes = [DagLeaf('$r1'),
+#                        DagLeaf('$r2'),
+#                        multnode]
+#
+#        self.assertEqualDag(dag, expect)
+
+    def assertEqualDag(self, dag1, dag2):
+        self.assertEqual(len(dag1.nodes), len(dag2.nodes))
+
+        for node1, node2 in zip(dag1.nodes, dag2.nodes):
+            self.assertEqualNodes(node1, node2)
+
+    def assertEqualNodes(self, node1, node2):
+        if isinstance(node1, DagLeaf):
+            self.assertIsInstance(node2, DagLeaf)
+            self.assertEqual(node1.reg, node2.reg)
+        elif isinstance(node2, DagLeaf):
+            raise AssertionError
+        else:
+            self.assertEqual(node1.op, node2.op)
+            self.assertEqual(node1.labels, node2.labels)
+            self.assertEqual(len(node1.nodes), len(node2.nodes))
+
+            for child1, child2 in zip(node1.nodes, node2.nodes):
+                self.assertEqualNodes(child1, child2)

+ 1 - 137
tests/test_dataflow.py

@@ -2,8 +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, Dag, DagNode, DagLeaf, get_defs, \
-        reaching_definitions
+        generate_flow_graph
 
 
 class TestDataflow(unittest.TestCase):
@@ -25,90 +24,6 @@ class TestDataflow(unittest.TestCase):
                 [B(s[:2]).statements, B(s[2:4]).statements, \
                  B(s[4:]).statements])
 
-    def test_get_defs(self):
-        s1 = S('command', 'add', '$3', '$1', '$2')
-        s2 = S('command', 'move', '$1', '$3')
-        s3 = S('command', 'move', '$3', '$2')
-        s4 = S('command', 'li', '$4', '0x00000001')
-        block = B([s1, s2, s3, s4])
-        self.assertEqual(get_defs([block]), {
-            '$3': set([s1.sid, s3.sid]),
-            '$1': set([s2.sid]),
-            '$4': set([s4.sid])
-        })
-
-    def test_create_gen_kill_simple(self):
-        s1 = S('command', 'addu', '$3', '$1', '$2')
-        s2 = S('command', 'addu', '$1', '$3', 10)
-        s3 = S('command', 'subu', '$3', '$1', 5)
-        s4 = S('command', 'li', '$4', '0x00000001')
-        block = B([s1, s2, s3, s4])
-        block.create_gen_kill(get_defs([block]))
-        self.assertEqual(block.gen_set, set([s2.sid, s3.sid, s4.sid]))
-        self.assertEqual(block.kill_set, set([s1.sid]))
-
-
-    def test_create_gen_kill_between_blocks(self):
-        s11 = S('command', 'li', 'a', 3)
-        s12 = S('command', 'li', 'b', 5)
-        s13 = S('command', 'li', 'd', 4)
-        s14 = S('command', 'li', 'x', 100)
-        s15 = S('command', 'blt', 'a', 'b', 'L1')
-        b1 = B([s11, s12, s13, s14, s15])
-
-        s21 = S('command', 'addu', 'c', 'a', 'b')
-        s22 = S('command', 'li', 'd', 2)
-        b2 = B([s21, s22])
-
-        s31 = S('label', 'L1')
-        s32 = S('command', 'li', 'c', 4)
-        s33 = S('command', 'mult', 'b', 'd')
-        s34 = S('command', 'mflo', 'temp')
-        s35 = S('command', 'addu', 'return', 'temp', 'c')
-        b3 = B([s31, s32, s33, s34, s35])
-
-        defs = get_defs([b1, b2, b3])
-        b1.create_gen_kill(defs)
-        b2.create_gen_kill(defs)
-        b3.create_gen_kill(defs)
-
-        self.assertEqual(b1.gen_set, set([s11.sid, s12.sid, s13.sid, s14.sid]))
-        self.assertEqual(b1.kill_set, set([s22.sid]))
-
-        self.assertEqual(b2.gen_set, set([s21.sid, s22.sid]))
-        self.assertEqual(b2.kill_set, set([s13.sid, s32.sid]))
-
-        self.assertEqual(b3.gen_set, set([s32.sid, s34.sid, s35.sid]))
-        self.assertEqual(b3.kill_set, set([s21.sid]))
-
-
-    def test_reaching_definitions(self):
-        s11 = S('command', 'li', 'a', 3)
-        s12 = S('command', 'li', 'b', 5)
-        s13 = S('command', 'li', 'd', 4)
-        s14 = S('command', 'li', 'x', 100)
-        s15 = S('command', 'blt', 'a', 'b', 'L1')
-        b1 = B([s11, s12, s13, s14, s15])
-
-        s21 = S('command', 'addu', 'c', 'a', 'b')
-        s22 = S('command', 'li', 'd', 2)
-        b2 = B([s21, s22])
-
-        s31 = S('label', 'L1')
-        s32 = S('command', 'li', 'c', 4)
-        s33 = S('command', 'mult', 'b', 'd')
-        s34 = S('command', 'mflo', 'temp')
-        s35 = S('command', 'addu', 'return', 'temp', 'c')
-        b3 = B([s31, s32, s33, s34, s35])
-
-        reaching_definitions([b1, b2, b3])
-        self.assertEqual(b1.in_set, set())
-        self.assertEqual(b1.out_set, set([s11.sid, s12.sid, s13.sid]))
-        self.assertEqual(b2.in_set, set([s11.sid, s12.sid]))
-        self.assertEqual(b2.out_set, set([s12.sid, s22.sid]))
-        self.assertEqual(b3.in_set, set([s12.sid, s22.sid]))
-        self.assertEqual(b3.out_set, set())
-
     def test_generate_flow_graph_simple(self):
         b1 = B([S('command', 'foo'), S('command', 'j', 'b2')])
         b2 = B([S('label', 'b2'), S('command', 'bar')])
@@ -129,54 +44,3 @@ 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_unary(self):
-        dag = Dag(B([S('command', 'neg.d', '$rd', '$rs')]))
-        expect = Dag([])
-        expect.nodes = [DagLeaf('$rs'), DagNode('neg.d', '$rd', \
-                        DagLeaf('$rs'))]
-
-        self.assertEqualDag(dag, expect)
-
-    def test_dag_binary(self):
-        dag = Dag(B([S('command', 'addu', '$rd', '$r1', '$r2')]))
-        expect = Dag([])
-        expect.nodes = [DagLeaf('$r1'),
-                        DagLeaf('$r2'),
-                        DagNode('addu', '$rd', DagLeaf('$r1'), DagLeaf('$r2'))]
-
-        self.assertEqualDag(dag, expect)
-
-#    def test_dag_combinednode(self):
-#        dag = Dag(B([S('command', 'mult', '$rd1', '$r1', '$r2'),
-#                     S('command', 'mult', '$rd2', '$r1', '$r2')]))
-#        expect = Dag([])
-#        multnode = DagNode('mult',
-#                           DagLeaf('$r1'),
-#                           DagLeaf('$r2'))
-#        multnode.labels = ['$rd1', '$rd2']
-#        expect.nodes = [DagLeaf('$r1'),
-#                        DagLeaf('$r2'),
-#                        multnode]
-#
-#        self.assertEqualDag(dag, expect)
-
-    def assertEqualDag(self, dag1, dag2):
-        self.assertEqual(len(dag1.nodes), len(dag2.nodes))
-
-        for node1, node2 in zip(dag1.nodes, dag2.nodes):
-            self.assertEqualNodes(node1, node2)
-
-    def assertEqualNodes(self, node1, node2):
-        if isinstance(node1, DagLeaf):
-            self.assertIsInstance(node2, DagLeaf)
-            self.assertEqual(node1.reg, node2.reg)
-        elif isinstance(node2, DagLeaf):
-            raise AssertionError
-        else:
-            self.assertEqual(node1.op, node2.op)
-            self.assertEqual(node1.labels, node2.labels)
-            self.assertEqual(len(node1.nodes), len(node2.nodes))
-
-            for child1, child2 in zip(node1.nodes, node2.nodes):
-                self.assertEqualNodes(child1, child2)

+ 63 - 0
tests/test_liveness.py

@@ -0,0 +1,63 @@
+import unittest
+
+from src.statement import Statement as S
+from src.dataflow import BasicBlock as B
+from src.liveness import create_gen_kill, create_in_out
+
+
+class TestLiveness(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_create_gen_kill(self):
+        s1 = S('command', 'addu', '$3', '$1', '$2')
+        s2 = S('command', 'addu', '$1', '$3', 10)
+        s3 = S('command', 'subu', '$3', '$1', 5)
+        s4 = S('command', 'li', '$4', '0x00000001')
+        block = B([s1, s2, s3, s4])
+
+        create_gen_kill(block)
+
+        self.assertEqual(block.live_gen, set(['$1', '$2']))
+        self.assertEqual(block.live_kill, set(['$3', '$1', '$1']))
+
+    #def test_create_in_out(self):
+    #    s11 = S('command', 'li', 'a', 3)
+    #    s12 = S('command', 'li', 'b', 5)
+    #    s13 = S('command', 'li', 'd', 4)
+    #    s14 = S('command', 'li', 'x', 100)
+    #    s15 = S('command', 'blt', 'a', 'b', 'L1')
+    #    b1 = B([s11, s12, s13, s14, s15])
+
+    #    s21 = S('command', 'addu', 'c', 'a', 'b')
+    #    s22 = S('command', 'li', 'd', 2)
+    #    b2 = B([s21, s22])
+
+    #    s31 = S('label', 'L1')
+    #    s32 = S('command', 'li', 'c', 4)
+    #    s33 = S('command', 'mult', 'b', 'd')
+    #    s34 = S('command', 'mflo', 'temp')
+    #    s35 = S('command', 'addu', 'return', 'temp', 'c')
+    #    b3 = B([s31, s32, s33, s34, s35])
+
+    #    create_in_out([b1, b2, b3])
+
+    #    self.assertEqual(b1.live_gen, set([s11.sid, s12.sid, s13.sid, s14.sid]))
+    #    self.assertEqual(b1.live_kill, set([s22.sid]))
+
+    #    self.assertEqual(b2.live_gen, set([s21.sid, s22.sid]))
+    #    self.assertEqual(b2.live_kill, set([s13.sid, s32.sid]))
+
+    #    self.assertEqual(b3.live_gen, set([s32.sid, s34.sid, s35.sid]))
+    #    self.assertEqual(b3.live_kill, set([s21.sid]))
+
+    #    self.assertEqual(b1.live_in, set())
+    #    self.assertEqual(b1.live_out, set([s11.sid, s12.sid, s13.sid]))
+    #    self.assertEqual(b2.live_in, set([s11.sid, s12.sid]))
+    #    self.assertEqual(b2.live_out, set([s12.sid, s22.sid]))
+    #    self.assertEqual(b3.live_in, set([s12.sid, s22.sid]))
+    #    self.assertEqual(b3.live_out, set())

+ 100 - 0
tests/test_reaching_definitions.py

@@ -0,0 +1,100 @@
+import unittest
+
+from src.statement import Statement as S
+from src.dataflow import BasicBlock as B
+from src.reaching_definitions import get_defs, create_gen_kill, create_in_out
+
+
+class TestReachingDefinitions(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_defs(self):
+        s1 = S('command', 'add', '$3', '$1', '$2')
+        s2 = S('command', 'move', '$1', '$3')
+        s3 = S('command', 'move', '$3', '$2')
+        s4 = S('command', 'li', '$4', '0x00000001')
+        block = B([s1, s2, s3, s4])
+
+        self.assertEqual(get_defs([block]), {
+            '$3': set([s1.sid, s3.sid]),
+            '$1': set([s2.sid]),
+            '$4': set([s4.sid])
+        })
+
+    def test_create_gen_kill_simple(self):
+        s1 = S('command', 'addu', '$3', '$1', '$2')
+        s2 = S('command', 'addu', '$1', '$3', 10)
+        s3 = S('command', 'subu', '$3', '$1', 5)
+        s4 = S('command', 'li', '$4', '0x00000001')
+        block = B([s1, s2, s3, s4])
+
+        create_gen_kill(block, get_defs([block]))
+
+        self.assertEqual(block.reach_gen, set([s2.sid, s3.sid, s4.sid]))
+        self.assertEqual(block.reach_kill, set([s1.sid]))
+
+    #def test_create_gen_kill_between_blocks(self):
+    #    s11 = S('command', 'li', 'a', 3)
+    #    s12 = S('command', 'li', 'b', 5)
+    #    s13 = S('command', 'li', 'd', 4)
+    #    s14 = S('command', 'li', 'x', 100)
+    #    s15 = S('command', 'blt', 'a', 'b', 'L1')
+    #    b1 = B([s11, s12, s13, s14, s15])
+
+    #    s21 = S('command', 'addu', 'c', 'a', 'b')
+    #    s22 = S('command', 'li', 'd', 2)
+    #    b2 = B([s21, s22])
+
+    #    s31 = S('label', 'L1')
+    #    s32 = S('command', 'li', 'c', 4)
+    #    s33 = S('command', 'mult', 'b', 'd')
+    #    s34 = S('command', 'mflo', 'temp')
+    #    s35 = S('command', 'addu', 'return', 'temp', 'c')
+    #    b3 = B([s31, s32, s33, s34, s35])
+
+    #    defs = get_defs([b1, b2, b3])
+    #    create_gen_kill(b1, defs)
+    #    create_gen_kill(b2, defs)
+    #    create_gen_kill(b3, defs)
+
+    #    self.assertEqual(b1.reach_gen, set([s11.sid, s12.sid, s13.sid, s14.sid]))
+    #    self.assertEqual(b1.reach_kill, set([s22.sid]))
+
+    #    self.assertEqual(b2.reach_gen, set([s21.sid, s22.sid]))
+    #    self.assertEqual(b2.reach_kill, set([s13.sid, s32.sid]))
+
+    #    self.assertEqual(b3.reach_gen, set([s32.sid, s34.sid, s35.sid]))
+    #    self.assertEqual(b3.reach_kill, set([s21.sid]))
+
+    #def test_create_in_out(self):
+    #    s11 = S('command', 'li', 'a', 3)
+    #    s12 = S('command', 'li', 'b', 5)
+    #    s13 = S('command', 'li', 'd', 4)
+    #    s14 = S('command', 'li', 'x', 100)
+    #    s15 = S('command', 'blt', 'a', 'b', 'L1')
+    #    b1 = B([s11, s12, s13, s14, s15])
+
+    #    s21 = S('command', 'addu', 'c', 'a', 'b')
+    #    s22 = S('command', 'li', 'd', 2)
+    #    b2 = B([s21, s22])
+
+    #    s31 = S('label', 'L1')
+    #    s32 = S('command', 'li', 'c', 4)
+    #    s33 = S('command', 'mult', 'b', 'd')
+    #    s34 = S('command', 'mflo', 'temp')
+    #    s35 = S('command', 'addu', 'return', 'temp', 'c')
+    #    b3 = B([s31, s32, s33, s34, s35])
+
+    #    create_in_out([b1, b2, b3])
+
+    #    self.assertEqual(b1.reach_in, set())
+    #    self.assertEqual(b1.reach_out, set([s11.sid, s12.sid, s13.sid]))
+    #    self.assertEqual(b2.reach_in, set([s11.sid, s12.sid]))
+    #    self.assertEqual(b2.reach_out, set([s12.sid, s22.sid]))
+    #    self.assertEqual(b3.reach_in, set([s12.sid, s22.sid]))
+    #    self.assertEqual(b3.reach_out, set())