Parcourir la source

Merge branch 'master' of github.com:taddeus/peephole

Jayke Meijer il y a 14 ans
Parent
commit
8303fe0b6e
4 fichiers modifiés avec 69 ajouts et 64 suppressions
  1. 14 42
      src/optimize/__init__.py
  2. 32 7
      src/optimize/redundancies.py
  3. 10 9
      tests/test_optimize.py
  4. 13 6
      tests/test_optimize_advanced.py

+ 14 - 42
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

+ 32 - 7
src/optimize/standard.py → 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])

+ 10 - 9
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)
 

+ 13 - 6
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'),