Commits

Maciej Fijalkowski committed f002fbc

dance to make interiorfields work

  • Participants
  • Parent commits bb1957c
  • Branches backend-vector-ops

Comments (0)

Files changed (7)

File pypy/jit/backend/llgraph/runner.py

 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0,
+                 width=-1, is_array=False, field_size=-1):
 
         self.ofs = ofs
         self.width = width
         self.arg_types = arg_types
         self.count_fields_if_immut = count_fields_if_immut
         self.ffi_flags = ffi_flags
+        self.is_array_descr = is_array
+        self.field_size = field_size
+
+    def get_field_size(self):
+        return self.field_size
 
     def get_arg_types(self):
         return self.arg_types
     def get_extra_info(self):
         return self.extrainfo
 
+    def get_width(self):
+        return self.width
+
     def sort_key(self):
         """Returns an integer that can be used as a key when sorting the
         field descrs of a single structure.  The property that this
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0,
+                 width=-1, is_array=False, field_size=-1):
         key = (ofs, typeinfo, extrainfo, name, arg_types,
                count_fields_if_immut, ffi_flags, width)
         try:
             return self._descrs[key]
         except KeyError:
             descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
-                          count_fields_if_immut, ffi_flags, width)
+                          count_fields_if_immut, ffi_flags, width, is_array,
+                          field_size)
             self._descrs[key] = descr
             return descr
 
         width = symbolic.get_size(A)
         ofs, size = symbolic.get_field_token(S, fieldname)
         token = history.getkind(getattr(S, fieldname))
-        return self.getdescr(ofs, token[0], name=fieldname, width=width)
+        return self.getdescr(ofs, token[0], name=fieldname, width=width,
+                             field_size=size)
 
     def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
         is_pointer, is_float, is_signed):
         else:
             typeinfo = INT
         # we abuse the arg_types field to distinguish dynamic and static descrs
-        return Descr(offset, typeinfo, arg_types='dynamic', name='<dynamic interior field>', width=width)
+        return Descr(offset, typeinfo, arg_types='dynamic', name='<dynamic interior field>', width=width, field_size=fieldsize)
 
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
         arg_types = []
             token = 's'
         else:
             token = '?'
-        return self.getdescr(size, token)
+        return self.getdescr(size, token, is_array=True)
 
     # ---------- the backend-dependent operations ----------
 

File pypy/jit/backend/llsupport/descr.py

     itemsize = 0
     lendescr = None
     flag = '\x00'
+    is_array_descr = True
 
     def __init__(self, basesize, itemsize, lendescr, flag):
         self.basesize = basesize
     def repr_of_descr(self):
         return '<Array%s %s>' % (self.flag, self.itemsize)
 
+    def get_item_size(self):
+        return self.itemsize
+
 
 def get_array_descr(gccache, ARRAY_OR_STRUCT):
     cache = gccache._cache_array
     def repr_of_descr(self):
         return '<InteriorFieldDescr %s>' % self.fielddescr.repr_of_descr()
 
+    def get_item_size(self):
+        return self.fielddescr.field_size
+
+    def get_width(self):
+        return self.arraydescr.itemsize
+
 def get_interiorfield_descr(gc_ll_descr, ARRAY, name):
     cache = gc_ll_descr._cache_interiorfield
     try:

File pypy/jit/metainterp/executor.py

 
 
 IGNORED = ['FLOAT_VECTOR_ADD', 'FLOAT_VECTOR_SUB',
-           'GETARRAYITEM_VECTOR_RAW',
+           'GETARRAYITEM_VECTOR_RAW', 'GETINTERIORFIELD_VECTOR_RAW',
+           'SETINTERIORFIELD_VECTOR_RAW',
            'SETARRAYITEM_VECTOR_RAW', 'ASSERT_ALIGNED']
 
 def _make_execute_list():

File pypy/jit/metainterp/history.py

 
 class AbstractDescr(AbstractValue):
     __slots__ = ()
+    is_array_descr = False
 
     def repr_of_descr(self):
         return '%r' % (self,)

File pypy/jit/metainterp/optimizeopt/test/test_vectorize.py

         cpu = LLtypeMixin.cpu
         FUNC = LLtypeMixin.FUNC
         arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
+        interiordescr = cpu.interiorfielddescrof_dynamic(0, 1, 8, False, True,
+                                                         False)
 
         def calldescr(cpu, FUNC, oopspecindex, extraeffect=None):
             if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
         f0 = getarrayitem_raw(p0, i0, descr=arraydescr)
         f1 = getarrayitem_raw(p1, i1, descr=arraydescr)
         f2 = float_add(f0, f1)
-        setarrayitem_raw(p2, i2, f2)
+        setarrayitem_raw(p2, i2, f2, descr=arraydescr)
         i3 = cast_float_to_int(f2)
         finish(p0, p1, p2, i0, i1, i3)
         """
         f0 = getarrayitem_raw(p0, i0, descr=arraydescr)
         f1 = getarrayitem_raw(p1, i1, descr=arraydescr)
         f2 = float_add(f0, f1)
