|
@@ -175,6 +175,61 @@ def eliminate_unused_definitions(entry_point):
|
|
for dead_def in dead_defs:
|
|
for dead_def in dead_defs:
|
|
dead_def.block.remove_definition(dead_def)
|
|
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):
|
|
def try_redefine_as_direct_call(definition, jit, called_globals):
|
|
"""Tries to redefine the given indirect call definition as a direct call."""
|
|
"""Tries to redefine the given indirect call definition as a direct call."""
|
|
call = definition.value
|
|
call = definition.value
|
|
@@ -218,6 +273,7 @@ def optimize(entry_point, jit):
|
|
optimize_graph_flow(entry_point)
|
|
optimize_graph_flow(entry_point)
|
|
elide_local_checks(entry_point)
|
|
elide_local_checks(entry_point)
|
|
optimize_graph_flow(entry_point)
|
|
optimize_graph_flow(entry_point)
|
|
|
|
+ eliminate_trivial_phis(entry_point)
|
|
optimize_calls(entry_point, jit)
|
|
optimize_calls(entry_point, jit)
|
|
eliminate_unused_definitions(entry_point)
|
|
eliminate_unused_definitions(entry_point)
|
|
optimize_graph_flow(entry_point)
|
|
optimize_graph_flow(entry_point)
|