[pypy-commit] pypy memoryerror3: finished the refactoring. the root loop has now it's own version, which makes generate_pending_loop_versions easier to understand. a fail descr now always points to the loop version (field version) it would like to jump to

plan_rich noreply at buildbot.pypy.org
Mon Aug 24 12:02:25 CEST 2015


Author: Richard Plangger <rich at pasra.at>
Branch: memoryerror3
Changeset: r79187:743dc64b5f8a
Date: 2015-08-21 14:10 +0200
http://bitbucket.org/pypy/pypy/changeset/743dc64b5f8a/

Log:	finished the refactoring. the root loop has now it's own version,
	which makes generate_pending_loop_versions easier to understand. a
	fail descr now always points to the loop version (field version) it
	would like to jump to handle not compiled versions (because they are
	not needed) gracefully

diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -162,7 +162,7 @@
 
     if loop.versions is not None:
         # every different loop version must update their target tokens
-        for version in loop.versions:
+        for version in loop.versions[1:]:
             version.update_token(jitcell_token, all_target_tokens)
 
     if not loop.quasi_immutable_deps:
@@ -194,10 +194,11 @@
     if loop.versions is not None:
         # compile each version once for the first fail descr!
         # this assumes that the root trace (= loop) is already compiled
-        for version in loop.versions:
-            if len(version.faildescrs) == 0:
+        root = loop.versions[0]
+        for faildescr in root.faildescrs:
+            version = faildescr.version
+            if not version or version.compiled():
                 continue
-            faildescr = version.faildescrs[0]
             vl = create_empty_loop(metainterp)
             vl.inputargs = version.inputargs
             vl.operations = version.operations
@@ -207,13 +208,19 @@
                                    version.operations, jitcell_token)
             record_loop_or_bridge(metainterp_sd, vl)
             assert asminfo is not None
-            version.compiled = asminfo
+            version._compiled = asminfo
+            faildescr.version = None
         # stitch the rest of the traces
