Commit 45898435 authored by Jayke Meijer's avatar Jayke Meijer

Moved non-jump optimizations to block optimization.

parent 1ab45a98
......@@ -7,6 +7,45 @@ def optimize_global(statements):
"""Optimize statement sequences on a global level."""
old_len = -1
while old_len != len(statements):
old_len = len(statements)
while not statements.end():
s = statements.read()
# beq/bne ..., $Lx -> bne/beq ..., $Ly
# j $Ly $Lx:
# $Lx:
if s.is_command('beq') or s.is_command('bne'):
following = statements.peek(2)
if len(following) == 2:
j, label = following
if j.is_command('j') and label.is_label(s[2]):
if s.is_command('beq'):
s.name = 'bne'
else:
s.name = 'beq'
s[2] = j[0]
statements.replace(3, [s, label])
def optimize_blocks(blocks):
"""Call the optimizer for each basic block. Do this several times until
no more optimizations are achieved."""
optimized = []
for block in blocks:
optimize_block(block)
return blocks
def optimize_block(statements):
"""Optimize a basic block."""
old_len = -1
while old_len != len(statements):
old_len = len(statements)
......@@ -67,57 +106,15 @@ def optimize_global(statements):
lw[-1] = str(s[2]) + lw[-1][1:]
statements.replace(2, [lw])
continue
# move $RegA, $RegB -> move $RegA, $RegB
# move $RegB, $RegA
if s.is_command('move'):
move = statements.peek()
# beq/bne ..., $Lx -> bne/beq ..., $Ly
# j $Ly $Lx:
# $Lx:
if s.is_command('beq') or s.is_command('bne'):
following = statements.peek(2)
if len(following) == 2:
j, label = following
if j.is_command('j') and label.is_label(s[2]):
if s.is_command('beq'):
s.name = 'bne'
else:
s.name = 'beq'
s[2] = j[0]
statements.replace(3, [s, label])
def optimize_blocks(blocks):
"""Call the optimizer for each basic block. Do this several times until
no more optimizations are achieved."""
changed = True
while changed:
changed = False
optimized = []
for block in blocks:
block_changed, b = optimize_block(block)
optimized.append(b)
if block_changed:
changed = True
blocks = optimized
return reduce(lambda a, b: a + b, blocks, [])
def optimize_block(statements):
"""Optimize a basic block."""
changed = False
output_statements = []
for statement in statements:
new_statement = statement
output_statements.append(new_statement)
return changed, output_statements
if move.is_command('move') and move[0] == s[1] and \
move[1] == s[0]:
statements.replace(2, [s])
def optimize(statements, verbose=0):
......@@ -130,8 +127,7 @@ def optimize(statements, verbose=0):
# Optimize basic blocks
basic_blocks = find_basic_blocks(statements)
# blocks = optimize_blocks(basic_blocks)
blocks = basic_blocks
blocks = optimize_blocks(basic_blocks)
block_statements = map(lambda b: b.statements, blocks)
opt_blocks = reduce(lambda a, b: a + b, block_statements)
b = len(opt_blocks)
......
......@@ -110,7 +110,10 @@ class Block:
def peek(self, count=1):
"""Read the statements until an offset from the current pointer
position."""
position."""
if self.end():
return Statement('empty', '') if count == 1 else []
return self.statements[self.pointer] if count == 1 \
else self.statements[self.pointer:self.pointer + count]
......
import unittest
from src.optimize import optimize_global
from src.optimize import optimize_global, optimize_block, optimize_blocks
from src.statement import Statement as S, Block as B
......@@ -9,26 +9,26 @@ class TestOptimize(unittest.TestCase):
def setUp(self):
pass
def test_optimize_global_movaa(self):
def test_optimize_block_movaa(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
block = B([foo,
S('command', 'move', '$regA', '$regA'),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo, bar])
def test_optimize_global_movab(self):
def test_optimize_block_movab(self):
foo = S('command', 'foo')
move = S('command', 'move', '$regA', '$regB')
bar = S('command', 'bar')
block = B([foo,
move,
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo, move, bar])
def test_optimize_global_movinst_true(self):
def test_optimize_block_movinst_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -36,12 +36,12 @@ class TestOptimize(unittest.TestCase):
S('command', 'move', '$regA', '$regB'),
S('command', 'addu', '$regA', '$regA', 2),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo,
S('command', 'addu', '$regA', '$regB', 2),
bar])
def test_optimize_global_movinst_false(self):
def test_optimize_block_movinst_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
statements = [foo, \
......@@ -50,10 +50,10 @@ class TestOptimize(unittest.TestCase):
bar]
block = B(statements)
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, statements)
def test_optimize_global_instr_mov_jal_true(self):
def test_optimize_block_instr_mov_jal_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -62,14 +62,14 @@ class TestOptimize(unittest.TestCase):
S('command', 'move', '$4', '$regA'),
S('command', 'jal', 'L1'),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo,
S('command', 'addu', '$4', '$regC', 2),
S('command', 'jal', 'L1'),
bar])
def test_optimize_global_instr_mov_jal_false(self):
def test_optimize_block_instr_mov_jal_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -79,11 +79,11 @@ class TestOptimize(unittest.TestCase):
S('command', 'jal', 'L1'), \
bar]
block = B(arguments)
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, arguments)
def test_optimize_global_sw_ld_true(self):
def test_optimize_block_sw_ld_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -91,13 +91,13 @@ class TestOptimize(unittest.TestCase):
S('command', 'sw', '$regA', '$regB'),
S('command', 'ld', '$regA', '$regC'),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo,
S('command', 'sw', '$regA', '$regB'),
bar])
def test_optimize_global_sw_ld_false(self):
def test_optimize_block_sw_ld_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -106,23 +106,23 @@ class TestOptimize(unittest.TestCase):
S('command', 'ld', '$regD', '$regC'), \
bar]
block = B(arguments)
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, arguments)
def test_optimize_global_shift_true(self):
def test_optimize_block_shift_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
block = B([foo,
S('command', 'sll', '$regA', '$regA', 0),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo,
bar])
def test_optimize_global_shift_false(self):
def test_optimize_block_shift_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -130,7 +130,7 @@ class TestOptimize(unittest.TestCase):
S('command', 'sll', '$regA', '$regB', 0), \
bar]
block = B(arguments)
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, arguments)
......@@ -138,11 +138,11 @@ class TestOptimize(unittest.TestCase):
S('command', 'sll', '$regA', '$regA', 1), \
bar]
block2 = B(arguments2)
optimize_global(block2)
optimize_block(block2)
self.assertEquals(block2.statements, arguments2)
def test_optimize_global_add_lw_true(self):
def test_optimize_block_add_lw_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -150,13 +150,13 @@ class TestOptimize(unittest.TestCase):
S('command', 'add', '$regA', '$regA', 10),
S('command', 'lw', '$regB', '0($regA)'),
bar])
optimize_global(block)
optimize_block(block)
self.assertEquals(block.statements, [foo,
S('command', 'lw', '$regB', '10($regA)'),
bar])
def test_optimize_global_add_lw_false(self):
def test_optimize_block_add_lw_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
......@@ -165,7 +165,7 @@ class TestOptimize(unittest.TestCase):
S('command', 'lw', '$regB', '0($regC)'), \
bar]
block = B(arguments)
optimize_global(block)
optimize_block(block)
arguments2 = [foo, \
S('command', 'add', '$regA', '$regB', 10), \
......@@ -178,7 +178,7 @@ class TestOptimize(unittest.TestCase):
S('command', 'lw', '$regB', '1($regA)'), \
bar]
block3 = B(arguments3)
optimize_global(block3)
optimize_block(block3)
self.assertEquals(block.statements, arguments)
self.assertEquals(block2.statements, arguments2)
......@@ -243,3 +243,42 @@ class TestOptimize(unittest.TestCase):
optimize_global(block)
self.assertEquals(block.statements, arguments)
def test_optimize_block_move_move_true(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
block = B([foo,
S('command', 'move', '$regA', '$regB'),
S('command', 'move', '$regB', '$regA'),
bar])
optimize_block(block)
self.assertEquals(block.statements, [foo,
S('command', 'move', '$regA', '$regB'),
bar])
def test_optimize_block_mov_mov_false(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
arguments = [foo, \
S('command', 'move', '$regA', '$regB'), \
S('command', 'move', '$regB', '$regC'), \
bar]
block = B(arguments)
optimize_block(block)
self.assertEquals(block.statements, arguments)
def test_optimize_blocks(self):
foo = S('command', 'foo')
bar = S('command', 'bar')
block1 = B([foo, bar])
block2 = B([bar, foo])
blocks_in = [block1, block2];
blocks_out = optimize_blocks(blocks_in)
self.assertEquals(blocks_in, blocks_out)
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