[pypy-commit] pypy numpy-dtype-alt: Introduce a new hint on lltype arrays, uncast_on_llgraph, which tells the llgraph backend to cast them to the correct types.

alex_gaynor noreply at buildbot.pypy.org
Sun Aug 21 21:55:33 CEST 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-dtype-alt
Changeset: r46689:21deb620ea89
Date: 2011-08-21 13:09 -0500
http://bitbucket.org/pypy/pypy/changeset/21deb620ea89/

Log:	Introduce a new hint on lltype arrays, uncast_on_llgraph, which
	tells the llgraph backend to cast them to the correct types. This is
	needed since casts are removed by the codewriter.

	Started fixing micronumpy zjit tests, still some work (annoying
	since it really translates).

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
@@ -57,6 +57,12 @@
     else:
         return LLSupport.from_rstr(s)
 
+FLOAT_ARRAY_TP = lltype.Ptr(lltype.Array(lltype.Float, hints={"nolength": True}))
+def maybe_uncast(TP, array):
+    if array._TYPE.TO._hints.get("uncast_on_llgraph"):
+        array = rffi.cast(TP, array)
+    return array
+
 # a list of argtypes of all operations - couldn't find any and it's
 # very useful.  Note however that the table is half-broken here and
 # there, in ways that are sometimes a bit hard to fix; that's why
@@ -1079,7 +1085,7 @@
     if isinstance(TYPE, lltype.Ptr):
         if isinstance(x, (int, long, llmemory.AddressAsInt)):
             x = llmemory.cast_int_to_adr(x)
-        if TYPE is rffi.VOIDP:
+        if TYPE is rffi.VOIDP or TYPE.TO._hints.get("uncast_on_llgraph"):
             # assume that we want a "C-style" cast, without typechecking the value
             return rffi.cast(TYPE, x)
         return llmemory.cast_adr_to_ptr(x, TYPE)
@@ -1329,8 +1335,8 @@
     return cast_to_floatstorage(array.getitem(index))
 
 def do_getarrayitem_raw_float(array, index):
-    array = array.adr.ptr._obj
-    return cast_to_floatstorage(array.getitem(index))
+    array = maybe_uncast(FLOAT_ARRAY_TP, array.adr.ptr)
+    return cast_to_floatstorage(array._obj.getitem(index))
 
 def do_getarrayitem_gc_ptr(array, index):
     array = array._obj.container
@@ -1392,8 +1398,9 @@
     newvalue = cast_from_floatstorage(ITEMTYPE, newvalue)
     array.setitem(index, newvalue)
 
+
 def do_setarrayitem_raw_float(array, index, newvalue):
-    array = array.adr.ptr
+    array = maybe_uncast(FLOAT_ARRAY_TP, array.adr.ptr)
     ITEMTYPE = lltype.typeOf(array).TO.OF
     newvalue = cast_from_floatstorage(ITEMTYPE, newvalue)
     array._obj.setitem(index, newvalue)
diff --git a/pypy/jit/metainterp/test/test_rawmem.py b/pypy/jit/metainterp/test/test_rawmem.py
--- a/pypy/jit/metainterp/test/test_rawmem.py
+++ b/pypy/jit/metainterp/test/test_rawmem.py
@@ -5,7 +5,7 @@
 class TestJITRawMem(LLJitMixin):
     def test_cast_void_ptr(self):
         TP = lltype.Array(lltype.Float, hints={"nolength": True})
