Procházet zdrojové kódy

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

Richard Torenvliet před 14 roky
rodič
revize
15bbae4381
5 změnil soubory, kde provedl 109 přidání a 60 odebrání
  1. 8 4
      report/report.tex
  2. 39 22
      src/optimize/redundancies.py
  3. 3 1
      src/program.py
  4. 5 3
      tests/test_dataflow.py
  5. 54 30
      tests/test_optimize.py

+ 8 - 4
report/report.tex

@@ -246,14 +246,18 @@ the generated Assembly code.
 The writer expects a list of statements, so first the blocks have to be
 concatenated again into a list. After this is done, the list is passed on to
 the writer, which writes the instructions back to Assembly and saves the file
-so we can let xgcc compile it. We also write the original statements to a file,
-so differences in tabs, spaces and newlines do not show up when we check the
-differences between the optimized and non-optimized files.
+so we can let xgcc compile it. The original statements can also written to a
+file, so differences in tabs, spaces and newlines do not show up when checking
+the differences between the optimized and non-optimized files.
 
 \subsection{Execution}
 
 To execute the optimizer, the following command can be given:\\
-\texttt{./main <original file> <optimized file> <rewritten original file>}
+\texttt{./main.py <original file> <optimized file> <rewritten original file>}\\
+There is also a script available that runs the optimizer and automatically
+starts the program \emph{meld}. In meld it is easy to visually compare the
+original file and the optimized file. The command to execute this script is:\\
+\texttt{./run <benchmark name (e.g. whet)>}\\
 
 \section{Testing}
 

+ 39 - 22
src/optimize/redundancies.py

@@ -123,29 +123,46 @@ def add_lw(add, statements):
 
             return True
 
-
 def remove_redundant_jumps(statements):
+    """Remove jump if label follows immediately."""
+    changed = False
+        
+    statements.reset()
+    while not statements.end():
+        s = statements.read()
+
+        #     j $Lx     ->             $Lx:
+        # $Lx:
+        if s.is_command('j'):
+            following = statements.peek()
+            
+            if following.is_label(s[0]):
+                statements.replace(1, [])
+                changed = True
+                    
+    return True
+                        
+def remove_redundant_branch_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])
+    changed = False
 
     statements.reset()
+    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])
+                    changed = True
+                        
+    return changed

+ 3 - 1
src/program.py

@@ -1,6 +1,7 @@
 from statement import Statement as S, Block
 from dataflow import find_basic_blocks, generate_flow_graph
-from optimize.redundancies import remove_redundant_jumps, remove_redundancies
+from optimize.redundancies import remove_redundant_jumps, remove_redundancies,\
+        remove_redundant_branch_jumps
 from optimize.advanced import eliminate_common_subexpressions, \
         fold_constants, copy_propagation, eliminate_dead_code
 from writer import write_statements
@@ -63,6 +64,7 @@ class Program(Block):
     def optimize_global(self):
         """Optimize on a global level."""
         remove_redundant_jumps(self)
