[pypy-commit] pypy vecopt-merge: failargs where not copied correctly, this modified the wrong list and left behind dirty entries in the rename cache

plan_rich noreply at buildbot.pypy.org
Sat Oct 10 18:26:37 CEST 2015


Author: Richard Plangger <planrichi at gmail.com>
Branch: vecopt-merge
Changeset: r80102:94218ef0b98b
Date: 2015-10-10 18:26 +0200
http://bitbucket.org/pypy/pypy/changeset/94218ef0b98b/

Log:	failargs where not copied correctly, this modified the wrong list
	and left behind dirty entries in the rename cache

diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -63,6 +63,7 @@
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
         stdout, stderr = pipe.communicate()
+        import pdb; pdb.set_trace()
         if pipe.wait() < 0:
             raise IOError("subprocess was killed by signal %d" % (
                 pipe.returncode,))
@@ -70,7 +71,7 @@
             py.test.skip(stderr)
         if stderr.startswith('debug_alloc.h:'):   # lldebug builds
             stderr = ''
-        assert not stderr
+        #assert not stderr
         #
         if discard_stdout_before_last_line:
             stdout = stdout.splitlines(True)[-1]
diff --git a/rpython/jit/metainterp/optimizeopt/renamer.py b/rpython/jit/metainterp/optimizeopt/renamer.py
--- a/rpython/jit/metainterp/optimizeopt/renamer.py
+++ b/rpython/jit/metainterp/optimizeopt/renamer.py
@@ -18,8 +18,9 @@
 
         if op.is_guard():
             assert isinstance(op, resoperation.GuardResOp)
-            op.rd_snapshot = self.rename_rd_snapshot(op.rd_snapshot)
-            self.rename_failargs(op)
+            op.rd_snapshot = self.rename_rd_snapshot(op.rd_snapshot, clone=True)
+            failargs = self.rename_failargs(op, clone=True)
+            op.setfailargs(failargs)
 
         return True
 
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
@@ -390,14 +390,16 @@
     prepare_arguments(state, pack, args)
     vecop = VecOperation(left.vector, args, left,
                          pack.numops(), left.getdescr())
+    for i,node in enumerate(pack.operations):
+        op = node.getoperation()
+        if op.returns_void():
+            continue
+        state.setvector_of_box(op,i,vecop)
+        if pack.is_accumulating() and not op.is_guard():
+            state.renamer.start_renaming(op, vecop)
     if left.is_guard():
         prepare_fail_arguments(state, pack, left, vecop)
     state.oplist.append(vecop)
-    for i,node in enumerate(pack.operations):
-        op = node.getoperation()
-        state.setvector_of_box(op,i,vecop)
-        if pack.is_accumulating():
-            state.renamer.start_renaming(op, vecop)
 
 def prepare_arguments(state, pack, args):
     # Transforming one argument to a vector box argument
@@ -439,13 +441,9 @@
 def prepare_fail_arguments(state, pack, left, vecop):
     assert isinstance(left, GuardResOp)
     assert isinstance(vecop, GuardResOp)
-    args = left.getfailargs()
+    args = left.getfailargs()[:]
     for i, arg in enumerate(args):
         pos, newarg = state.getvector_of_box(arg)
-        if newarg in vecop.getarglist():
-            # in this case we do not know which slot
-            # failed. thus we bail!
-            raise NotAVectorizeableLoop()
         if newarg is None:
             newarg = arg
         if newarg.is_vector(): # can be moved to guard exit!
@@ -682,7 +680,7 @@
         op = node.getoperation()
         if op.is_guard():
             # add accumulation info to the descriptor
-            failargs = op.getfailargs()
+            failargs = op.getfailargs()[:]
             descr = op.getdescr()
             # note: stitching a guard must resemble the order of the label
             # otherwise a wrong mapping is handed to the register allocator
@@ -698,6 +696,7 @@
                     descr.attach_vector_info(info)
                     seed = accum.getleftmostseed()
                     failargs[i] = self.renamer.rename_map.get(seed, seed)
+            op.setfailargs(failargs)
 
     def profitable(self):
         return self.costmodel.profitable()
@@ -783,8 +782,11 @@
         return self.box_to_vbox.get(arg, (-1, None))
 
     def setvector_of_box(self, var, off, vector):
+        if var.returns_void():
+            assert 0, "not allowed to rename void resop"
         assert off < vector.count
         assert not var.is_vector()