-        for version in loop.versions:
-            for faildescr in version.faildescrs[1:]:
-                assert isinstance(faildescr, CompileLoopVersionDescr)
-                if faildescr.version.compiled:
-                    cpu.stitch_bridge(faildescr, version.compiled)
+        for lv in loop.versions:
+            if not lv.compiled():
+                # the version was never compiled, do not bother
+                # to assign it's fail descr
+                continue
+            for faildescr in lv.faildescrs:
+                version = faildescr.version
+                if version and version.compiled():
+                    cpu.stitch_bridge(faildescr, version._compiled)
+                faildescr.version = None
     loop.versions = None
 
 def compile_retrace(metainterp, greenkey, start,
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -748,28 +748,62 @@
 
 class LoopVersion(object):
 
-    def __init__(self, operations):
-        self.operations = operations
+    def __init__(self, loop):
         self.faildescrs = []
-        #
-        idx = index_of_first(rop.LABEL, operations)
-        assert idx >= 0
-        label = operations[idx]
-        self.label_pos = idx
-        self.inputargs = label.getarglist()
-        self.renamed_inputargs = label.getarglist()
-        self.compiled = None
+        self._compiled = None
+        if loop:
+            self.operations = self.copy_operations(loop.operations) 
+            idx = index_of_first(rop.LABEL, self.operations)
+            assert idx >= 0
+            label = self.operations[idx]
+            self.inputargs = label.getarglist()
+            self.renamed_inputargs = label.getarglist()
+        else:
+            self.operations = None
+            self.inputargs = None
+            self.renamed_inputargs = None
 
-    def register_guard(self, op):
+    def compiled(self):
+        if self.operations is None:
+            # root version must always be compiled
+            return True
+
+        return self._compiled is not None
+
+    def copy_operations(self, operations):
+        from rpython.jit.metainterp.compile import ResumeGuardDescr
+        ignore = (rop.DEBUG_MERGE_POINT,)
+        oplist = []
+        for op in operations:
+            if op.getopnum() in ignore:
+                continue
+            cloned = op.clone()
+            oplist.append(cloned)
+            if cloned.is_guard():
+                olddescr = cloned.getdescr()
+                if not olddescr:
+                    continue
+                descr = olddescr.clone()
+                cloned.setdescr(descr)
+                if olddescr.loop_version():
+                    # copy the version
+                    descr.version = olddescr.version
+                    self.faildescrs.append(descr)
+        return oplist
+
+    def register_guard(self, op, version):
         from rpython.jit.metainterp.compile import CompileLoopVersionDescr
         assert isinstance(op, GuardResOp)
         descr = op.getdescr()
+        if not descr.loop_version():
+            assert 0, "cannot register a guard that is not a CompileLoopVersionDescr"
         assert isinstance(descr, CompileLoopVersionDescr)
+        descr.version = version
         self.faildescrs.append(descr)
-        descr.version = self
         # note: stitching a guard must resemble the order of the label
         # otherwise a wrong mapping is handed to the register allocator
-        op.setfailargs(self.renamed_inputargs)
+        op.setfailargs(version.renamed_inputargs)
+        assert version.renamed_inputargs is not None
 
     def update_token(self, jitcell_token, all_target_tokens):
         # this is only invoked for versioned loops!
@@ -798,7 +832,6 @@
         label.setdescr(token)
         jump.setdescr(token)
 
-
 class TreeLoop(object):
     inputargs = None
     operations = None
@@ -872,9 +905,11 @@
         return None
 
     def snapshot(self):
-        faildescrs = []
-        version = LoopVersion(self.copy_operations(faildescrs))
-        version.faildescrs = faildescrs
+        if len(self.versions) == 0:
+            # create a root version, simplyfies the code in compile.py
+            self.versions.append(LoopVersion(None))
+        root_version = self.versions[0]
+        version = LoopVersion(self)
         if not we_are_translated():
             print "LOOP SNAPSHOT"
             for op in version.operations:
@@ -882,23 +917,6 @@
         self.versions.append(version)
         return version
 
-    def copy_operations(self, faildescrs=None):
-        from rpython.jit.metainterp.compile import ResumeGuardDescr
-        ignore = (rop.DEBUG_MERGE_POINT,)
-        operations = []
-        for op in self.operations:
-            if op.getopnum() in ignore:
-                continue
-            cloned = op.clone()
-            operations.append(cloned)
-            descr = cloned.getdescr()
-            if cloned.is_guard() and descr:
-                assert isinstance(descr, ResumeGuardDescr)
-                cloned.setdescr(descr.clone())
-                if faildescrs and descr.loop_version():
-                    faildescrs.append(cloned.getdescr())
-        return operations
-
     def get_display_text(self):    # for graphpage.py
         return self.name + '\n' + repr(self.inputargs)
 
diff --git a/rpython/jit/metainterp/optimizeopt/guard.py b/rpython/jit/metainterp/optimizeopt/guard.py
--- a/rpython/jit/metainterp/optimizeopt/guard.py
+++ b/rpython/jit/metainterp/optimizeopt/guard.py
@@ -152,8 +152,7 @@
         assert operations[self.index] is self.op
         operations[self.index] = None
         descr = self.op.getdescr()
-        if isinstance(descr, CompileLoopVersionDescr) and descr.version:
-            descr.version.faildescrs.remove(descr)
+        if descr and descr.loop_version():
             descr.version = None
         if operations[self.index-1] is self.cmp_op:
             operations[self.index-1] = None
@@ -265,19 +264,20 @@
         self.collect_guard_information(loop)
         self.eliminate_guards(loop)
         #
-        assert len(loop.versions) == 1, "none or more than one version created"
-        version = loop.versions[0]
+        assert len(loop.versions) == 2, "need one orignal loop version (before trans) and the current one"
+        root_version = loop.versions[0]
+        version = loop.versions[1]
 
         for op in loop.operations:
             if not op.is_guard():
                 continue
             descr = op.getdescr()
             if descr.loop_version():
-                version.register_guard(op)
+                root_version.register_guard(op, version)
 
         if user_code:
             version = loop.snapshot()
-            self.eliminate_array_bound_checks(loop, version)
+            self.eliminate_array_bound_checks(loop, root_version, version)
 
     def emit_operation(self, op):
         self.renamer.rename(op)
@@ -286,7 +286,7 @@
     def operation_position(self):
         return len(self._newoperations)
 
-    def eliminate_array_bound_checks(self, loop, version):
+    def eliminate_array_bound_checks(self, loop, root_version, version):
         self._newoperations = []
         for key, guards in self.strongest_guards.items():
             if len(guards) <= 1:
@@ -299,7 +299,7 @@
                 transitive_guard = one.transitive_imply(other, self, loop)
                 if transitive_guard:
                     other.set_to_none(loop.operations)
-                    version.register_guard(transitive_guard)
+                    root_version.register_guard(transitive_guard, version)
 
         if self.has_two_labels:
             oplist = [loop.operations[0]] + self._newoperations + \
diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py b/rpython/jit/metainterp/optimizeopt/vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/vectorize.py
@@ -38,6 +38,7 @@
     user_code = not jitdriver_sd.vec and warmstate.vec_all
     if user_code and user_loop_bail_fast_path(loop, warmstate):
         return
+    # the original loop (output of optimize_unroll)
     version = loop.snapshot()
     try:
         debug_start("vec-opt-loop")
@@ -493,7 +494,7 @@
             return
         if vector:
             # add accumulation info to the descriptor
-            for version in self.loop.versions:
+            for version in self.loop.versions[1:]:
                 # this needs to be done for renamed (accum arguments)
                 version.renamed_inputargs = [ renamer.rename_map.get(arg,arg) for arg in version.inputargs ]
             self.appended_arg_count = len(sched_data.invariant_vector_vars)
@@ -874,7 +875,7 @@
                 box = result
             elif accum.operator == Accum.MULTIPLY:
                 # multiply is only supported by floats
-                op = ResOperation(rop.VEC_FLOAT_EXPAND, [ConstFloat(1.0)], box)
+                op = ResOperation(rop.VEC_FLOAT_EXPAND, [ConstFloat(1.0), ConstInt(size)], box)
                 sched_data.invariant_oplist.append(op)
             else:
                 raise NotImplementedError("can only handle + and *")


More information about the pypy-commit mailing list