浏览代码

Optimize temporaries in tree-ir codegen

jonathanvdc 8 年之前
父节点
当前提交
60b60b805f
共有 1 个文件被更改,包括 45 次插入21 次删除
  1. 45 21
      kernel/modelverse_jit/tree_ir.py

+ 45 - 21
kernel/modelverse_jit/tree_ir.py

@@ -44,6 +44,11 @@ class Instruction(object):
         """Tells if this instruction requires a definition."""
         return True
 
+    def get_result_name_override(self):
+        """Gets a value that overrides the code generator's result name for this
+           instruction if it is not None."""
+        return None
+
     def generate_python_def(self, code_generator):
         """Generates a Python statement that executes this instruction.
            The statement is appended immediately to the code generator."""
@@ -110,22 +115,42 @@ class PythonGenerator(object):
 
         self.indentation -= 1
 
-    def get_result_name(self, instruction):
+    def get_result_name(self, instruction, advised_name=None):
         """Gets the name of the given instruction's result variable."""
-
         if instruction not in self.result_value_dict:
-            self.result_value_dict[instruction] = \
-                'tmp' + str(len(self.result_value_dict))
+            override_name = instruction.get_result_name_override()
+            if override_name is not None:
+                self.result_value_dict[instruction] = override_name
+            elif advised_name is not None:
+                self.result_value_dict[instruction] = advised_name
+            else:
+                self.result_value_dict[instruction] = \
+                    'tmp' + str(len(self.result_value_dict))
 
         return self.result_value_dict[instruction]
 
     def append_definition(self, lhs, rhs):
         """Defines the first instruction's result variable as the second
            instruction's result."""
-
         self.append_line(
             self.get_result_name(lhs) + ' = ' + rhs.generate_python_use(self))
 
+    def append_move_definition(self, lhs, rhs):
+        """First defines the second instruction, then defines the first
+           instruction as the result of the second."""
+        if rhs.has_definition():
+            # Retrieve the result name for the lhs.
+            lhs_result_name = self.get_result_name(lhs)
+            # Encourage the rhs to take on the same result name as the lhs.
+            rhs_result_name = self.get_result_name(rhs, lhs_result_name)
+            # Generate the rhs' definition.
+            rhs.generate_python_def(self)
+            # Only perform an assignment if it's truly necessary.
+            if lhs_result_name != rhs_result_name:
+                self.append_definition(lhs, rhs)
+        else:
+            self.append_definition(lhs, rhs)
+
     def append_state_definition(self, lhs, opcode, args):
         """Appends a definition that queries the modelverse state."""
 
@@ -182,19 +207,19 @@ class SelectInstruction(Instruction):
         code_generator.append_line(
             'if ' + self.condition.generate_python_use(code_generator) + ':')
         code_generator.increase_indentation()
-        if self.if_clause.has_definition() or (not if_has_result):
-            self.if_clause.generate_python_def(code_generator)
         if if_has_result:
-            code_generator.append_definition(self, self.if_clause)
+            code_generator.append_move_definition(self, self.if_clause)
+        else:
+            self.if_clause.generate_python_def(code_generator)
         code_generator.decrease_indentation()
         else_has_def = self.else_clause.has_definition()
         if else_has_def or if_has_result:
             code_generator.append_line('else:')
             code_generator.increase_indentation()
-            if else_has_def:
-                self.else_clause.generate_python_def(code_generator)
             if if_has_result:
-                code_generator.append_definition(self, self.else_clause)
+                code_generator.append_move_definition(self, self.else_clause)
+            else:
+                self.else_clause.generate_python_def(code_generator)
             code_generator.decrease_indentation()
 
 class ReturnInstruction(VoidInstruction):
@@ -361,9 +386,7 @@ class CompoundInstruction(Instruction):
     def generate_python_def(self, code_generator):
         """Generates Python code for this instruction."""
         self.first.generate_python_def(code_generator)
-        self.second.generate_python_def(code_generator)
-        if self.has_result():
-            code_generator.append_definition(self, self.second)
+        code_generator.append_move_definition(self, self.second)
 
 class LiteralInstruction(Instruction):
     """Represents an integer, floating-point, string or Boolean literal."""
@@ -408,6 +431,11 @@ class LocalInstruction(Instruction):
         Instruction.__init__(self)
         self.name = name
 
+    def get_result_name_override(self):
+        """Gets a value that overrides the code generator's result name for this
+           instruction if it is not None."""
+        return self.name
+
     def create_load(self):
         """Creates an instruction that loads the variable referenced by this instruction."""
         return LoadLocalInstruction(self.name)
@@ -435,11 +463,7 @@ class StoreLocalInstruction(LocalInstruction):
     def generate_python_def(self, code_generator):
         """Generates a Python statement that executes this instruction.
            The statement is appended immediately to the code generator."""
-
-        if self.value.has_definition():
-            self.value.generate_python_def(code_generator)
-        code_generator.append_line(
-            '%s = %s' % (self.name, self.value.generate_python_use(code_generator)))
+        code_generator.append_move_definition(self, self.value)
 
 class LoadLocalInstruction(LocalInstruction):
     """An instruction that loads a value from a local variable."""
@@ -642,8 +666,8 @@ def create_block(*statements):
         return statements[0]
     else:
         return CompoundInstruction(
-            create_block(*statements[:-1]),
-            statements[-1])
+            statements[0],
+            create_block(*statements[1:]))
 
 if __name__ == "__main__":
     example_tree = SelectInstruction(