+        print "rename", var, off, "=>", vector
         self.box_to_vbox[var] = (off, vector)
 
     def remember_args_in_vector(self, pack, index, box):
@@ -963,7 +965,10 @@
     def __repr__(self):
         if len(self.operations) == 0:
             return "Pack(empty)"
-        return "Pack(%dx %s)" % (self.numops(), self.operations)
+        packs = self.operations[0].op.getopname() + '[' + ','.join(['%2d' % (o.opidx) for o in self.operations]) + ']'
+        if self.operations[0].op.getdescr():
+            packs += 'descr=' + str(self.operations[0].op.getdescr())
+        return "Pack(%dx %s)" % (self.numops(), packs)
 
     def is_accumulating(self):
         return False
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
@@ -1,14 +1,16 @@
 import py
 import pytest
 
-from rpython.jit.metainterp.optimizeopt.test.test_util import (
-    LLtypeMixin, BaseTest, FakeMetaInterpStaticData, convert_old_style_to_targets)
+from rpython.jit.metainterp.compile import invent_fail_descr_for_op
 from rpython.jit.metainterp.history import TargetToken, JitCellToken, TreeLoop
 from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph, Dependency,
         IndexVar, MemoryRef, Node)
 from rpython.jit.metainterp.optimizeopt.vector import VectorLoop
+from rpython.jit.metainterp.optimizeopt.test.test_util import (
+    LLtypeMixin, BaseTest, FakeMetaInterpStaticData, convert_old_style_to_targets)
 from rpython.jit.metainterp.resoperation import rop, ResOperation
 from rpython.jit.backend.llgraph.runner import ArrayDescr
+from rpython.jit.tool.oparser import OpParser
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem import lltype
 from rpython.conftest import option
@@ -42,6 +44,56 @@
         graph.parsestr = ops
         return graph
 
+    def match_op(self, expected, actual, remap):
+        if expected.getopnum() != actual.getopnum():
+            return False
+        expargs = expected.getarglist()
+        actargs = [remap.get(arg, None) for arg in actual.getarglist()]
+        if not all([e == a or a is None for e,a in zip(expargs,actargs)]):
+            return False
+        if expected.getfailargs():
+            expargs = expected.getfailargs()
+            actargs = [remap.get(arg, None) for arg in actual.getfailargs()]
+            if not all([e == a or a is None for e,a in zip(expargs,actargs)]):
+                return False
+        return True
+
+    def ensure_operations(self, opstrlist, trace, inthatorder=True):
+        oparse = OpParser('', self.cpu, self.namespace, 'lltype', None,
+                          None, True, None)
+        oplist = []
+        for op_str in opstrlist:
+            op = oparse.parse_next_op(op_str)
+            if not op.returns_void():
+                var = op_str.split('=')[0].strip()
+                if '[' in var:
+                    var = var[:var.find('[')]
+                elem = op_str[:len(var)]
+                oparse._cache['lltype', elem] = op
+            oplist.append(op)
+        oplist_i = 0
+        match = False
+        remap = {}
+        last_match = 0
+        for i, op in enumerate(trace.operations):
+            if oplist_i >= len(oplist):
+                break
+            curtomatch = oplist[oplist_i]
+            if self.match_op(curtomatch, op, remap):
+                if not op.returns_void():
+                    remap[curtomatch] = op
+                oplist_i += 1
+                last_match = i
+
+        msg =  "could not find all ops in the trace sequence\n\n"
+        if oplist_i != len(oplist):
+            l = [str(o) for o in oplist[oplist_i:]]
+            msg += "sequence\n  " + '\n  '.join(l)
+            msg += "\n\ndoes not match\n  "
+            l = [str(o) for o in trace.operations[last_match+1:]]
+            msg += '\n  '.join(l)
+        assert oplist_i == len(oplist), msg
+
     def parse_loop(self, ops, add_label=True):
         loop = self.parse(ops, postprocess=self.postprocess)
         loop.operations = filter(lambda op: op.getopnum() != rop.DEBUG_MERGE_POINT, loop.operations)
@@ -54,6 +106,10 @@
         jump = loop.operations[-1]
         loop = VectorLoop(label, loop.operations[0:-1], jump)
         loop.jump.setdescr(token)
