Commits

Maciej Fijalkowski  committed e583fdf

in-progress. Start implementing vector operations. It's a bit annoying because
we don't (can't?) have a type representing sse vector while not jitted so
a bit of dance is required.

  • Participants
  • Parent commits d4efba8
  • Branches numpy-exp

Comments (0)

Files changed (13)

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

     'force_token'     : ((), 'int'),
     'call_may_force'  : (('int', 'varargs'), 'intorptr'),
     'guard_not_forced': ((), None),
-    'sse_float_add'   : (('int', 'int', 'int', 'int'), None),
 }
 
 # ____________________________________________________________
 
     op_getarrayitem_raw_pure = op_getarrayitem_raw
 
-    def op_sse_float_add(self, arraydescr, array1, array2, arrayres,
-                         index):
-        from pypy.jit.metainterp.blackhole import BlackholeInterpreter
-        return BlackholeInterpreter.bhimpl_sse_float_add.im_func(self.cpu,
-               arraydescr, array1, array2, arrayres, index)
-
     def op_getfield_gc(self, fielddescr, struct):
         if fielddescr.typeinfo == REF:
             return do_getfield_gc_ptr(struct, fielddescr.ofs)

File pypy/jit/codewriter/jtransform.py

             prepare = self._handle_jit_call
         elif oopspec_name.startswith('libffi_'):
             prepare = self._handle_libffi_call
+        elif oopspec_name.startswith('vector_'):
+            prepare = self._handle_vector_op
         else:
             prepare = self.prepare_builtin_call
         try:
         return self._do_builtin_call(op, 'raw_free', [op.args[0]],
                                      extra = (ARRAY,), extrakey = ARRAY)
 
-    def rewrite_op_sse_float_add(self, op):
-        ARRAY = op.args[0].concretetype.TO
-        arraydescr = self.cpu.arraydescrof(ARRAY)
-        kind = getkind(op.result.concretetype)
-        assert kind == 'void'
-        return SpaceOperation('sse_float_add',
-                              [arraydescr] + op.args, op.result)
-
     def rewrite_op_getarrayitem(self, op):
         ARRAY = op.args[0].concretetype.TO
         if self._array_of_voids(ARRAY):
             assert False, 'unsupported oopspec: %s' % oopspec_name
         return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
 
+    # ----------
+    # vector ops
+
+    def _handle_vector_op(self, op, oopspec_name, args):
+        if oopspec_name in ['vector_float_read',
+                            'vector_float_write',
+                            'vector_float_add']:
+            return SpaceOperation(oopspec_name, op.args, op.result)
+        else:
+            raise NotSupported(oopspec_name)
+
     def rewrite_op_jit_force_virtual(self, op):
         return self._do_builtin_call(op)
 

File pypy/jit/codewriter/test/test_jtransform.py

     assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY
     assert op1.args[2] == ListOfKind('int', [v3, v4, v5])
     assert op1.args[3] == ListOfKind('ref', [v1, v2])
+
+def test_vector_ops():
+    TP = lltype.Array(lltype.Float, hints={'nolength': True})
+    

File pypy/jit/metainterp/blackhole.py

     def bhimpl_setarrayitem_raw_f(cpu, array, arraydescr, index, newvalue):
         cpu.bh_setarrayitem_raw_f(arraydescr, array, index, newvalue)
 
-    @arguments("cpu", "d", "i", "i", "i", "i")
-    def bhimpl_sse_float_add(cpu, arraydescr, array1, array2, array_res, index):
-        one = cpu.bh_getarrayitem_raw_f(arraydescr, array1, index)
-        two = cpu.bh_getarrayitem_raw_f(arraydescr, array2, index)
-        cpu.bh_setarrayitem_raw_f(arraydescr, array_res, index, one + two)
-        one = cpu.bh_getarrayitem_raw_f(arraydescr, array1, index + 1)
-        two = cpu.bh_getarrayitem_raw_f(arraydescr, array2, index + 1)
-        cpu.bh_setarrayitem_raw_f(arraydescr, array_res, index + 1, one + two)
-
     # note, there is no 'r' here, since it can't happen
 
     @arguments("cpu", "r", "d", returns="i")

File pypy/jit/metainterp/executor.py

     else:
         cpu.bh_setarrayitem_raw_i(arraydescr, array, index, itembox.getint())
 
-def do_sse_float_add(cpu, _, array1, array2, arrayres, indexbox, arraydescr):
-    onebox = do_getarrayitem_raw(cpu, _, array1, indexbox, arraydescr)
-    twobox = do_getarrayitem_raw(cpu, _, array2, indexbox, arraydescr)
-    res = onebox.getfloat() + twobox.getfloat()
-    do_setarrayitem_raw(cpu, _, arrayres, indexbox, BoxFloat(res), arraydescr)
-    indexbox = BoxInt(indexbox.getint() + 1)
-    onebox = do_getarrayitem_raw(cpu, _, array1, indexbox, arraydescr)
-    twobox = do_getarrayitem_raw(cpu, _, array2, indexbox, arraydescr)
-    res = onebox.getfloat() + twobox.getfloat()
-    do_setarrayitem_raw(cpu, _, arrayres, indexbox, BoxFloat(res), arraydescr)
-
 def do_getfield_gc(cpu, _, structbox, fielddescr):
     struct = structbox.getref_base()
     if fielddescr.is_pointer_field():

File pypy/jit/metainterp/history.py

 INT   = 'i'
 REF   = 'r'
 FLOAT = 'f'