-        VOID_TP = lltype.Array(lltype.Void, hints={"nolength": True})
+        VOID_TP = lltype.Array(lltype.Void, hints={"nolength": True, "uncast_on_llgraph": True})
         class A(object):
             def __init__(self, x):
                 self.storage = rffi.cast(lltype.Ptr(VOID_TP), x)\
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,24 +3,29 @@
 It should not be imported by the module itself
 """
 
+from pypy.interpreter.baseobjspace import InternalSpaceCache
+from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
 from pypy.module.micronumpy.interp_numarray import Scalar, SingleDimArray, BaseArray
 
 
 class BogusBytecode(Exception):
     pass
 
-def create_array(size):
-    a = SingleDimArray(size)
+def create_array(dtype, size):
+    a = SingleDimArray(size, dtype=dtype)
     for i in range(size):
-        a.storage[i] = float(i % 10)
+        dtype.setitem(a.storage, i, dtype.box(float(i % 10)))
     return a
 
 class TrivialSpace(object):
+    def __init__(self):
+        self.fromcache = InternalSpaceCache(self).getorbuild
+
     def wrap(self, x):
         return x
 
     def issequence_w(self, w_obj):
-        # Completley wrong in the general case, but good enough for this.
+        # Completely wrong in the general case, but good enough for this.
         return isinstance(w_obj, BaseArray)
 
     def float_w(self, w_obj):
@@ -31,12 +36,13 @@
     space = TrivialSpace()
     stack = []
     i = 0
+    dtype = space.fromcache(W_Float64Dtype)
     for b in bytecode:
         if b == 'a':
-            stack.append(create_array(array_size))
+            stack.append(create_array(dtype, array_size))
             i += 1
         elif b == 'f':
-            stack.append(Scalar(1.2))
+            stack.append(Scalar(dtype, dtype.box(1.2)))
         elif b == '+':
             right = stack.pop()
             stack.append(stack.pop().descr_add(space, right))
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -45,7 +45,7 @@
 class BaseBox(object):
     pass
 
-VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True}))
+VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True}))
 
 def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype):
     class Box(BaseBox):
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -403,7 +403,8 @@
         return self.res_dtype
 
     def _eval(self, i):
-        call_sig = self.signature.components[0]
+        sig = jit.promote(self.signature)
+        call_sig = sig.components[0]
         assert isinstance(call_sig, signature.Call1)
         val = self.values.eval(i).convert_to(self.res_dtype)
         return call_sig.func(self.res_dtype, val)
@@ -431,7 +432,8 @@
     def _eval(self, i):
         lhs = self.left.eval(i).convert_to(self.res_dtype)
         rhs = self.right.eval(i).convert_to(self.res_dtype)
-        call_sig = self.signature.components[0]
+        sig = jit.promote(self.signature)
+        call_sig = sig.components[0]
         assert isinstance(call_sig, signature.Call2)
         return call_sig.func(self.res_dtype, lhs, rhs)
 
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -27,6 +27,8 @@
 class Signature(BaseSignature):
     _known_sigs = r_dict(components_eq, components_hash)
 
+    _immutable_fields_ = ["components[*]"]
+
     def __init__(self, components):
         self.components = components
 
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -1,8 +1,8 @@
+from pypy.interpreter.baseobjspace import InternalSpaceCache
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.module.micronumpy.compile import numpy_compile
 from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
-from pypy.module.micronumpy.interp_numarray import (SingleDimArray, Scalar,
-    Call2, SingleDimSlice, Call1)
+from pypy.module.micronumpy.interp_numarray import SingleDimArray, Scalar
 from pypy.module.micronumpy.interp_ufuncs import negative, add
 from pypy.rlib.nonconst import NonConstant
 from pypy.rlib.objectmodel import specialize
@@ -12,6 +12,9 @@
 class FakeSpace(object):
     w_ValueError = None
 
+    def __init__(self):
+        self.fromcache = InternalSpaceCache(self).getorbuild
+
     def issequence_w(self, w_obj):
         return True
 
@@ -32,7 +35,7 @@
             ar = SingleDimArray(i, dtype=self.float64_dtype)
             v = add(self.space, ar, ar)
             concrete = v.get_concrete()
-            return concrete.dtype.getitem(concrete.storage, 3)
+            return concrete.dtype.getitem(concrete.storage, 3).val
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)
         self.check_loops({'getarrayitem_raw': 2, 'float_add': 1,
@@ -42,8 +45,8 @@
 
     def test_floatadd(self):
         def f(i):
-            ar = SingleDimArray(i)
-            v = Call2(add, ar, Scalar(4.5), Signature())
+            ar = SingleDimArray(i, dtype=self.float64_dtype)
+            v = add(self.space, ar, Scalar(self.float64_dtype, self.float64_dtype.box(4.5)))
             return v.dtype.getitem(v.get_concrete().storage, 3)
 
         result = self.meta_interp(f, [5], listops=True, backendopt=True)


More information about the pypy-commit mailing list