Browse Source

Implement trivial phi elimination

jonathanvdc 8 years ago
parent
commit
ee38409027
2 changed files with 62 additions and 1 deletions
  1. 6 1
      kernel/modelverse_jit/cfg_ir.py
  2. 56 0
      kernel/modelverse_jit/cfg_optimization.py

+ 6 - 1
kernel/modelverse_jit/cfg_ir.py

@@ -32,6 +32,10 @@ class BasicBlock(object):
             self.renumber_definitions()
         return result
 
+    def remove_parameter(self, parameter):
+        """Removes the given parameter definition from this basic block."""
+        return self.parameters.remove(parameter)
+
     def prepend_definition(self, value):
         """Defines the given value in this basic block."""
         result = self.create_definition(value)
@@ -124,7 +128,8 @@ class Instruction(object):
            along with any dependencies of instruction dependencies."""
         results = list(self.get_dependencies())
         for item in results:
-            results.extend(item.get_all_dependencies())
+            if not isinstance(item, Definition):
+                results.extend(item.get_all_dependencies())
 
         return results
 

+ 56 - 0
kernel/modelverse_jit/cfg_optimization.py

@@ -175,6 +175,61 @@ def eliminate_unused_definitions(entry_point):
     for dead_def in dead_defs:
         dead_def.block.remove_definition(dead_def)
 
+def get_trivial_phi_value(parameter_def, values):
+    """Tests if the given parameter definition is an alias for another definition.
+       If so, then the other definition is returned; otherwise, None."""
+    result = None
+    for elem in values:
+        if elem is not parameter_def:
+            if result is None:
+                result = elem
+            else:
+                return None
+
+    if result is not None:
+        print('Found trivial phi value for %s: %s' % (parameter_def, result))
+    return result
+
+def eliminate_trivial_phis(entry_point):
+    """Eliminates trivial block parameters, i.e., block parameters which are really
+       aliases."""
+    phi_values = defaultdict(set)
+    all_blocks = list(get_all_blocks(entry_point))
+    for block in all_blocks:
+        for branch in block.flow.branches():
+            for phi, arg in zip(branch.block.parameters, branch.arguments):
+                phi_values[phi].add(arg)
+
+    replacements = []
+    for block in all_blocks:
+        block_parameters = list(block.parameters)
+        for parameter_def in block_parameters:
+            trivial_phi_val = get_trivial_phi_value(
+                parameter_def, phi_values[parameter_def])
+            if trivial_phi_val is not None:
+                replacements.append((parameter_def, trivial_phi_val))
+
+    erase_parameters(entry_point, set([parameter_def for parameter_def, _ in replacements]))
+
+    for parameter_def, trivial_phi_val in replacements:
+        block = parameter_def.block
+        parameter_def.redefine(trivial_phi_val)
+        block.prepend_definition(parameter_def)
+
+def erase_parameters(entry_point, parameters_to_erase):
+    """Erases all arguments for the given set of parameters, and then takes out the
+       parameters themselves."""
+    for block in get_all_blocks(entry_point):
+        for branch in block.flow.branches():
+            new_arg_list = []
+            for parameter, arg in zip(branch.block.parameters, branch.arguments):
+                if parameter not in parameters_to_erase:
+                    new_arg_list.append(arg)
+            branch.arguments = new_arg_list
+
+    for parameter_def in parameters_to_erase:
+        parameter_def.block.remove_parameter(parameter_def)
+
 def try_redefine_as_direct_call(definition, jit, called_globals):
     """Tries to redefine the given indirect call definition as a direct call."""
     call = definition.value
@@ -218,6 +273,7 @@ def optimize(entry_point, jit):
     optimize_graph_flow(entry_point)
     elide_local_checks(entry_point)
     optimize_graph_flow(entry_point)
+    eliminate_trivial_phis(entry_point)
     optimize_calls(entry_point, jit)
     eliminate_unused_definitions(entry_point)
     optimize_graph_flow(entry_point)