-        setarrayitem_raw(p2, i2, f2)
+        setarrayitem_raw(p2, i2, f2, descr=arraydescr)
         i3 = cast_float_to_int(f2)
         finish(p0, p1, p2, i0, i1, i3)
         """
         self.optimize_loop(ops, expected)
+
+    def test_getinteriorfield(self):
+        ops = """
+        [p0, p1, p2, i0, i1, i2]
+        call(0, p0, i0, descr=assert_aligned)
+        call(0, p1, i1, descr=assert_aligned)
+        call(0, p1, i2, descr=assert_aligned)
+        f0 = getinteriorfield_raw(p0, i0, descr=interiordescr)
+        f1 = getinteriorfield_raw(p1, i1, descr=interiordescr)
+        f2 = float_add(f0, f1)
+        setinteriorfield_raw(p2, i2, f2, descr=interiordescr)
+        i0_1 = int_add(i0, 8)
+        i1_1 = int_add(8, i1)
+        i2_1 = int_add(i2, 8)
+        f0_1 = getinteriorfield_raw(p0, i0_1, descr=interiordescr)
+        f1_1 = getinteriorfield_raw(p1, i1_1, descr=interiordescr)
+        f2_1 = float_add(f0_1, f1_1)
+        setinteriorfield_raw(p2, i2_1, f2_1, descr=interiordescr)
+        finish(p0, p1, p2, i0_1, i1_1, i2_1)
+        """
+        expected = """
+        [p0, p1, p2, i0, i1, i2]
+        i0_1 = int_add(i0, 8)
+        i1_1 = int_add(8, i1)
+        i2_1 = int_add(i2, 8)
+        vec0 = getinteriorfield_vector_raw(p0, i0, descr=interiordescr)
+        vec1 = getinteriorfield_vector_raw(p1, i1, descr=interiordescr)
+        vec2 = float_vector_add(vec0, vec1)
+        setinteriorfield_vector_raw(p2, i2, vec2, descr=interiordescr)
+        finish(p0, p1, p2, i0_1, i1_1, i2_1)        
+        """
+        self.optimize_loop(ops, expected)
+    
+    def test_getinteriorfield_wrong(self):
+        ops = """
+        [p0, p1, p2, i0, i1, i2]
+        call(0, p0, i0, descr=assert_aligned)
+        call(0, p1, i1, descr=assert_aligned)
+        call(0, p1, i2, descr=assert_aligned)
+        f0 = getinteriorfield_raw(p0, i0, descr=interiordescr)
+        f1 = getinteriorfield_raw(p1, i1, descr=interiordescr)
+        f2 = float_add(f0, f1)
+        setinteriorfield_raw(p2, i2, f2, descr=interiordescr)
+        i0_1 = int_add(i0, 1)
+        i1_1 = int_add(1, i1)
+        i2_1 = int_add(i2, 1)
+        f0_1 = getinteriorfield_raw(p0, i0_1, descr=interiordescr)
+        f1_1 = getinteriorfield_raw(p1, i1_1, descr=interiordescr)
+        f2_1 = float_add(f0_1, f1_1)
+        setinteriorfield_raw(p2, i2_1, f2_1, descr=interiordescr)
+        finish(p0, p1, p2, i0_1, i1_1, i2_1)
+        """
+        expected = """
+        [p0, p1, p2, i0, i1, i2]
+        i0_1 = int_add(i0, 1)
+        i1_1 = int_add(1, i1)
+        i2_1 = int_add(i2, 1)
+        f0 = getinteriorfield_raw(p0, i0, descr=interiordescr)
+        f1 = getinteriorfield_raw(p1, i1, descr=interiordescr)
+        f2 = float_add(f0, f1)
+        setinteriorfield_raw(p2, i2, f2, descr=interiordescr)
+        f0_1 = getinteriorfield_raw(p0, i0_1, descr=interiordescr)
+        f1_1 = getinteriorfield_raw(p1, i1_1, descr=interiordescr)
+        f2_1 = float_add(f0_1, f1_1)
+        setinteriorfield_raw(p2, i2_1, f2_1, descr=interiordescr)
+        finish(p0, p1, p2, i0_1, i1_1, i2_1)
+        """
+        self.optimize_loop(ops, expected)
+

File pypy/jit/metainterp/optimizeopt/vectorize.py

 
 VECTOR_SIZE = 2
 VEC_MAP = {rop.FLOAT_ADD: rop.FLOAT_VECTOR_ADD,
-           rop.FLOAT_SUB: rop.FLOAT_VECTOR_SUB}
+           rop.FLOAT_SUB: rop.FLOAT_VECTOR_SUB,
+           rop.GETINTERIORFIELD_RAW: rop.GETINTERIORFIELD_VECTOR_RAW,
+           rop.SETINTERIORFIELD_RAW: rop.SETINTERIORFIELD_VECTOR_RAW,
+           rop.GETARRAYITEM_RAW: rop.GETARRAYITEM_VECTOR_RAW,
+           rop.SETARRAYITEM_RAW: rop.SETARRAYITEM_VECTOR_RAW,
+           }
+
 
 class BaseTrack(object):
     pass
 
     def emit(self, optimizer):
         box = BoxVector()
-        op = ResOperation(rop.GETARRAYITEM_VECTOR_RAW, [self.arr.box,
+        op = ResOperation(VEC_MAP[self.op.getopnum()], [self.arr.box,
                                                         self.index.val.box],
                           box, descr=self.op.getdescr())
         optimizer.emit_operation(op)
     def match(self, other, i):
         if not isinstance(other, Write):
             return False
+        descr = self.op.getdescr()
+        i = i * descr.get_field_size() / descr.get_width()
         return self.v.match(other.v, i)
 
     def emit(self, optimizer):
         arg = self.v.emit(optimizer)
-        op = ResOperation(rop.SETARRAYITEM_VECTOR_RAW, [self.arr.box,
+        op = ResOperation(VEC_MAP[self.op.getopnum()], [self.arr.box,
                                                         self.index.box, arg],
                           None, descr=self.op.getdescr())
         optimizer.emit_operation(op)
         self.val = val
         self.index = index
 
-    def advance(self):
-        return TrackIndex(self.val, self.index + 1)
+    def advance(self, v):
+        return TrackIndex(self.val, self.index + v)
+
+    def match_descr(self, descr):
+        if self.index == 0:
+            return True
+        if descr.is_array_descr:
+            return self.index == 1
+        if descr.get_width() != 1:
+            return False # XXX this can probably be supported
+        return self.index == descr.get_field_size()
 
 class OptVectorize(Optimization):
     def __init__(self):
         track = self.tracked_indexes.get(index, None)
         if track is None:
             self.emit_operation(op)
+        elif not track.match_descr(op.getdescr()):
+            self.reset()
+            self.emit_operation(op)
         else:
             self.ops_so_far.append(op)
             self.track[self.getvalue(op.result)] = Read(arr, track, op)
         one = self.getvalue(op.getarg(0))
         two = self.getvalue(op.getarg(1))
         self.emit_operation(op)
-        if (one.is_constant() and one.box.getint() == 1 and
-            two in self.tracked_indexes):
+        if (one.is_constant() and two in self.tracked_indexes):
             index = two
-        elif (two.is_constant() and two.box.getint() == 1 and
-              one in self.tracked_indexes):
+            v = one.box.getint()
+        elif (two.is_constant() and one in self.tracked_indexes):
             index = one
+            v = two.box.getint()
         else:
             return
-        self.tracked_indexes[self.getvalue(op.result)] = self.tracked_indexes[index].advance()
+        self.tracked_indexes[self.getvalue(op.result)] = self.tracked_indexes[index].advance(v)
 
     def _optimize_binop(self, op):
         left = self.getvalue(op.getarg(0))
         right = self.getvalue(op.getarg(1))
         if left not in self.track or right not in self.track:
+            if left in self.track or right in self.track:
+                self.reset()
             self.emit_operation(op)
         else:
             self.ops_so_far.append(op)
         index = self.getvalue(op.getarg(1))
         val = self.getvalue(op.getarg(2))
         if index not in self.tracked_indexes or val not in self.track:
+            # We could detect cases here, but we're playing on the safe
+            # side and just resetting everything
+            self.reset()
             self.emit_operation(op)
             return
         self.ops_so_far.append(op)
         ti = self.tracked_indexes[index]
         if arr not in self.full:
             self.full[arr] = [None] * VECTOR_SIZE
-        self.full[arr][ti.index] = Write(arr, index, v, op)
+        i = (ti.index * op.getdescr().get_width() //
+             op.getdescr().get_field_size())
+        self.full[arr][i] = Write(arr, index, v, op)
 
     optimize_SETINTERIORFIELD_RAW = optimize_SETARRAYITEM_RAW
 

File pypy/jit/metainterp/resoperation.py

     'GETARRAYITEM_VECTOR_RAW/2d',
     'GETARRAYITEM_RAW/2d',
     'GETINTERIORFIELD_GC/2d',
+    'GETINTERIORFIELD_VECTOR_RAW/2d',
     'GETINTERIORFIELD_RAW/2d',
     'GETFIELD_GC/1d',
     'GETFIELD_RAW/1d',
     'SETARRAYITEM_RAW/3d',
     'SETARRAYITEM_VECTOR_RAW/3d',
     'SETINTERIORFIELD_GC/3d',
+    'SETINTERIORFIELD_VECTOR_RAW/3d',
     'SETINTERIORFIELD_RAW/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',