Browse Source

Nullify entry point block parameters after SSA construction

jonathanvdc 8 years ago
parent
commit
c8a432c739

+ 2 - 2
kernel/modelverse_jit/cfg_optimization.py

@@ -311,7 +311,7 @@ def expand_indirect_definitions(entry_point):
                 new_dep = dep
                 if isinstance(new_dep, cfg_ir.Definition):
                     while isinstance(new_dep.value, cfg_ir.Definition):
-                        new_dep = dep.value
+                        new_dep = new_dep.value
                 else:
                     new_dep = __expand_indirect_defs(new_dep)
 
@@ -335,7 +335,7 @@ def optimize(entry_point, jit):
     elide_local_checks(entry_point)
     optimize_graph_flow(entry_point)
     eliminate_trivial_phis(entry_point)
-    # cfg_ssa_construction.construct_ssa_form(entry_point)
+    # entry_point = cfg_ssa_construction.construct_ssa_form(entry_point)
     optimize_calls(entry_point, jit)
     yield [("CALL_ARGS", [inline_constants, (entry_point,)])]
     simplify_values(entry_point)

+ 33 - 4
kernel/modelverse_jit/cfg_ssa_construction.py

@@ -43,7 +43,8 @@ def get_ineligible_local_ids(entry_point):
     return ineligible_local_ids
 
 def construct_ssa_form(entry_point):
-    """Converts local variables into SSA form in the graph defined by the given entry point."""
+    """Converts local variables into SSA form in the graph defined by the given entry point.
+       A potentially new entry block is returned."""
     # Build some helper data structures.
     all_blocks = list(cfg_ir.get_all_blocks(entry_point))
     ineligible_locals = get_ineligible_local_ids(entry_point)
@@ -60,6 +61,37 @@ def construct_ssa_form(entry_point):
     for block in all_blocks:
         state.update_block_branches(block)
 
+    # Nullify entry point parameters.
+    return nullify_entry_block_parameters(entry_point)
+
+def nullify_entry_block_parameters(entry_point):
+    """Creates or returns an entry block that takes no parameters.
+       The (new) entry block is returned."""
+    # The SSA construction algorithm has the nasty habit of replacing potentially
+    # undefined variables by entry block parameters. Codegen doesn't like that one
+    # bit: it assumes that all block parameters are defined by the branches to those
+    # parameters -- but there usually is no branch to the entry point!
+    #
+    # We can fix this by either replacing the block-parameters in the entry block by
+    # definitions, or by creating a new entry point that jumps to the old entry
+    # point with an argument list. The former construction is more efficient, but it is only
+    # correct if there are no pre-existing branches to the entry point.
+    #
+    # We could build the predecessor map block and use the first option if possible,
+    # but we won't; trivial phi elimination followed by block merging will reduce
+    # the second construction to the first one anyway.
+    if len(entry_point.parameters) == 0:
+        return entry_point
+
+    pre_entry_point = cfg_ir.BasicBlock(entry_point.counter)
+    arg_list = []
+    for _ in entry_point.parameters:
+        literal_def = pre_entry_point.append_definition(cfg_ir.Literal(None))
+        arg_list.append(literal_def)
+
+    pre_entry_point.flow = cfg_ir.create_jump(entry_point, arg_list)
+    return pre_entry_point
+
 # The algorithms below are based on
 # Simple and Efficient Construction of Static Single Assignment Form by M. Braun et al
 # (https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf).
@@ -234,6 +266,3 @@ class SSAConstructionState(object):
             # Append arguments to the branch.
             for _, arg in sorted_pairs:
                 branch.arguments.append(arg)
-
-
-