Commit 091fc8d0 authored by Taddeus Kroes's avatar Taddeus Kroes

Implemented variable liveness analysis, renamed the sets for RD.

parent a6dfda54
def create_gen_kill(block):
from copy import copy
def create_use_def(block):
used = set()
defined = set()
# Get the last of each definition series and put in in the `def' set
block.live_gen = set()
block.live_kill = set()
block.use_set = set()
block.def_set = set()
for s in block:
# If a register is used without having been defined in this block,
# yet, put it in the `gen' set
# use[B] is the set of variables whose values may be used in B prior to
# any definition of the variable
for reg in s.get_use():
if reg not in block.live_kill:
block.live_gen.add(reg)
used.add(reg)
if reg not in defined:
block.use_set.add(reg)
# def[B] is the set of variables assigned values in B prior to any use
# of that variable in B
for reg in s.get_def():
block.live_kill.add(reg)
defined.add(reg)
if reg not in used:
block.def_set.add(reg)
def succ(block, known=[]):
"""Recursively find all successors of a node."""
direct = filter(lambda b: b not in known, block.edges_to)
p = copy(direct)
for successor in direct:
p += succ(successor, direct)
return p
def create_in_out(blocks):
for b in blocks:
b.live_in = set()
create_use_def(b)
b.live_in = b.use_set
b.live_out = set()
change = True
while change:
change = False
for b in blocks:
# in[B] = use[B] | (out[B] - def[B])
new_in = b.use_set | (b.live_out - b.def_set)
# out[B] = union of in[S] for S in succ(B)
new_out = set()
for s in succ(b):
new_out |= s.live_in
# Check if either `in' or `out' changed
if new_in != b.live_in:
b.live_in = new_in
change = True
if new_out != b.live_out:
b.live_out = new_out
change = True
from src.dataflow import find_basic_blocks
from src.dataflow import find_basic_blocks, generate_flow_graph
import src.liveness as liveness
import src.reaching_definitions as reaching_definitions
......@@ -51,6 +51,7 @@ def optimize(statements, verbose=0):
blocks = find_basic_blocks(statements)
# Perform dataflow analysis
generate_flow_graph(blocks)
liveness.create_in_out(blocks)
reaching_definitions.create_in_out(blocks)
......
from dataflow import BasicBlock as B, generate_flow_graph
from dataflow import BasicBlock as B
def get_defs(blocks):
......@@ -20,34 +20,31 @@ 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()
block.gen_set = 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)
block.gen_set.add(s.sid)
# Generate kill set
block.reach_kill = set()
block.kill_set = set()
for reg, statement_ids in global_defs.iteritems():
if reg in block_defs:
block.reach_kill |= statement_ids - set([block_defs[reg]])
block.kill_set |= 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)
for b in blocks:
create_gen_kill(b, defs)
b.reach_out = b.reach_gen
b.reach_out = b.gen_set
change = True
......@@ -60,7 +57,7 @@ def create_in_out(blocks):
for pred in b.edges_from:
b.reach_in |= pred.reach_out
new_out = b.reach_gen | (b.reach_in - b.reach_kill)
new_out = b.gen_set | (b.reach_in - b.kill_set)
if new_out != b.reach_out:
b.reach_out = new_out
......
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
from src.dataflow import BasicBlock as B, find_basic_blocks, \
generate_flow_graph
from src.liveness import create_use_def, create_in_out
class TestLiveness(unittest.TestCase):
......@@ -20,44 +21,45 @@ class TestLiveness(unittest.TestCase):
s4 = S('command', 'li', '$4', '0x00000001')
block = B([s1, s2, s3, s4])
create_gen_kill(block)
create_use_def(block)
self.assertEqual(block.live_gen, set(['$1', '$2']))
self.assertEqual(block.live_kill, set(['$3', '$1', '$4']))
self.assertEqual(block.use_set, set(['$1', '$2']))
self.assertEqual(block.def_set, set(['$3', '$4']))
#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', 'beq', 'a', 'b', 'L1')
# b1 = B([s11, s12, s13, s14, s15])
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', 'beq', 'a', 'b', 'L1')
# s21 = S('command', 'addu', 'c', 'a', 'b')
# s22 = S('command', 'li', 'd', 2)
# b2 = B([s21, s22])
s21 = S('command', 'addu', 'c', 'a', 'b')
s22 = S('command', 'li', 'd', 2)
# 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])
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')
# create_in_out([b1, b2, b3])
b1, b2, b3 = find_basic_blocks([s11, s12, s13, s14, s15, s21, s22, \
s31, s32, s33, s34, s35])
# self.assertEqual(b1.live_gen, set([s11.sid, s12.sid, s13.sid, s14.sid]))
# self.assertEqual(b1.live_kill, set([s22.sid]))
generate_flow_graph([b1, b2, b3])
create_in_out([b1, b2, b3])
# self.assertEqual(b2.live_gen, set([s21.sid, s22.sid]))
# self.assertEqual(b2.live_kill, set([s13.sid, s32.sid]))
self.assertEqual(b1.use_set, set())
self.assertEqual(b1.def_set, set(['a', 'b', 'd', 'x']))
# self.assertEqual(b3.live_gen, set([s32.sid, s34.sid, s35.sid]))
# self.assertEqual(b3.live_kill, set([s21.sid]))
self.assertEqual(b2.use_set, set(['a', 'b']))
self.assertEqual(b2.def_set, set(['c', 'd']))
# 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())
self.assertEqual(b3.use_set, set(['b', 'd']))
self.assertEqual(b3.def_set, set(['c', 'temp', 'return']))
self.assertEqual(b1.live_in, set())
self.assertEqual(b1.live_out, set(['a', 'b', 'd']))
self.assertEqual(b2.live_in, set(['a', 'b']))
self.assertEqual(b2.live_out, set(['b', 'd']))
self.assertEqual(b3.live_in, set(['b', 'd']))
self.assertEqual(b3.live_out, set())
......@@ -3,7 +3,8 @@ from copy import copy
from src.optimize.advanced import eliminate_common_subexpressions, \
fold_constants, copy_propagation, algebraic_transformations
from src.statement import Statement as S, Block as B
from src.statement import Statement as S
from src.dataflow import BasicBlock as B, generate_flow_graph
import src.liveness as liveness
......
import unittest
from src.statement import Statement as S
from src.dataflow import BasicBlock as B, find_basic_blocks
from src.dataflow import BasicBlock as B, find_basic_blocks, \
generate_flow_graph
from src.reaching_definitions import get_defs, create_gen_kill, create_in_out
......@@ -35,8 +36,8 @@ class TestReachingDefinitions(unittest.TestCase):
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]))
self.assertEqual(block.gen_set, set([s2.sid, s3.sid, s4.sid]))
self.assertEqual(block.kill_set, set([s1.sid]))
def test_create_in_out(self):
s11 = S('command', 'li', 'a', 3)
......@@ -57,15 +58,16 @@ class TestReachingDefinitions(unittest.TestCase):
b1, b2, b3 = find_basic_blocks([s11, s12, s13, s14, s15, s21, s22, \
s31, s32, s33, s34, s35])
generate_flow_graph([b1, b2, b3])
create_in_out([b1, b2, b3])
self.assertEqual(b1.reach_gen, set([s11.sid, s12.sid, s13.sid,
self.assertEqual(b1.gen_set, 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]))
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]))
self.assertEqual(b1.reach_in, set())
self.assertEqual(b1.reach_out, set([s11.sid, s12.sid, s13.sid,
......
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