+VECTOR = 'F'
 HOLE  = '_'
 VOID  = 'v'
 
     def forget_value(self):
         raise NotImplementedError
 
+class BoxVector(Box):
+    _attrs_ = ()
+
 class BoxInt(Box):
     type = INT
     _attrs_ = ('value',)

File pypy/jit/metainterp/pyjitpl.py

     opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any
     opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any
 
-    @arguments("descr", "box", "box", "box", "box")
-    def opimpl_sse_float_add(self, arraydescr, array1, array2, arrayres, index):
-        return self.execute_with_descr(rop.SSE_FLOAT_ADD, arraydescr, array1,
-                                       array2, arrayres, index)
-
     @arguments("box", "descr", "box")
     def _opimpl_getarrayitem_raw_any(self, arraybox, arraydescr, indexbox):
         return self.execute_with_descr(rop.GETARRAYITEM_RAW,

File pypy/jit/metainterp/resoperation.py

     'SETARRAYITEM_RAW/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',
-    'SSE_FLOAT_ADD/4d',
     'STRSETITEM/3',
     'UNICODESETITEM/3',
     #'RUNTIMENEW/1',     # ootype operation    

File pypy/jit/metainterp/test/test_optimizeopt.py

         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
 
-
-
-
 ##class TestOOtype(OptimizeOptTest, OOtypeMixin):
 
 ##    def test_instanceof(self):

File pypy/rlib/rvector.py

+
+from pypy.rpython.extregistry import ExtRegistryEntry
+
+class VectorContainer(object):
+    """ Class that is a container for multiple float/int objects.
+    Can be represented at jit-level by a single register, like xmm
+    on x86 architecture
+    """
+
+class FloatVectorContainer(VectorContainer):
+    """ A container for float values
+    """
+    def __init__(self, val1, val2):
+        self.v1 = val1
+        self.v2 = val2
+
+    def __repr__(self):
+        return '<FloatVector %f %f>' % (self.v1, self.v2)
+
+def vector_float_read(arr, index):
+    return FloatVectorContainer(arr[index], arr[index + 1])
+vector_float_read.oopspec = 'vector_float_read(arr, index)'
+
+def vector_float_write(arr, index, container):
+    arr[index] = container.v1
+    arr[index + 1] = container.v2
+vector_float_write.oopspec = 'vector_from_write(arr, index, container)'
+
+def vector_float_add(left, right):
+    return FloatVectorContainer(left.v1 + right.v1, left.v2 + right.v2)
+vector_float_add.oopspec = 'vector_float_add(left, right)'

File pypy/rlib/test/test_rvector.py

+
+from pypy.rlib.rvector import (vector_float_read, vector_float_write,
+                               vector_float_add)
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.test.test_llinterp import interpret
+
+TP = lltype.Array(lltype.Float, hints={'nolength': True})
+
+class TestRVector(object):
+    def test_direct_add(self):
+        a = lltype.malloc(TP, 16, flavor='raw')
+        b = lltype.malloc(TP, 16, flavor='raw')
+        res = lltype.malloc(TP, 16, flavor='raw')
+        a[0] = 1.2
+        a[1] = 1.3
+        b[0] = 0.1
+        b[1] = 0.3
+        a[10] = 8.3
+        a[11] = 8.1
+        b[10] = 7.8
+        b[11] = 7.6
+        f1 = vector_float_read(a, 0)
+        f2 = vector_float_read(b, 0)
+        vector_float_write(res, 2, vector_float_add(f1, f2))
+        assert res[2] == 1.2 + 0.1
+        assert res[3] == 1.3 + 0.3
+        f1 = vector_float_read(a, 10)
+        f2 = vector_float_read(b, 10)
+        vector_float_write(res, 8, vector_float_add(f1, f2))
+        assert res[8] == 8.3 + 7.8
+        assert res[9] == 8.1 + 7.6
+        lltype.free(a, flavor='raw')
+        lltype.free(b, flavor='raw')
+        lltype.free(res, flavor='raw')
+
+    def test_interpret(self):
+        def f():
+            a = lltype.malloc(TP, 16, flavor='raw')
+            b = lltype.malloc(TP, 16, flavor='raw')
+            res = lltype.malloc(TP, 16, flavor='raw')
+            try:
+                a[0] = 1.2
+                a[1] = 1.3
+                b[0] = 0.1
+                b[1] = 0.3
+                f1 = vector_float_read(a, 0)
+                f2 = vector_float_read(b, 0)
+                vector_float_write(res, 8, vector_float_add(f1, f2))
+                return res[8] * 100 + res[9]
+            finally:
+                lltype.free(a, flavor='raw')
+                lltype.free(b, flavor='raw')
+                lltype.free(res, flavor='raw')
+
+        res = interpret(f, [])
+        assert res == f()

File pypy/rpython/lltypesystem/lloperation.py

     'get_write_barrier_from_array_failing_case': LLOp(sideeffects=False),
     'gc_get_type_info_group': LLOp(sideeffects=False),
 
-    # __________ vectorization ops _______
-
-    'sse_float_add': LLOp(canrun=True),
-
     # __________ GC operations __________
 
     'gc__collect':          LLOp(canunwindgc=True),

File pypy/rpython/lltypesystem/opimpl.py

 def op_shrink_array(array, smallersize):
     return False
 
-def op_sse_float_add(arr1, arr2, arr_res, index):
-    arr_res[index] = arr1[index] + arr2[index]
-    arr_res[index + 1] = arr1[index + 1] + arr2[index + 1]
-
 # ____________________________________________________________
 
 def get_op_impl(opname):