Преглед изворни кода

Added common subexpression elimination (unfinished and untested).

Taddeus Kroes пре 14 година
родитељ
комит
effe72670a
4 измењених фајлова са 96 додато и 22 уклоњено
  1. 16 22
      src/optimize/__init__.py
  2. 56 0
      src/optimize/advanced.py
  3. 11 0
      src/statement.py
  4. 13 0
      tests/test_optimize_advanced.py

+ 16 - 22
src/optimize/__init__.py

@@ -3,6 +3,7 @@ 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 advanced import eliminate_common_subexpressions, fold_constants
 
 
 def optimize_global(statements):
@@ -30,41 +31,34 @@ def optimize_global(statements):
                         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."""
-#    for block in blocks:
-#        optimize_block(block)
-#
-#    return blocks
-
-
-def optimize_block(statements):
+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
 
-    while old_len != len(statements):
-        old_len = len(statements)
-
-        while not statements.end():
-            s = statements.read()
+    # Standard optimizations
+    while old_len != len(block):
+        old_len = len(block)
 
-            #
-            cont = False
+        while not block.end():
+            s = block.read()
 
             for callback in standard:
-                if callback(s, statements):
-                    cont = True
+                if callback(s, block):
                     break
 
-            if cont:
-                continue
+    # Advanced optimizations
+    #changed = True
 
-            # Other optimizations...
+    #while changed:
+    #    changed = eliminate_common_subexpressions(block) \
+    #              or fold_constants(block)
 
+    while eliminate_common_subexpressions(block) \
+            | fold_constants(block):
+        pass
 
 def optimize(statements, verbose=0):
     """optimization wrapper function, calls global and basic-block level

+ 56 - 0
src/optimize/advanced.py

@@ -0,0 +1,56 @@
+from src.statement import Statement as S
+
+
+def eliminate_common_subexpressions(block):
+    """
+    Common subexpression elimination:
+    - Traverse through the statements in reverse order.
+    - If the statement can be possibly be eliminated, walk further collecting
+      all other occurrences of the expression until one of the arguments is
+      assigned in a statement, or the start of the block has been reached.
+    - If one or more occurrences were found, insert the expression with a new
+      destination address before the last found occurrence and change all
+      occurrences to a move instruction from that address.
+    """
+    found = False
+    block.reverse_statements()
+
+    while not block.end():
+        s = block.read()
+
+        if s.is_arith():
+            pointer = block.pointer
+            last = False
+            args = s[1:]
+
+            # Collect similar statements
+            while not block.end():
+                s2 = block.read()
+
+                # Stop if one of the arguments is assigned
+                if len(s2) and s2[0] in args:
+                    break
+
+                # Replace a similar expression by a move instruction
+                if s2.name == s.name and s2[1:] == args:
+                    block.replace(1, [S('command', 'move', s2[0], new_reg)])
+                    last = block.pointer
+
+            # Insert an additional expression with a new destination address
+            if last:
+                block.insert(S('command', s.name, [new_reg] + args), last)
+                found = True
+
+            # Reset pointer to and continue from the original statement
+            block.pointer = pointer
+
+    block.reverse_statements()
+
+    return found
+
+
+def fold_constants(block):
+    """
+    Constant folding:
+    """
+    return False

+ 11 - 0
src/statement.py

@@ -139,7 +139,18 @@ class Block:
         self.statements = before + replacement + after
         self.pointer = start + len(replacement)
 
+    def insert(self, statement, index=None):
+        if index == None:
+            index = self.pointer
+
+        self.statements.insert(index, statement)
+
     def apply_filter(self, callback):
         """Apply a filter to the statement list. If the callback returns True,
         the statement will remain in the list.."""
         self.statements = filter(callback, self.statements)
+
+    def reverse_statements(self):
+        """Reverse the statement list and reset the pointer."""
+        self.statements = self.statements[::-1]
+        self.pointer = 0

+ 13 - 0
tests/test_optimize_advanced.py

@@ -0,0 +1,13 @@
+import unittest
+
+from src.optimize.advanced import eliminate_common_subexpressions
+from src.statement import Statement as S, Block as B
+
+
+class TestOptimizeAdvanced(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def test_eliminate_common_subexpressions(self):
+        pass