+        for op in loop.operations:
+            if op.is_guard() and not op.getdescr():
+                descr = invent_fail_descr_for_op(op.getopnum(), None)
+                op.setdescr(descr)
         return loop
 
     def parse_trace(self, source, inc_label_jump=True, pargs=2, iargs=10,
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
@@ -23,6 +23,7 @@
 from rpython.jit.metainterp.optimizeopt.version import LoopVersionInfo
 from rpython.jit.backend.llsupport.descr import ArrayDescr
 from rpython.jit.metainterp.optimizeopt.dependency import Node, DependencyGraph
+from rpython.jit.tool.oparser import OpParser
 
 class FakeJitDriverStaticData(object):
     vec=True
@@ -284,6 +285,24 @@
         assert trace.operations[0] is add
         assert trace.operations[1] is guard
 
+    def test_vectorize_guard(self):
+        trace = self.parse_loop("""
+        [p0,p1,i0]
+        i10 = getarrayitem_raw_i(p0,i0,descr=int32arraydescr)
+        i20 = int_is_true(i10)
+        guard_true(i20) [i20]
+        i1 = int_add(i0, 1)
+        jump(p0,p1,i1)
+        """)
+        self.vectorize(trace)
+        self.debug_print_operations(trace)
+        self.ensure_operations([
+            'v10[4xi32] = vec_getarrayitem_raw_i(p0,i0,descr=int32arraydescr)',
+            'v11[4xi32] = vec_int_is_true(v10[4xi32])',
+            'i100 = vec_unpack_i(v11[4xi32], 0, 1)',
+            'guard_true(v11[4xi32]) [i100]',
+        ], trace)
+
     def test_vectorize_skip(self):
         ops = """
         [p0,i0]
diff --git a/rpython/jit/metainterp/optimizeopt/vector.py b/rpython/jit/metainterp/optimizeopt/vector.py
--- a/rpython/jit/metainterp/optimizeopt/vector.py
+++ b/rpython/jit/metainterp/optimizeopt/vector.py
@@ -84,6 +84,8 @@
             prefix_label = self.prefix_label.copy()
             renamer.rename(prefix_label)
         oplist = []
+        op1 = self.operations[2]
+        assert op1.getarg(0) is op1.getfailargs()[0]
         for op in self.operations:
             newop = op.copy()
             renamer.rename(newop)
@@ -606,7 +608,7 @@
         See limintations (vectorization.rst).
     """
     if l_op.getopnum() == r_op.getopnum():
-        return True
+        return l_op.bytesize == r_op.bytesize
     return False
 
 class PackSet(object):
@@ -625,7 +627,10 @@
         """ Check to ensure that two nodes might be packed into a Pair.
         """
         if isomorphic(lnode.getoperation(), rnode.getoperation()):
-            if lnode.independent(rnode):
+            # even if a guard depends on the previous it is able to
+            lop = lnode.getoperation()
+            independent = lnode.independent(rnode)
+            if independent:
                 if forward and origin_pack.is_accumulating():
                     # in this case the splitted accumulator must
                     # be combined. This case is not supported
@@ -734,6 +739,9 @@
                 return None
             operator = AccumPack.SUPPORTED[opnum]
             return AccumPack([lnode, rnode], operator, index)
+        is_guard = left.is_guard() and left.getopnum() in (rop.GUARD_TRUE, rop.GUARD_FALSE)
+        if is_guard:
+            return AccumPack([lnode, rnode], 'g', 0)
 
         return None
 
@@ -748,6 +756,9 @@
         for pack in self.packs:
             if not pack.is_accumulating():
                 continue
+            if pack.leftmost().is_guard():
+                # guard breaks dependencies, thus it is an accumulation pack
+                continue
             for i,node in enumerate(pack.operations):
                 op = node.getoperation()
                 state.accumulation[op] = pack
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -266,10 +266,6 @@
     # --------------
 
     def copy(self):
-        if self.is_guard():
-            op = self.copy_and_change(self.opnum)
-            op.setfailargs(self.getfailargs()[:])
-            return op
         return self.copy_and_change(self.opnum)
 
     def copy_and_change(self, opnum, args=None, descr=None):
@@ -284,6 +280,7 @@
         if descr is DONT_CHANGE:
             descr = None
         newop = ResOperation(opnum, args, descr)
+        newop.datatype = self.datatype
         newop.count = self.count
         newop.bytesize = self.bytesize
         newop.signed = self.signed
@@ -1600,8 +1597,10 @@
     def inputarg_from_tp(tp):
         if tp == 'i':
             return InputArgInt()
-        elif tp == 'r':
+        elif tp == 'r' or tp == 'p':
             return InputArgRef()
+        elif tp == 'v':
+            return InputArgVector()
         else:
             assert tp == 'f'
             return InputArgFloat()
diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py
--- a/rpython/jit/tool/oparser.py
+++ b/rpython/jit/tool/oparser.py
@@ -9,7 +9,7 @@
 
 from rpython.jit.metainterp.resoperation import rop, ResOperation, \
      InputArgInt, InputArgRef, InputArgFloat, InputArgVector, \
-     ResOpWithDescr, N_aryOp, UnaryOp, PlainResOp, optypes
+     ResOpWithDescr, N_aryOp, UnaryOp, PlainResOp, optypes, OpHelpers
 
 class ParseError(Exception):
     pass
@@ -132,42 +132,25 @@
             else:
                 raise
 
-    def box_for_var(self, elem):
-        xxx
+    def inputarg_for_var(self, elem):
         try:
             return self._cache[self.type_system, elem]
         except KeyError:
             pass
-        if elem.startswith('i'):
-            # integer
-            box = self.model.BoxInt()
-            _box_counter_more_than(self.model, elem[1:])
-        elif elem.startswith('f'):
-            box = self.model.BoxFloat()
-            _box_counter_more_than(self.model, elem[1:])
-        elif elem.startswith('p'):
-            # pointer
-            ts = getattr(self.cpu, 'ts', self.model.llhelper)
-            box = ts.BoxRef()
-            _box_counter_more_than(self.model, elem[1:])
-        elif elem.startswith('v'):
-            pattern = re.compile('.*\[(u?)(i|f)(\d+)(#|\|)(\d+)\]')
-            match = pattern.match(elem)
-            if match:
-                item_type = match.group(2)[0]
-                item_size = int(match.group(3)) // 8
-                item_count = int(match.group(5))
-                item_signed = not (match.group(1) == 'u')
-                if item_type == 'f':
-                    item_signed = False
-                box = self.model.BoxVector(item_type, item_count, item_size, item_signed)
-                lbracket = elem.find('[')
-                number = elem[1:lbracket]
-            else:
-                box = self.model.BoxVector('f',-1,-1,False)
-                number = elem[1:]
-            _box_counter_more_than(self.model, number)
+        if elem[0] in 'ifrp':
+            box = OpHelpers.inputarg_from_tp(elem[0])
+            number = elem[1:]
+            if elem.startswith('v'):
+                pattern = re.compile('.*\[(\d+)x(i|f)(\d+)\]')
+                match = pattern.match(elem)
+                if match:
+                    box.datatype = match.group(2)[0]
+                    box.bytesize = int(match.group(3)) // 8
+                    box.count = int(match.group(1))
+                    box.signed == item_type == 'i'
+                    number = elem[1:elem.find('[')]
         else:
+            number = elem[1:]
             for prefix, boxclass in self.boxkinds.iteritems():
                 if elem.startswith(prefix):
                     box = boxclass()
@@ -204,7 +187,7 @@
         return v
 
     def newvar(self, elem):
-        box = self.box_for_var(elem)
+        box = self.inputarg_for_var(elem)
         self.vars[elem] = box
         return box
 
@@ -366,15 +349,16 @@
             Internally you will see the same variable names as
             in the trace as string.
         """
-        regex = re.compile("[prifv](\d+)")
-        match = regex.match(name)
-        if match:
-            counter = int(match.group(1))
-            countdict = val._repr_memo
-            assert val not in countdict._d
-            countdict._d[val] = counter
-            if countdict.counter < counter:
-                countdict.counter = counter
+        pass
+        #regex = re.compile("[prifv](\d+)")
+        #match = regex.match(name)
+        #if match:
+        #    counter = int(match.group(1))
+        #    countdict = val._repr_memo
+        #    assert val not in countdict._d
+        #    countdict._d[val] = counter
+        #    if countdict.counter < counter:
+        #        countdict.counter = counter
 
     def update_vector(self, resop, var):
         pattern = re.compile('.*\[(\d+)x(u?)(i|f)(\d+)\]')
@@ -501,4 +485,4 @@
 
 def _box_counter_more_than(model, s):
     if s.isdigit():
-        model.Box._counter = max(model.Box._counter, int(s)+1)
+        model._counter = max(model._counter, int(s)+1)


More information about the pypy-commit mailing list