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
......@@ -26,38 +26,83 @@ class BasicBlock(Block):
self.dominates.append(block)
block.dominated_by.append(self)
def create_gen_kill(self, defs):
used = set()
self_defs = {}
# def get_gen(self):
# for s in self.statements:
# if s.is_arith():
# self.gen_set.add(s[0])
# print 'added: ', s[0]
#
# return self.gen_set
#
# def get_kill(self):
## if self.edges_from != []:
#
# for backw in self.edges_from:
# self.kill_set = self.gen_set & backw.kill_set
#
# self.kill_set = self.kill_set - self.get_gen()
# print 'get_kill_set', self.kill_set
# return self.kill_set
# 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:
print 'Found def:', s
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:
add = statement_ids - set([self_defs[reg]])
else:
add = statement_ids
self.kill_set |= add
def 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 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 get_in(self):
# for backw in self.edges_from:
# self.in_set = self.in_set | backw.out_set
# print 'in_set', self.in_set
# return self.in_set
# def get_out(self):
# print 'gen_set', self.gen_set
# print 'get_in', self.get_in()
# print 'get_kill', self.get_kill()
# self.out_set = self.gen_set | (self.get_in() - self.get_kill())
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):
......
......@@ -2,12 +2,18 @@ import re
class Statement:
sid = 1
def __init__(self, stype, name, *args, **kwargs):
self.stype = stype
self.name = name
self.args = list(args)
self.options = kwargs
# Assign a unique ID to each satement
self.sid = Statement.sid
Statement.sid += 1
def __getitem__(self, n):
"""Get an argument."""
return self.args[n]
......@@ -26,8 +32,8 @@ class Statement:
return len(self.args)
def __str__(self): # pragma: nocover
return '<Statement type=%s name=%s args=%s>' \
% (self.stype, self.name, self.args)
return '<Statement sid=%d type=%s name=%s args=%s>' \
% (self.sid, self.stype, self.name, self.args)
def __repr__(self): # pragma: nocover
return str(self)
......@@ -66,7 +72,8 @@ class Statement:
def is_load(self):
"""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):
"""Check if the statement is an arithmetic operation."""
......
......@@ -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, Dag, DagNode, DagLeaf
generate_flow_graph, Dag, DagNode, DagLeaf, defs, reaching_definitions
class TestDataflow(unittest.TestCase):
......@@ -112,6 +112,46 @@ class TestDataflow(unittest.TestCase):
#
# 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):
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