Browse Source

Use a simpler instruction scheduler

jonathanvdc 8 years ago
parent
commit
7f791a5ce2
1 changed files with 71 additions and 4 deletions
  1. 71 4
      kernel/modelverse_jit/cfg_to_tree.py

+ 71 - 4
kernel/modelverse_jit/cfg_to_tree.py

@@ -317,8 +317,75 @@ def find_inlinable_definitions(entry_point):
 
     return eligible_defs
 
-class DefinitionScheduler(object):
-    """Schedules definitions within a basic block."""
+class SimpleDefinitionScheduler(object):
+    """Schedules definitions within a basic block in the order they occur in."""
+    def __init__(self, lowering_state, definitions, flow):
+        self.lowering_state = lowering_state
+        self.definition_queue = definitions + [flow]
+        self.definition_set = set(self.definition_queue)
+
+    def use(self, definition):
+        """Creates a tree that produces the given definition's value."""
+        def_value = cfg_ir.get_def_value(definition)
+        if isinstance(def_value, LoweringState.inline_value_types):
+            return self.lowering_state.lower_value(def_value)
+        elif isinstance(def_value, cfg_ir.AllocateRootNode):
+            return tree_ir.LoadLocalInstruction(
+                self.lowering_state.get_root_node_name(def_value))
+        elif definition.has_value():
+            return self.lowering_state.create_definition_load(definition)
+        else:
+            return tree_ir.EmptyInstruction()
+
+    def get_schedulable_definition(self):
+        """Finds a schedulable definition. Returns None if there are no definitions left to
+           schedule."""
+        if len(self.definition_queue) == 0:
+            return None
+        else:
+            return self.definition_queue[-1]
+
+    def __schedule_single_def(self, definition, store_and_forget, statements):
+        if isinstance(definition, cfg_ir.FlowInstruction):
+            statements.append(self.lowering_state.lower_value(definition))
+        else:
+            # We're sure that we're dealing with a bona fide cfg_ir.Definition now.
+            definition_value = definition.value
+            if cfg_ir.is_value_def(definition_value, LoweringState.inline_value_types):
+                pass
+            else:
+                lowered_value = self.lowering_state.lower_value(definition_value)
+                if definition.has_value():
+                    def_load = self.lowering_state.create_definition_load(definition)
+                    statements.append(
+                        tree_ir.IgnoreInstruction(def_load.create_store(lowered_value)))
+                    if not store_and_forget:
+                        statements.append(def_load)
+                else:
+                    statements.append(lowered_value)
+
+    def has_scheduled(self, definition):
+        """Tests if the given definition has already been scheduled."""
+        return definition not in self.definition_set
+
+    def schedule(self, definition, store_and_forget=False):
+        """Schedules the given definition. The resulting tree is returned."""
+        assert definition in self.definition_set
+
+        index = self.definition_queue.index(definition)
+        defs_to_schedule = self.definition_queue[:index + 1]
+        del self.definition_queue[:index + 1]
+
+        statements = []
+        for schedule_def in defs_to_schedule:
+            self.definition_set.remove(schedule_def)
+            self.__schedule_single_def(schedule_def, store_and_forget, statements)
+
+        return tree_ir.create_block(*statements)
+
+class DependencyDefinitionScheduler(object):
+    """Schedules definitions within a basic block in an order that tries to maximize
+       the inlining of expressions."""
     # We now have the opportunity to schedule definitions in a somewhat intelligent way.
     # We ought to make sure that we don't reorder operations in an observable way, though.
     # Specifically:
@@ -615,13 +682,13 @@ class LoweringState(object):
     def lower_block(self, block):
         """Lowers the given (relooped) block to a tree."""
         statements = []
-        self.scheduler = DefinitionScheduler(self, block.definitions, block.flow)
+        self.scheduler = SimpleDefinitionScheduler(self, block.definitions, block.flow)
         while 1:
             schedulable_def = self.scheduler.get_schedulable_definition()
             if schedulable_def is None:
                 break
 
-            statements.append(self.scheduler.schedule(schedulable_def))
+            statements.append(self.scheduler.schedule(schedulable_def, True))
 
         self.scheduler = None