Author: Richard Plangger <r...@pasra.at>
Branch: vecopt-merge
Changeset: r79092:27ddd5637fb8
Date: 2015-08-21 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/27ddd5637fb8/

Log:    moved the collection of compile loop version descr to guard opt. the
        assembler writes the correct offset into memory but it is not
        visible in the resulting memory block (e.g. jitviewer?). something
        is wrong

diff --git a/rpython/jit/backend/llgraph/runner.py 
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -265,8 +265,8 @@
         self.stats = stats or MiniStats()
         self.vinfo_for_tests = kwds.get('vinfo_for_tests', None)
 
-    def stitch_bridge(self, faildescr, compiled_faildescr, jitcell_token):
-        faildescr._llgraph_bridge = compiled_faildescr._llgraph_bridge
+    def stitch_bridge(self, faildescr, target):
+        faildescr._llgraph_bridge = target
 
     def compile_loop(self, inputargs, operations, looptoken, jd_id=0,
                      unique_id=0, log=True, name='', logger=None):
@@ -285,6 +285,7 @@
         faildescr._llgraph_bridge = lltrace
         clt._llgraph_alltraces.append(lltrace)
         self._record_labels(lltrace)
+        return lltrace
 
     def _record_labels(self, lltrace):
         for i, op in enumerate(lltrace.operations):
diff --git a/rpython/jit/backend/llsupport/assembler.py 
b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -35,7 +35,6 @@
         self.exc = exc
         self.is_guard_not_invalidated = is_guard_not_invalidated
         self.is_guard_not_forced = is_guard_not_forced
-        self.rawstart = 0
 
     def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth):
         # note that regalloc has a very similar compute, but
@@ -70,7 +69,7 @@
         self.rtyper = cpu.rtyper
         self._debug = False
 
-    def stitch_bridge(self, faildescr, compiled_faildescr, token):
+    def stitch_bridge(self, faildescr, target):
         raise NotImplementedError
 
     def setup_once(self):
diff --git a/rpython/jit/backend/llsupport/llmodel.py 
b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -97,8 +97,8 @@
                                             inputargs, operations,
                                             looptoken, log=log)
 
-    def stitch_bridge(self, faildescr, compiled_faildescr, token):
-        self.assembler.stitch_bridge(faildescr, compiled_faildescr, token)
+    def stitch_bridge(self, faildescr, target):
+        self.assembler.stitch_bridge(faildescr, target)
 
     def _setup_frame_realloc(self, translate_support_code):
         FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF, lltype.Signed],
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -569,7 +569,7 @@
         fullsize = self.mc.get_relative_pos()
         #
         rawstart = self.materialize_loop(original_loop_token)
-        faildescr.rawstart = rawstart
+        faildescr.bridge_rawstart = rawstart
         self.patch_stack_checks(frame_depth_no_fixed_size + 
JITFRAME_FIXED_SIZE,
                                 rawstart)
         debug_bridge(descr_number, rawstart, codeendpos)
@@ -592,8 +592,9 @@
                                                        rawstart, fullsize)
         return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos)
 
-    def stitch_bridge(self, faildescr, compiled_faildescr, token):
-        self.patch_jump_for_descr(faildescr, compiled_faildescr.rawstart)
+    def stitch_bridge(self, faildescr, target):
+        assert target != 0
+        self.patch_jump_for_descr(faildescr, target)
 
     def write_pending_failure_recoveries(self, regalloc):
         # for each pending guard, generate the code of the recovery stub
@@ -604,7 +605,8 @@
                 regalloc.position = tok.position
                 tok.pos_recovery_stub = self.generate_quick_failure(tok, 
regalloc)
             else:
-                self.store_info_on_descr(0, tok)
+                startpos = self.mc.get_relative_pos()
+                self.store_info_on_descr(startpos, tok)
         if WORD == 8 and len(self.pending_memoryerror_trampoline_from) > 0:
             self.error_trampoline_64 = self.generate_propagate_error_64()
 
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -322,7 +322,6 @@
             if accum:
                 loc = self.loc(accum.getoriginalbox())
                 faillocs.append(loc)
-                import pdb; pdb.set_trace()
                 self.update_accumulation_loc(arg, accum, descr, i)
             else:
                 faillocs.append(self.loc(arg))
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
@@ -192,6 +192,8 @@
     metainterp_sd = metainterp.staticdata
     cpu = metainterp_sd.cpu
     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:
                 continue
@@ -200,12 +202,16 @@
             vl.inputargs = version.inputargs
             vl.operations = version.operations
             vl.original_jitcell_token = jitcell_token
