Commit bfe97cf8 authored by Taddeus Kroes's avatar Taddeus Kroes

Started implementing liveness analysis.

parent ccaa52ac
#from copy import copy from copy import copy
from statement import Block from statement import Block
...@@ -25,40 +25,85 @@ class BasicBlock(Block): ...@@ -25,40 +25,85 @@ class BasicBlock(Block):
if block not in self.dominates: if block not in self.dominates:
self.dominates.append(block) self.dominates.append(block)
block.dominated_by.append(self) block.dominated_by.append(self)
def create_gen_kill(self, defs):
# def get_gen(self): used = set()
# for s in self.statements: self_defs = {}
# if s.is_arith():
# self.gen_set.add(s[0]) # Get the last of each definition series and put in in the `def' set
# print 'added: ', s[0] self.gen_set = set()
#
# return self.gen_set for s in reversed(self):
# for reg in s.get_def():
# def get_kill(self): if reg not in self_defs:
## if self.edges_from != []: print 'Found def:', s
# self_defs[reg] = s.sid
# for backw in self.edges_from: self.gen_set.add(s.sid)
# self.kill_set = self.gen_set & backw.kill_set
# # Generate kill set
# self.kill_set = self.kill_set - self.get_gen() self.kill_set = set()
# print 'get_kill_set', self.kill_set
# return self.kill_set for reg, statement_ids in defs.iteritems():
if reg in self_defs:
# def get_in(self): add = statement_ids - set([self_defs[reg]])
# for backw in self.edges_from: else:
# self.in_set = self.in_set | backw.out_set add = statement_ids
# print 'in_set', self.in_set
# return self.in_set self.kill_set |= add
# def get_out(self):
# print 'gen_set', self.gen_set def defs(blocks):
# print 'get_in', self.get_in() # Collect definitions of all registers
# print 'get_kill', self.get_kill() defs = {}
# self.out_set = self.gen_set | (self.get_in() - self.get_kill())
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 slides."""
defs = defs(blocks)
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:
b.in_set = set()
for pred in b.edges_from:
b.in_set |= pred.out_set
oldout = copy(p.out_set)
p.out_set = b.gen_set | (b.in_set - b.kill_set)
if b.out_set != oldout:
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:
......
...@@ -2,12 +2,18 @@ import re ...@@ -2,12 +2,18 @@ import re
class Statement: class Statement:
sid = 1
def __init__(self, stype, name, *args, **kwargs): def __init__(self, stype, name, *args, **kwargs):
self.stype = stype self.stype = stype
self.name = name self.name = name
self.args = list(args) self.args = list(args)
self.options = kwargs self.options = kwargs
# Assign a unique ID to each satement
self.sid = Statement.sid
Statement.sid += 1
def __getitem__(self, n): def __getitem__(self, n):
"""Get an argument.""" """Get an argument."""
return self.args[n] return self.args[n]
...@@ -26,8 +32,8 @@ class Statement: ...@@ -26,8 +32,8 @@ class Statement:
return len(self.args) return len(self.args)
def __str__(self): # pragma: nocover def __str__(self): # pragma: nocover
return '<Statement type=%s name=%s args=%s>' \ return '<Statement sid=%d type=%s name=%s args=%s>' \
% (self.stype, self.name, self.args) % (self.sid, self.stype, self.name, self.args)
def __repr__(self): # pragma: nocover def __repr__(self): # pragma: nocover
return str(self) return str(self)
...@@ -66,7 +72,8 @@ class Statement: ...@@ -66,7 +72,8 @@ class Statement:
def is_load(self): def is_load(self):
"""Check if the statement is a load instruction.""" """Check if the statement is a load instruction."""
return self.is_command() and self.name in ['lw', 'dlw', 'l.s', 'l.d'] return self.is_command() and self.name in ['lw', 'li', 'dlw', 'l.s', \
'l.d']
def is_arith(self): def is_arith(self):
"""Check if the statement is an arithmetic operation.""" """Check if the statement is an arithmetic operation."""
......
...@@ -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, Dag, DagNode, DagLeaf generate_flow_graph, Dag, DagNode, DagLeaf, defs, reaching_definitions
class TestDataflow(unittest.TestCase): class TestDataflow(unittest.TestCase):
...@@ -23,12 +23,12 @@ class TestDataflow(unittest.TestCase): ...@@ -23,12 +23,12 @@ class TestDataflow(unittest.TestCase):
self.assertEqual(map(lambda b: b.statements, find_basic_blocks(s)), \ self.assertEqual(map(lambda b: b.statements, find_basic_blocks(s)), \
[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_gen(self): # def test_get_gen(self):
# b1 = B([S('command', 'add', '$1', '$2', '$3'), \ # b1 = B([S('command', 'add', '$1', '$2', '$3'), \
# S('command', 'add', '$2', '$3', '$4'), \ # S('command', 'add', '$2', '$3', '$4'), \
# S('command', 'add', '$1', '$4', '$5')]) # S('command', 'add', '$1', '$4', '$5')])
# #
# self.assertEqual(b1.get_gen(), ['$1', '$2']) # self.assertEqual(b1.get_gen(), ['$1', '$2'])
# def test_get_out(self): # def test_get_out(self):
...@@ -36,18 +36,18 @@ class TestDataflow(unittest.TestCase): ...@@ -36,18 +36,18 @@ class TestDataflow(unittest.TestCase):
# S('command', 'add', '$2', '$3', '$4'), \ # S('command', 'add', '$2', '$3', '$4'), \
# S('command', 'add', '$1', '$4', '$5'), \ # S('command', 'add', '$1', '$4', '$5'), \
# S('command', 'j', 'b2')]) # S('command', 'j', 'b2')])
# #
# b2 = B([S('command', 'add', '$3', '$5', '$6'), \ # b2 = B([S('command', 'add', '$3', '$5', '$6'), \
# S('command', 'add', '$1', '$2', '$3'), \ # S('command', 'add', '$1', '$2', '$3'), \
# S('command', 'add', '$6', '$4', '$5')]) # S('command', 'add', '$6', '$4', '$5')])
# #
# blocks = [b1, b2] # blocks = [b1, b2]
# #
# # initialize out[B] = gen[B] for every block # # initialize out[B] = gen[B] for every block
# for block in blocks: # for block in blocks:
# block.out_set = block.get_gen() # block.out_set = block.get_gen()
# print 'block.out_set', block.out_set # print 'block.out_set', block.out_set
# #
# generate_flow_graph(blocks) # generate_flow_graph(blocks)
# change = True # change = True
...@@ -112,6 +112,46 @@ class TestDataflow(unittest.TestCase): ...@@ -112,6 +112,46 @@ class TestDataflow(unittest.TestCase):
# #
# self.assertEqualDag(dag, expect) # self.assertEqualDag(dag, expect)
def test_defs(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])
self.assertEqual(defs([block]), {
'$3': set([s1.sid, s3.sid]),
'$1': set([s2.sid]),
'$4': set([s4.sid])
})
#def test_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(defs([block]), {
# '$3': set([s1.sid, s3.sid]),
# '$1': set([s2.sid]),
# '$4': set([s4.sid])
# })
def test_create_gen_kill_gen(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(defs([block]))
self.assertEqual(block.gen_set, set([s2.sid, s3.sid, s4.sid]))
#def test_get_kill_used(self):
# block = B([S('command', 'move', '$1', '$3'),
# S('command', 'add', '$3', '$1', '$2'),
# S('command', 'move', '$1', '$3'),
# S('command', 'move', '$2', '$3')])
# self.assertEqual(block.get_kill(), set())
def assertEqualDag(self, dag1, dag2): def assertEqualDag(self, dag1, dag2):
self.assertEqual(len(dag1.nodes), len(dag2.nodes)) self.assertEqual(len(dag1.nodes), len(dag2.nodes))
......
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