Browse Source

Read node values before branching on them (CFG construction)

jonathanvdc 8 years ago
parent
commit
ce653f6424

+ 9 - 4
kernel/modelverse_jit/bytecode_to_cfg.py

@@ -93,8 +93,11 @@ class AnalysisState(object):
 
     def analyze_if(self, instruction):
         """Analyzes an 'if' instruction."""
+        def __analyze_condition():
+            condition_node = self.analyze(instruction.condition)
+            return self.current_block.append_definition(cfg_ir.Read(condition_node))
         return self.emit_select(
-            lambda: self.analyze(instruction.condition),
+            __analyze_condition,
             lambda: self.analyze(instruction.if_clause),
             lambda:
             self.current_block.append_definition(cfg_ir.Literal(None))
@@ -110,7 +113,8 @@ class AnalysisState(object):
         #     jump !loop_condition()
         #
         # !loop_condition():
-        #     $condition = <condition>
+        #     $condition_node = <condition>
+        #     $condition = read condition_node
         #     select $condition, !loop_body(), !loop_exit()
         #
         # !loop_body():
@@ -128,9 +132,10 @@ class AnalysisState(object):
         self.current_block.flow = cfg_ir.create_jump(loop_condition_block)
 
         self.current_block = loop_condition_block
-        condition_value = self.analyze(instruction.condition)
+        condition_node = self.analyze(instruction.condition)
+        condition = self.current_block.append_definition(cfg_ir.Read(condition_node))
         self.current_block.flow = cfg_ir.SelectFlow(
-            condition_value, cfg_ir.Branch(loop_body_block), cfg_ir.Branch(loop_exit_block))
+            condition, cfg_ir.Branch(loop_body_block), cfg_ir.Branch(loop_exit_block))
 
         self.current_block = loop_body_block
         self.analyze(instruction.body)

+ 14 - 0
kernel/modelverse_jit/cfg_ir.py

@@ -460,6 +460,20 @@ class StoreAtPointer(Value):
     def __str__(self):
         return 'store %s, %s' % (self.pointer.ref_str(), self.value.ref_str())
 
+class Read(Value):
+    """A value that reads the value stored in a node."""
+    def __init__(self, node):
+        Value.__init__(self)
+        self.node = node
+        assert isinstance(node, Definition)
+
+    def get_dependencies(self):
+        """Gets all definitions and instructions on which this instruction depends."""
+        return [self.node]
+
+    def __str__(self):
+        return 'read %s' % (self.node.ref_str())
+
 class Input(Value):
     """A value that pops a node from the input queue."""
     def get_dependencies(self):

+ 6 - 0
kernel/modelverse_jit/cfg_to_tree.py

@@ -451,6 +451,11 @@ class LoweringState(object):
         return bytecode_to_tree.create_assign(
             self.load_definition(value.pointer), self.load_definition(value.value))
 
+    def lower_read(self, value):
+        """Lowers a 'read' value."""
+        return tree_ir.ReadValueInstruction(
+            self.load_definition(value.node))
+
     def lower_binary(self, value):
         """Lowers a 'binary' value."""
         return tree_ir.BinaryInstruction(
@@ -493,6 +498,7 @@ class LoweringState(object):
         cfg_ir.DeallocateRootNode : lower_free_root_node,
         cfg_ir.LoadPointer : lower_load_pointer,
         cfg_ir.StoreAtPointer : lower_store_pointer,
+        cfg_ir.Read : lower_read,
         cfg_ir.Binary : lower_binary,
         cfg_ir.Input : lower_input,
         cfg_ir.Output : lower_output,