Commit ccaa52ac authored by Taddeus Kroes's avatar Taddeus Kroes

Started implementing Dead Code elimination.

parent 0ee8729c
......@@ -3,7 +3,7 @@ from src.dataflow import find_basic_blocks
from redundancies import remove_redundant_jumps, move_1, move_2, move_3, \
move_4, load, shift, add
from advanced import eliminate_common_subexpressions, fold_constants, \
copy_propagation, algebraic_transformations
copy_propagation, algebraic_transformations, eliminate_dead_code
def remove_redundancies(block):
......@@ -32,7 +32,8 @@ def optimize_block(block):
| eliminate_common_subexpressions(block) \
| fold_constants(block) \
| copy_propagation(block)\
| algebraic_transformations(block):
| algebraic_transformations(block) \
| eliminate_dead_code(block):
pass
......
......@@ -40,7 +40,7 @@ def eliminate_common_subexpressions(block):
y = u
The algorithm used is as follows:
- Traverse through the statements in reverse order.
- Traverse through the statements.
- If the statement can be possibly be eliminated, walk further collecting
all other occurrences of the expression until one of the arguments is
assigned in a statement, or the start of the block has been reached.
......@@ -292,3 +292,40 @@ def algebraic_transformations(block):
changed = True
return changed
def eliminate_dead_code(block):
"""
Dead code elimination:
TODO: example...
The algorithm used is as follows:
- Traverse through the statements in reverse order.
- If the statement definition is dead, remove it. A variable is dead if it
is not used in the rest of the block, and is not in the `out' set of the
block.
"""
# TODO: Finish
changed = False
block.reverse_statements()
unused = set()
while not block.end():
s = block.read()
for reg in s.get_def():
if reg in unused:
# Statement is redefined later, so this statement is useless
s.remove = True
#print 'reg %s is in %s, remove:' % (reg, unused), \
# block.pointer - 1, s
else:
unused.add(reg)
unused -= set(s.get_use())
block.apply_filter(lambda s: not hasattr(s, 'remove'))
block.reverse_statements()
return changed
......@@ -71,8 +71,11 @@ class Statement:
def is_arith(self):
"""Check if the statement is an arithmetic operation."""
return self.is_command() \
and re.match('^s(ll|rl|ra)|(add|sub|mflo|abs|neg|slt|sqrt)' \
+ '(u|\.s|\.d)?$', self.name)
and re.match('^s(ll|rl|ra)'
+ '|(mfhi|mflo|abs|neg|and|[xn]?or)'
+ '|(add|sub|slt)u?'
+ '|(add|sub|mult|div|abs|neg|sqrt|c)\.[sd]$', \
self.name)
def is_monop(self):
"""Check if the statement is an unary operation."""
......@@ -89,31 +92,42 @@ class Statement:
return self[-1]
def defines(self, reg):
"""Check if this statement defines the given register."""
def get_def(self):
# TODO: Finish
return (self.is_load() or self.is_arith()) and self[0] == reg
if self.is_load() or self.is_arith():
return self[:1]
def uses(self, reg):
"""Check if this statement uses the given register."""
# TODO: Finish
if self.is_arith():
return reg in self[1:]
return []
if self.is_command('move'):
return self[1] == reg
def get_use(self):
# TODO: Finish with ALL the available commands!
use = []
if self.is_command('lw', 'sb', 'sw', 'dsw'):
if self.is_binop():
use += self[1:]
elif self.is_command('move'):
use.append(self[1])
elif self.is_command('lw', 'sb', 'sw', 'dsw', 's.s', 's.d'):
m = re.match('^\d+\(([^)]+)\)$', self[1])
if m:
return m.group(1) == reg
use.append(m.group(1))
# 'sw' also uses its first argument
if self.name in ['sw', 'dsw']:
return self[0] == reg
use.append(self[0])
elif len(self) == 2: # FIXME: temporary fix, manually add all commands
use.append(self[1])
return False
return use
def defines(self, reg):
"""Check if this statement defines the given register."""
return reg in self.get_def()
def uses(self, reg):
"""Check if this statement uses the given register."""
return reg in self.get_use()
class Block:
......
......@@ -90,6 +90,6 @@ class TestStatement(unittest.TestCase):
self.assertFalse(S('label', 'lw').is_load())
def test_is_arith(self):
self.assertTrue(S('command', 'add', '$1', '$2', '$3').is_arith())
self.assertTrue(S('command', 'addu', '$1', '$2', '$3').is_arith())
self.assertFalse(S('command', 'foo').is_arith())
self.assertFalse(S('label', 'add').is_arith())
self.assertFalse(S('label', 'addu').is_arith())
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