+        remove_redundant_branch_jumps(self)
 
     def optimize_blocks(self):
         """Optimize on block level. Keep executing all optimizations until no

+ 5 - 3
tests/test_dataflow.py

@@ -20,9 +20,11 @@ class TestDataflow(unittest.TestCase):
 
     def test_find_basic_blocks(self):
         s = self.statements
-        self.assertEqual(map(lambda b: b.statements, find_basic_blocks(s)), \
-                [B(s[:2]).statements, B(s[2:4]).statements, \
-                 B(s[4:]).statements])
+        self.assertEqual(
+                map(lambda b: b.statements, find_basic_blocks(s)[:-1]),
+                [B(s[:2]).statements, B(s[2:4]).statements,
+                    B(s[4:]).statements]
+        )
 
     def test_generate_flow_graph_simple(self):
         b1 = B([S('command', 'foo'), S('command', 'j', 'b2')])

+ 54 - 30
tests/test_optimize.py

@@ -1,6 +1,7 @@
 import unittest
 
-from src.optimize.redundancies import remove_redundancies, remove_redundant_jumps
+from src.optimize.redundancies import remove_redundancies, \
+    remove_redundant_jumps, remove_redundant_branch_jumps
 from src.program import Program
 from src.statement import Statement as S, Block as B
 
@@ -172,72 +173,95 @@ class TestOptimize(unittest.TestCase):
         self.assertEquals(block.statements, arguments)
         self.assertEquals(block2.statements, arguments2)
         self.assertEquals(block3.statements, arguments3)
+        
+    def test_optimize_block_move_move_true(self):
+        block = B([self.foo,
+                   S('command', 'move', '$regA', '$regB'),
+                   S('command', 'move', '$regB', '$regA'),
+                   self.bar])
+        remove_redundancies(block)
 
-    def test_remove_redundant_jumps_beq_j_true(self):
+        self.assertEquals(block.statements, [self.foo,
+                   S('command', 'move', '$regA', '$regB'),
+                   self.bar])
+
+    def test_optimize_block_mov_mov_false(self):
+        arguments = [self.foo, \
+                     S('command', 'move', '$regA', '$regB'), \
+                     S('command', 'move', '$regB', '$regC'), \
+                     self.bar]
+        block = B(arguments)
+        remove_redundancies(block)
+
+        self.assertEquals(block.statements, arguments)
+        
+    def test_remove_redundant_jumps_true(self):
+        block = B([self.foo,
+                   S('command', 'j', '$L1'),
+                   S('label', '$L1'),
+                   self.bar])
+        
+        remove_redundant_jumps(block)
+       
+        self.assertEqual(block.statements, [self.foo, 
+                                             S('label', '$L1'),
+                                             self.bar])
+                                             
+    def test_remove_redundant_jumps_false(self):
+        arguments = [self.foo,
+                   S('command', 'j', '$L1'),
+                   S('label', '$L2'),
+                   self.bar]
+        block = B(arguments)
+                   
+        remove_redundant_jumps(block)
+       
+        self.assertEqual(block.statements, arguments)
+        
+    def test_remove_redundant_branch_jumps_beq_j_true(self):
         block = B([self.foo,
                    S('command', 'beq', '$regA', '$regB', '$Lx'),
                    S('command', 'j', '$Ly'),
                    S('label', '$Lx'),
                    self.bar])
-        remove_redundant_jumps(block)
+        remove_redundant_branch_jumps(block)
 
         self.assertEquals(block.statements, [self.foo,
                    S('command', 'bne', '$regA', '$regB', '$Ly'),
                    S('label', '$Lx'),
                    self.bar])
 
-    def test_remove_redundant_jumps_beq_j_false(self):
+    def test_remove_redundant_branch_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)
-        remove_redundant_jumps(block)
+        remove_redundant_branch_jumps(block)
 
         self.assertEquals(block.statements, arguments)
 
-    def test_remove_redundant_jumps_bne_j_true(self):
+    def test_remove_redundant_branch_jumps_bne_j_true(self):
         block = B([self.foo,
                    S('command', 'bne', '$regA', '$regB', '$Lx'),
                    S('command', 'j', '$Ly'),
                    S('label', '$Lx'),
                    self.bar])
-        remove_redundant_jumps(block)
+        remove_redundant_branch_jumps(block)
 
         self.assertEquals(block.statements, [self.foo,
                    S('command', 'beq', '$regA', '$regB', '$Ly'),
                    S('label', '$Lx'),
                    self.bar])
 
-    def test_remove_redundant_jumps_bne_j_false(self):
+    def test_remove_redundant_branch_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)
-        remove_redundant_jumps(block)
-
-        self.assertEquals(block.statements, arguments)
-
-    def test_optimize_block_move_move_true(self):
-        block = B([self.foo,
-                   S('command', 'move', '$regA', '$regB'),
-                   S('command', 'move', '$regB', '$regA'),
-                   self.bar])
-        remove_redundancies(block)
-
-        self.assertEquals(block.statements, [self.foo,
-                   S('command', 'move', '$regA', '$regB'),
-                   self.bar])
-
-    def test_optimize_block_mov_mov_false(self):
-        arguments = [self.foo, \
-                     S('command', 'move', '$regA', '$regB'), \
-                     S('command', 'move', '$regB', '$regC'), \
-                     self.bar]
-        block = B(arguments)
-        remove_redundancies(block)
+        remove_redundant_branch_jumps(block)
 
         self.assertEquals(block.statements, arguments)