diff --git a/src/optimize/__init__.py b/src/optimize/__init__.py index 46b72ea48ac6b02918ac1eb4cf2c3f69f9ec6c37..bd28f0d61006893c4971eae711c48d2a3c204a96 100644 --- a/src/optimize/__init__.py +++ b/src/optimize/__init__.py @@ -1,63 +1,35 @@ from src.dataflow import find_basic_blocks -from standard import redundant_move_1, redundant_move_2, \ - redundant_move_3, redundant_move_4, redundant_load, \ - redundant_shift, redundant_add +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 + copy_propagation -def optimize_global(statements): - """Optimize statement sequences on a global level.""" +def remove_redundancies(block): + """Execute all functions that remove redundant statements.""" + callbacks = [move_1, move_2, move_3, move_4, load, shift, add] old_len = -1 + changed = False - 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', 'bne'): - following = statements.peek(2) - - if len(following) == 2: - j, label = following - - if j.is_command('j') and label.is_label(s[2]): - s.name = 'bne' if s.is_command('beq') else 'beq' - s[2] = j[0] - statements.replace(3, [s, label]) - - -def optimize_block(block): - """Optimize a basic block.""" - standard = [redundant_move_1, redundant_move_2, redundant_move_3, \ - redundant_move_4, redundant_load, redundant_shift, \ - redundant_add] - old_len = -1 - - # Standard optimizations while old_len != len(block): old_len = len(block) while not block.end(): s = block.read() - for callback in standard: + for callback in callbacks: if callback(s, block): + changed = True break - # Advanced optimizations - #changed = True + return changed - #while changed: - # changed = eliminate_common_subexpressions(block) \ - # or fold_constants(block) - while eliminate_common_subexpressions(block) \ +def optimize_block(block): + """Optimize a basic block.""" + while remove_redundancies(block) \ + | eliminate_common_subexpressions(block) \ | fold_constants(block) \ | copy_propagation(block): pass diff --git a/src/optimize/standard.py b/src/optimize/redundancies.py similarity index 68% rename from src/optimize/standard.py rename to src/optimize/redundancies.py index 1e224ce6ceb97263dd94a07dcdcada8bd18c8aa4..7d1db362afd7c665e8f5763394a9c860fc252da4 100644 --- a/src/optimize/standard.py +++ b/src/optimize/redundancies.py @@ -1,7 +1,7 @@ import re -def redundant_move_1(mov, statements): +def move_1(mov, statements): """ mov $regA, $regA -> --- remove it """ @@ -11,7 +11,7 @@ def redundant_move_1(mov, statements): return True -def redundant_move_2(mov, statements): +def move_2(mov, statements): """ mov $regA, $regB -> instr $regA, $regB, ... instr $regA, $regA, ... @@ -26,7 +26,7 @@ def redundant_move_2(mov, statements): return True -def redundant_move_3(ins, statements): +def move_3(ins, statements): """ instr $regA, ... -> instr $4, ... mov $4, $regA jal XX @@ -47,7 +47,7 @@ def redundant_move_3(ins, statements): return True -def redundant_move_4(mov1, statements): +def move_4(mov1, statements): """ mov $RegA, $RegB -> move $RegA, $RegB mov $RegB, $RegA @@ -62,7 +62,7 @@ def redundant_move_4(mov1, statements): return True -def redundant_load(sw, statements): +def load(sw, statements): """ sw $regA, XX -> sw $regA, XX ld $regA, XX @@ -76,7 +76,7 @@ def redundant_load(sw, statements): return True -def redundant_shift(shift, statements): +def shift(shift, statements): """ shift $regA, $regA, 0 -> --- remove it """ @@ -86,7 +86,7 @@ def redundant_shift(shift, statements): return True -def redundant_add(add, statements): +def add(add, statements): """ add $regA, $regA, X -> lw ..., X($regA) lw ..., 0($regA) @@ -99,3 +99,28 @@ def redundant_add(add, statements): statements.replace(2, [lw]) return True + + +def remove_redundant_jumps(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', 'bne'): + following = statements.peek(2) + + if len(following) == 2: + j, label = following + + if j.is_command('j') and label.is_label(s[2]): + s.name = 'bne' if s.is_command('beq') else 'beq' + s[2] = j[0] + statements.replace(3, [s, label]) diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 6d6b9874f827457f823c5fe1f5320f11befb3525..8bfbc3715db5c2e490cbbf54fbdae92405a6536d 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -1,6 +1,7 @@ import unittest -from src.optimize import optimize_global, optimize_block +from src.optimize.redundancies import remove_redundant_jumps +from src.optimize import optimize_block from src.statement import Statement as S, Block as B @@ -155,51 +156,51 @@ class TestOptimize(unittest.TestCase): self.assertEquals(block2.statements, arguments2) self.assertEquals(block3.statements, arguments3) - def test_optimize_global_beq_j_true(self): + def test_remove_redundant_jumps_beq_j_true(self): block = B([self.foo, S('command', 'beq', '$regA', '$regB', '$Lx'), S('command', 'j', '$Ly'), S('label', '$Lx'), self.bar]) - optimize_global(block) + remove_redundant_jumps(block) self.assertEquals(block.statements, [self.foo, S('command', 'bne', '$regA', '$regB', '$Ly'), S('label', '$Lx'), self.bar]) - def test_optimize_global_beq_j_false(self): + def test_remove_redundant_jumps_beq_j_false(self): arguments = [self.foo, \ S('command', 'beq', '$regA', '$regB', '$Lz'), \ S('command', 'j', '$Ly'), \ S('label', '$Lx'), \ self.bar] block = B(arguments) - optimize_global(block) + remove_redundant_jumps(block) self.assertEquals(block.statements, arguments) - def test_optimize_global_bne_j_true(self): + def test_remove_redundant_jumps_bne_j_true(self): block = B([self.foo, S('command', 'bne', '$regA', '$regB', '$Lx'), S('command', 'j', '$Ly'), S('label', '$Lx'), self.bar]) - optimize_global(block) + remove_redundant_jumps(block) self.assertEquals(block.statements, [self.foo, S('command', 'beq', '$regA', '$regB', '$Ly'), S('label', '$Lx'), self.bar]) - def test_optimize_global_bne_j_false(self): + def test_remove_redundant_jumps_bne_j_false(self): arguments = [self.foo, \ S('command', 'bne', '$regA', '$regB', '$Lz'), \ S('command', 'j', '$Ly'), \ S('label', '$Lx'), \ self.bar] block = B(arguments) - optimize_global(block) + remove_redundant_jumps(block) self.assertEquals(block.statements, arguments) diff --git a/tests/test_optimize_advanced.py b/tests/test_optimize_advanced.py index 84da77dec61a83ec5ba98bbb5d18774b7c12ec7b..936f0046423ac5b9632114cc2cef097bf0b78477 100644 --- a/tests/test_optimize_advanced.py +++ b/tests/test_optimize_advanced.py @@ -11,37 +11,44 @@ class TestOptimizeAdvanced(unittest.TestCase): self.foo = S('command', 'foo') self.bar = S('command', 'bar') + def tearDown(self): + del self.foo + del self.bar + def test_eliminate_common_subexpressions(self): pass - + + def test_fold_constants(self): + pass + def test_copy_propagation_true(self): block = B([self.foo, S('command', 'move', '$1', '$2'), self.foo, S('command', 'addu', '$3', '$1', '$4'), self.bar]) - + self.assertTrue(copy_propagation(block)) self.assertEqual(block.statements, [self.foo, S('command', 'move', '$1', '$2'), self.foo, S('command', 'addu', '$3', '$2', '$4'), self.bar]) - + def test_copy_propagation_overwrite(self): block = B([self.foo, \ S('command', 'move', '$1', '$2'), S('command', 'move', '$1', '$5'), S('command', 'addu', '$3', '$1', '$4'), self.bar]) - + self.assertTrue(copy_propagation(block)) self.assertEqual(block.statements, [self.foo, S('command', 'move', '$1', '$2'), S('command', 'move', '$1', '$5'), S('command', 'addu', '$3', '$5', '$4'), self.bar]) - + def test_copy_propagation_false(self): arguments = [self.foo, S('command', 'move', '$1', '$2'), @@ -52,7 +59,7 @@ class TestOptimizeAdvanced(unittest.TestCase): block = B(arguments) self.assertFalse(copy_propagation(block)) self.assertEqual(block.statements, arguments) - + def test_copy_propagation_false_severalmoves(self): arguments = [self.foo, S('command', 'move', '$1', '$2'),