Skip to content
Snippets Groups Projects
Commit c8dba202 authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

Debugged Dead Code Elimination.

parent 74461223
No related branches found
No related tags found
No related merge requests found
from src.statement import Statement as S from src.statement import Statement as S
def create_variable(): def reg_dead_in(var, context):
return '$15' """Check if a register is `dead' in a given list of statements."""
# TODO: Finish
for s in context:
if s.defines(var) or s.uses(var):
return False
return True
def find_free_reg(context):
"""Find a temporary register that is free in a given list of statements."""
for i in xrange(8):
tmp = '$t%d' % i
if reg_dead_in(tmp, context):
return tmp
raise Exception('No temporary register is available.')
def eliminate_common_subexpressions(block): def eliminate_common_subexpressions(block):
...@@ -44,19 +61,22 @@ def eliminate_common_subexpressions(block): ...@@ -44,19 +61,22 @@ def eliminate_common_subexpressions(block):
# Replace a similar expression by a move instruction # Replace a similar expression by a move instruction
if s2.name == s.name and s2[1:] == args: if s2.name == s.name and s2[1:] == args:
if not new_reg: if not new_reg:
new_reg = create_variable() new_reg = find_free_reg(block[:pointer])
block.replace(1, [S('command', 'move', s2[0], new_reg)]) block.replace(1, [S('command', 'move', s2[0], new_reg)])
last = block.pointer last = block.pointer
# Insert an additional expression with a new destination address
if last:
block.insert(S('command', s.name, [new_reg] + args), last)
found = True
# Reset pointer to and continue from the original statement # Reset pointer to and continue from the original statement
block.pointer = pointer block.pointer = pointer
if last:
# Insert an additional expression with a new destination address
block.insert(S('command', s.name, *([new_reg] + args)), last)
# Replace the original expression with a move statement
block.replace(1, [S('command', 'move', s[0], new_reg)])
found = True
block.reverse_statements() block.reverse_statements()
return found return found
...@@ -139,7 +159,7 @@ def fold_constants(block): ...@@ -139,7 +159,7 @@ def fold_constants(block):
if s.name == 'div': if s.name == 'div':
result = to_hex(rs_val / rt_val) result = to_hex(rs_val / rt_val)
block.replace(1, [S('command', 'li', result)]) block.replace(1, [S('command', 'li', rd, result)])
register[rd] = result register[rd] = result
found = True found = True
elif rt_known: elif rt_known:
...@@ -186,7 +206,7 @@ def copy_propagation(block): ...@@ -186,7 +206,7 @@ def copy_propagation(block):
break break
elif len(s) == 3 and s[0] in moves_to: elif len(s) == 3 and s[0] in moves_to:
# The result gets overwritten, so remove the data from the list. # The result gets overwritten, so remove the data from the list.
i = 0 i = 0
while i < len(moves_to): while i < len(moves_to):
if moves_to[i] == s[0]: if moves_to[i] == s[0]:
del moves_to[i] del moves_to[i]
...@@ -200,16 +220,16 @@ def copy_propagation(block): ...@@ -200,16 +220,16 @@ def copy_propagation(block):
if s[1] == moves_to[i]: if s[1] == moves_to[i]:
s[1] = moves_from[i] s[1] = moves_from[i]
break break
if s[2] == moves_to[i]: if s[2] == moves_to[i]:
s[2] = moves_from[i] s[2] = moves_from[i]
break break
changed = True changed = True
return changed return changed
def algebraic_transformations(block): def algebraic_transformations(block):
""" """
Change ineffective or useless algebraic transformations. Handled are: Change ineffective or useless algebraic transformations. Handled are:
...@@ -219,11 +239,11 @@ def algebraic_transformations(block): ...@@ -219,11 +239,11 @@ def algebraic_transformations(block):
- x = x * 2 -> x = x << 1 - x = x * 2 -> x = x << 1
""" """
changed = False changed = False
while not block.end(): while not block.end():
changed = True changed = True
s = block.read() s = block.read()
if (s.is_command('addu') or s.is_command('subu')) and s[2] == 0: if (s.is_command('addu') or s.is_command('subu')) and s[2] == 0:
block.replace(1, []) block.replace(1, [])
elif s.is_command('mult') and s[2] == 1: elif s.is_command('mult') and s[2] == 1:
...@@ -233,5 +253,5 @@ def algebraic_transformations(block): ...@@ -233,5 +253,5 @@ def algebraic_transformations(block):
block.replace(1, [new_command]) block.replace(1, [new_command])
else: else:
changed = False changed = False
return changed return changed
...@@ -88,6 +88,16 @@ class Statement: ...@@ -88,6 +88,16 @@ class Statement:
return self[-1] return self[-1]
def defines(self, reg):
"""Check if this statement defines the given register."""
# TODO: Finish
return (self.is_load() or self.is_arith()) and self[0] == reg
def uses(self, reg):
"""Check if this statement uses the given register."""
# TODO: Finish
return (self.is_load() or self.is_arith()) and reg in self[1:]
class Block: class Block:
def __init__(self, statements=[]): def __init__(self, statements=[]):
......
import unittest import unittest
from copy import copy
from src.optimize.advanced import eliminate_common_subexpressions, \ from src.optimize.advanced import eliminate_common_subexpressions, \
fold_constants, copy_propagation, algebraic_transformations fold_constants, copy_propagation, algebraic_transformations
...@@ -15,8 +16,22 @@ class TestOptimizeAdvanced(unittest.TestCase): ...@@ -15,8 +16,22 @@ class TestOptimizeAdvanced(unittest.TestCase):
del self.foo del self.foo
del self.bar del self.bar
def test_eliminate_common_subexpressions(self): def test_eliminate_common_subexpressions_simple(self):
pass b = B([S('command', 'addu', '$regC', '$regA', '$regB'),
S('command', 'addu', '$regD', '$regA', '$regB')])
e = [S('command', 'addu', '$t0', '$regA', '$regB'), \
S('command', 'move', '$regC', '$t0'), \
S('command', 'move', '$regD', '$t0')]
eliminate_common_subexpressions(b)
self.assertEqual(b.statements, e)
def test_eliminate_common_subexpressions_assigned(self):
b = B([S('command', 'addu', '$regC', '$regA', '$regB'),
S('command', 'li', '$regA', '0x00000001'),
S('command', 'addu', '$regD', '$regA', '$regB')])
e = copy(b.statements)
eliminate_common_subexpressions(b)
self.assertEqual(b.statements, e)
def test_fold_constants(self): def test_fold_constants(self):
pass pass
...@@ -70,12 +85,12 @@ class TestOptimizeAdvanced(unittest.TestCase): ...@@ -70,12 +85,12 @@ class TestOptimizeAdvanced(unittest.TestCase):
block = B(arguments) block = B(arguments)
self.assertFalse(copy_propagation(block)) self.assertFalse(copy_propagation(block))
self.assertEqual(block.statements, arguments) self.assertEqual(block.statements, arguments)
def test_algebraic_transforms_add0(self): def test_algebraic_transforms_add0(self):
block = B([self.foo, block = B([self.foo,
S('command', 'addu', '$1', '$2', 0), S('command', 'addu', '$1', '$2', 0),
self.bar]) self.bar])
# self.assertTrue(copy_propagation(block)) # self.assertTrue(copy_propagation(block))
algebraic_transformations(block) algebraic_transformations(block)
self.assertEqual(block.statements, [self.foo, self.assertEqual(block.statements, [self.foo,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment