Commit 6924b53c authored by Taddeus Kroes's avatar Taddeus Kroes

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

parent 053da966
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
...@@ -9,10 +9,6 @@ class BasicBlock(Block): ...@@ -9,10 +9,6 @@ class BasicBlock(Block):
self.dominates = [] self.dominates = []
self.dominated_by = [] 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): def add_edge_to(self, block):
if block not in self.edges_to: if block not in self.edges_to:
...@@ -24,90 +20,6 @@ class BasicBlock(Block): ...@@ -24,90 +20,6 @@ class BasicBlock(Block):
self.dominates.append(block) self.dominates.append(block)
block.dominated_by.append(self) 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): def find_leaders(statements):
"""Determine the leaders, which are: """Determine the leaders, which are:
...@@ -169,104 +81,3 @@ def generate_flow_graph(blocks): ...@@ -169,104 +81,3 @@ def generate_flow_graph(blocks):
b.add_edge_to(blocks[i + 1]) b.add_edge_to(blocks[i + 1])
elif i < len(blocks) - 1: elif i < len(blocks) - 1:
b.add_edge_to(blocks[i + 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
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
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
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
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)
...@@ -2,8 +2,7 @@ import unittest ...@@ -2,8 +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, Dag, DagNode, DagLeaf, get_defs, \ generate_flow_graph
reaching_definitions
class TestDataflow(unittest.TestCase): class TestDataflow(unittest.TestCase):
...@@ -25,90 +24,6 @@ class TestDataflow(unittest.TestCase): ...@@ -25,90 +24,6 @@ class TestDataflow(unittest.TestCase):
[B(s[:2]).statements, B(s[2:4]).statements, \ [B(s[:2]).statements, B(s[2:4]).statements, \
B(s[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): def test_generate_flow_graph_simple(self):
b1 = B([S('command', 'foo'), S('command', 'j', 'b2')]) b1 = B([S('command', 'foo'), S('command', 'j', 'b2')])
b2 = B([S('label', 'b2'), S('command', 'bar')]) b2 = B([S('label', 'b2'), S('command', 'bar')])
...@@ -129,54 +44,3 @@ class TestDataflow(unittest.TestCase): ...@@ -129,54 +44,3 @@ 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_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)
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())
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())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment