[pypy-svn] pypy numpy-exp: in-progress. Start implementing vector operations. It's a bit annoying because

fijal commits-noreply at bitbucket.org
Tue Mar 22 22:04:45 CET 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-exp
Changeset: r42850:e583fdf3b8b1
Date: 2011-03-22 15:03 -0600
http://bitbucket.org/pypy/pypy/changeset/e583fdf3b8b1/

Log:	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.

diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -15,6 +15,7 @@
 INT   = 'i'
 REF   = 'r'
 FLOAT = 'f'
+VECTOR = 'F'
 HOLE  = '_'
 VOID  = 'v'
 
@@ -508,6 +509,9 @@
     def forget_value(self):
         raise NotImplementedError
 
+class BoxVector(Box):
+    _attrs_ = ()
+
 class BoxInt(Box):
     type = INT
     _attrs_ = ('value',)

diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -161,7 +161,6 @@
     'force_token'     : ((), 'int'),
     'call_may_force'  : (('int', 'varargs'), 'intorptr'),
     'guard_not_forced': ((), None),
-    'sse_float_add'   : (('int', 'int', 'int', 'int'), None),
 }
 
 # ____________________________________________________________
@@ -736,12 +735,6 @@
 
     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)

diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -394,11 +394,6 @@
     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,

diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -947,3 +947,7 @@
     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})
+    

diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -578,10 +578,6 @@
 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):

diff --git a/pypy/rlib/rvector.py b/pypy/rlib/rvector.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/rvector.py
@@ -0,0 +1,31 @@
+
+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)'

diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -125,17 +125,6 @@
     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():

diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1069,15 +1069,6 @@
     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")

diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -441,10 +441,6 @@
     '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),

diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -351,6 +351,8 @@
             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:
@@ -476,14 +478,6 @@
         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):
@@ -1359,6 +1353,17 @@
             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)
 

diff --git a/pypy/rlib/test/test_rvector.py b/pypy/rlib/test/test_rvector.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/test_rvector.py
@@ -0,0 +1,56 @@
+
+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()

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5515,9 +5515,6 @@
         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
 
-
-
-
 ##class TestOOtype(OptimizeOptTest, OOtypeMixin):
 
 ##    def test_instanceof(self):

diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -466,7 +466,6 @@
     'SETARRAYITEM_RAW/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',
-    'SSE_FLOAT_ADD/4d',
     'STRSETITEM/3',
     'UNICODESETITEM/3',
     #'RUNTIMENEW/1',     # ootype operation    


More information about the Pypy-commit mailing list