-            send_bridge_to_backend(jitdriver_sd, metainterp_sd,
-                                   faildescr, version.inputargs,
-                                   version.operations, jitcell_token)
+            asminfo = send_bridge_to_backend(jitdriver_sd, metainterp_sd,
+                                             faildescr, version.inputargs,
+                                             version.operations, jitcell_token)
             record_loop_or_bridge(metainterp_sd, vl)
-            for fd in version.faildescrs[1:]:
-                cpu.stitch_bridge(fd, faildescr, jitcell_token)
+            version.compiled = faildescr.bridge_rawstart
+            assert asminfo is not None
+        # stitch the rest of the traces
+        for version in loop.versions:
+            for faildescr in version.faildescrs[1:]:
+                cpu.stitch_bridge(faildescr, version.compiled)
     loop.versions = None
 
 def compile_retrace(metainterp, greenkey, start,
@@ -437,6 +443,7 @@
     #if metainterp_sd.warmrunnerdesc is not None:    # for tests
     #    metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(
     #        original_loop_token)
+    return asminfo
 
 # ____________________________________________________________
 
@@ -742,6 +749,11 @@
     def loop_version(self):
         return True
 
+    def clone(self):
+        cloned = ResumeGuardDescr.clone(self)
+        cloned.version = self.version
+        return cloned
+
 class AllVirtuals:
     llopaque = True
     cache = None
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
@@ -758,38 +758,7 @@
         label = operations[idx]
         self.label_pos = idx
         self.inputargs = label.getarglist()
-
-    def register_all_guards(self, opt_ops, invariant_arg_count=0):
-        from rpython.jit.metainterp.compile import CompileLoopVersionDescr
-        pass_by = 0
-        idx = index_of_first(rop.LABEL, opt_ops)
-        if opt_ops[idx].getdescr() is not opt_ops[-1].getdescr():
-            idx = index_of_first(rop.LABEL, opt_ops, pass_by=1)
-        assert idx >= 0
-        version_failargs = opt_ops[idx].getarglist()
-        if invariant_arg_count > 0:
-            # constant/variable expansion append arguments to the label
-            # if they are not removed, the register allocator cannot
-            # reconstruct the binding if len(inputargs) != len(faillocs)
-            to = len(version_failargs) - invariant_arg_count
-            assert to >= 0
-            version_failargs = version_failargs[:to]
-
-        for op in opt_ops:
-            if op.is_guard():
-                assert isinstance(op, GuardResOp)
-                descr = op.getdescr()
-                if descr.loop_version():
-                    assert isinstance(descr, CompileLoopVersionDescr)
-                    if descr.version is None:
-                        # currently there is only ONE versioning,
-                        # that is the original loop after unrolling.
-                        # if there are more possibilites, let the descr
-                        # know which loop version he preferes
-                        descr.version = self
-                        self.faildescrs.append(descr)
-                        op.setfailargs(version_failargs)
-                        op.rd_snapshot = None
+        self.compiled = None
 
     def register_guard(self, op):
         from rpython.jit.metainterp.compile import CompileLoopVersionDescr
@@ -798,8 +767,6 @@
         assert isinstance(descr, CompileLoopVersionDescr)
         descr.version = self
         self.faildescrs.append(descr)
-        op.setfailargs(self.inputargs)
-        op.rd_snapshot = None
 
     def update_token(self, jitcell_token, all_target_tokens):
         # this is only invoked for versioned loops!
@@ -892,16 +859,22 @@
         return self.operations
 
     def find_first_index(self, opnum, pass_by=0):
-        """ return the first operation having the same opnum or -1 """
+        """ return the first index of the operation having the same opnum or 
-1 """
         return index_of_first(opnum, self.operations, pass_by)
 
+    def find_first(self, opnum, pass_by=0):
+        index = self.find_first_index(opnum, pass_by)
+        if index != -1:
+            return self.operations[index]
+        return None
+
     def snapshot(self):
         version = LoopVersion(self.copy_operations())
         self.versions.append(version)
         return version
 
     def copy_operations(self):
-        from rpython.jit.metainterp.compile import ResumeGuardDescr
+        from rpython.jit.metainterp.compile import ResumeGuardDescr, 
CompileLoopVersionDescr
         ignore = (rop.DEBUG_MERGE_POINT,)
         operations = []
         for op in self.operations:
@@ -913,6 +886,8 @@
             if cloned.is_guard() and descr:
                 assert isinstance(descr, ResumeGuardDescr)
                 cloned.setdescr(descr.clone())
+                if isinstance(descr, CompileLoopVersionDescr):
+                    descr.version.register_guard(cloned)
         return operations
 
     def get_display_text(self):    # for graphpage.py
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -102,6 +102,7 @@
         return descr.repr_of_descr()
 
     def repr_of_arg(self, arg):
+        return str(arg) # XXX
         try:
             mv = self.memo[arg]
         except KeyError:
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
@@ -10,7 +10,7 @@
 from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp)
 from rpython.jit.metainterp.history import (ConstInt, BoxVector, 
         BoxFloat, BoxInt, ConstFloat, Box, Const)
-from rpython.jit.metainterp.compile import ResumeGuardDescr
+from rpython.jit.metainterp.compile import ResumeGuardDescr, 
CompileLoopVersionDescr
 from rpython.rlib.objectmodel import we_are_translated
 
 class Guard(object):
@@ -70,7 +70,7 @@
                 return (lc <= 0 and rc >= 0)
         return False
 
-    def transitive_imply(self, other, opt):
+    def transitive_imply(self, other, opt, loop):
         if self.op.getopnum() != other.op.getopnum():
             # stronger restriction, intermixing e.g. <= and < would be possible
             return None
@@ -91,6 +91,8 @@
         assert isinstance(descr, ResumeGuardDescr)
         guard.setdescr(descr.clone())
         guard.setarg(0, box_result)
+        label = loop.find_first(rop.LABEL)
+        guard.setfailargs(label.getarglist())
         opt.emit_operation(guard)
 
         return guard
@@ -149,6 +151,10 @@
     def set_to_none(self, operations):
         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)
+            descr.version = None
         if operations[self.index-1] is self.cmp_op:
             operations[self.index-1] = None
 
@@ -171,12 +177,14 @@
         return Guard(index, guard_op, cmp_op, index_vars)
 
 class GuardStrengthenOpt(object):
-    def __init__(self, index_vars):
+    """ Note that this optimization is only used in the vector optimizer (yet) 
"""
+    def __init__(self, index_vars, has_two_labels):
         self.index_vars = index_vars
         self._newoperations = []
         self.strength_reduced = 0 # how many guards could be removed?
         self.strongest_guards = {}
         self.guards = {}
+        self.has_two_labels = has_two_labels
 
     def collect_guard_information(self, loop):
         operations = loop.operations
@@ -256,8 +264,18 @@
         # the guards are ordered. guards[i] is before guards[j] iff i < j
         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]
 
-        if user_code or True:
+        for op in loop.operations:
+            if not op.is_guard():
+                continue
+            descr = op.getdescr()
+            if isinstance(descr, CompileLoopVersionDescr):
+                version.register_guard(op)
+
+        if user_code and False:
             version = loop.snapshot()
             self.eliminate_array_bound_checks(loop, version)
 
@@ -278,11 +296,16 @@
             # iff we add invariant guards
             one = guards[0]
             for other in guards[1:]:
-                transitive_guard = one.transitive_imply(other, self)
+                transitive_guard = one.transitive_imply(other, self, loop)
                 if transitive_guard:
                     other.set_to_none(loop.operations)
                     version.register_guard(transitive_guard)
 
-        loop.operations = self._newoperations + \
-                [op for op in loop.operations if op]
+        if self.has_two_labels:
+            oplist = [loop.operations[0]] + self._newoperations + \
+                     [op for op in loop.operations[1:] if op]
+            loop.operations = oplist
+        else:
+            loop.operations = self._newoperations + \
+                    [op for op in loop.operations if op]
 
diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py 
b/rpython/jit/metainterp/optimizeopt/schedule.py
--- a/rpython/jit/metainterp/optimizeopt/schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/schedule.py
@@ -856,34 +856,6 @@
         assert not isinstance(box, BoxVector)
         self.box_to_vbox[box] = (off, vector)
 
-    def prepend_invariant_operations(self, oplist, orig_label_args):
-        if len(self.invariant_oplist) > 0:
-            label = oplist[0]
-            assert label.getopnum() == rop.LABEL
-            #
-            jump = oplist[-1]
-            assert jump.getopnum() == rop.JUMP
-            #
-            label_args = label.getarglist()[:]
-            jump_args = jump.getarglist()
-            for var in self.invariant_vector_vars:
-                label_args.append(var)
-                jump_args.append(var)
-            #
-            # in case of any invariant_vector_vars, the label is restored
-            # and the invariant operations are added between the original label
-            # and the new label
-            descr = label.getdescr()
-            assert isinstance(descr, TargetToken)
-            token = TargetToken(descr.targeting_jitcell_token)
-            oplist[0] = label.copy_and_change(label.getopnum(), 
args=label_args, descr=token)
-            oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args, 
descr=token)
-            #
-            return [ResOperation(rop.LABEL, orig_label_args, None, descr)] + \
-                   self.invariant_oplist + oplist
-        #
-        return oplist
-
 class Pack(object):
     """ A pack is a set of n statements that are:
         * isomorphic
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_guard.py 
b/rpython/jit/metainterp/optimizeopt/test/test_guard.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_guard.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_guard.py
@@ -84,7 +84,7 @@
             if op.is_guard():
                 op.setdescr(compile.CompileLoopVersionDescr())
         dep = DependencyGraph(loop)
-        opt = GuardStrengthenOpt(dep.index_vars)
+        opt = GuardStrengthenOpt(dep.index_vars, False)
         opt.propagate_all_forward(loop, user_code)
         return opt
 
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
@@ -49,10 +49,11 @@
         #
         opt = VectorizingOptimizer(metainterp_sd, jitdriver_sd, loop, 0)
         opt.propagate_all_forward()
-        gso = GuardStrengthenOpt(opt.dependency_graph.index_vars)
+        #
+        gso = GuardStrengthenOpt(opt.dependency_graph.index_vars, 
opt.has_two_labels)
         gso.propagate_all_forward(opt.loop, user_code)
         # connect all compile loop version fail descriptors to this version
-        version.register_all_guards(loop.operations, opt.appended_arg_count)
+        #version.register_all_guards(loop.operations, opt.appended_arg_count)
         #
         #
         end = time.clock()
@@ -135,6 +136,7 @@
         self.costmodel = X86_CostModel(cost_threshold, 
self.cpu.vector_register_size)
         self.appended_arg_count = 0
         self.orig_label_args = None
+        self.has_two_labels = False
 
     def propagate_all_forward(self, clear=True):
         self.clear_newoperations()
@@ -503,11 +505,46 @@
                     accum = arg.getaccum()
                     if accum:
                         accum.save_to_descr(op.getdescr(),i)
-        self.loop.operations = \
-            sched_data.prepend_invariant_operations(self._newoperations,
-                                                    self.orig_label_args)
+            self.has_two_labels = len(sched_data.invariant_oplist) > 0
+            self.loop.operations = 
self.prepend_invariant_operations(sched_data)
+        else:
+            self.loop.operations = self._newoperations
+        
         self.clear_newoperations()
 
+    def prepend_invariant_operations(self, sched_data):
+        """ Add invariant operations to the trace loop. returns the operation 
list
+            as first argument and a second a boolean value. it is true if any 
inva
+        """
+        oplist = self._newoperations
+
+        if len(sched_data.invariant_oplist) > 0:
+            label = oplist[0]
+            assert label.getopnum() == rop.LABEL
+            #
+            jump = oplist[-1]
+            assert jump.getopnum() == rop.JUMP
+            #
+            label_args = label.getarglist()[:]
+            jump_args = jump.getarglist()
+            for var in sched_data.invariant_vector_vars:
+                label_args.append(var)
+                jump_args.append(var)
+            #
+            # in case of any invariant_vector_vars, the label is restored
+            # and the invariant operations are added between the original label
+            # and the new label
+            descr = label.getdescr()
+            assert isinstance(descr, TargetToken)
+            token = TargetToken(descr.targeting_jitcell_token)
+            oplist[0] = label.copy_and_change(label.getopnum(), 
args=label_args, descr=token)
+            oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args, 
descr=token)
+            #
+            return [ResOperation(rop.LABEL, self.orig_label_args, None, 
descr)] + \
+                   sched_data.invariant_oplist + oplist
+        #
+        return oplist
+
     def analyse_index_calculations(self):
         ee_pos = self.loop.find_first_index(rop.GUARD_EARLY_EXIT)
         if len(self.loop.operations) <= 2 or ee_pos == -1:
@@ -580,7 +617,6 @@
             descr.copy_all_attributes_from(olddescr)
         #
         tgt_op.setdescr(descr)
-        tgt_op.rd_snapshot = op.rd_snapshot
         tgt_op.setfailargs(op.getfailargs()[:])
 
 
diff --git a/rpython/jit/metainterp/test/test_vectorize.py 
b/rpython/jit/metainterp/test/test_vectorize.py
--- a/rpython/jit/metainterp/test/test_vectorize.py
+++ b/rpython/jit/metainterp/test/test_vectorize.py
@@ -222,17 +222,19 @@
 
     def test_accum(self):
         myjitdriver = JitDriver(greens = [], reds = 'auto')
-        T = lltype.Array(rffi.DOUBLE, hints={'nolength': True})
+        T = lltype.Array(rffi.DOUBLE)
         def f(d, value):
             va = lltype.malloc(T, d, flavor='raw', zero=True)
             for i in range(d):
                 va[i] = value
             r = 0
             i = 0
+            k = d + 2
+            # in this case a guard k <= d is inserted which fails right away!
             while i < d:
                 myjitdriver.jit_merge_point()
-                if not(i < d):
-                    raise IndexError
+                #if not(i < k):
+                #    k -= 1
                 r += va[i]
                 i += 1
             lltype.free(va, flavor='raw')
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to