diff --git a/QUESTIONS b/QUESTIONS deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/QUESTIONS +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/optimize.py b/src/optimize.py index bba4775bedaacbc05aa7d114195654d7d2849270..88ed60e5299c459785fed36896b77fdbc54250e6 100644 --- a/src/optimize.py +++ b/src/optimize.py @@ -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) @@ -147,7 +143,7 @@ def optimize(statements, verbose=0): print 'Original statements: %d' % o print 'After global optimization: %d' % g print 'After basic blocks optimization: %d' % b - print 'Speedup: %d (%d%%)' \ - % (b - o, int((b - o) / o * 100)) + print 'Optimization: %d (%d%%)' \ + % (b - o, int((b - o) / float(o) * 100)) return opt_blocks diff --git a/src/statement.py b/src/statement.py index db0ce023697a5ed447252500af3fade051704a0d..87dea3ea134e9af73bab1151f570d0399e111575 100644 --- a/src/statement.py +++ b/src/statement.py @@ -118,7 +118,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] diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 93000e1e97f9502c3909fb11021ebc08dbf5dacf..b3025ebf7aecfc2888602cb6c2f331c5fce03adc 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -1,6 +1,6 @@ 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)