[pypy-commit] pypy default: Support casts between floats and (u)longlongs written as a force_cast.

arigo noreply at buildbot.pypy.org
Mon Oct 24 17:58:24 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r48380:054d434f5e82
Date: 2011-10-24 17:58 +0200
http://bitbucket.org/pypy/pypy/changeset/054d434f5e82/

Log:	Support casts between floats and (u)longlongs written as a
	force_cast.

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
@@ -849,14 +849,12 @@
             return self._float_to_float_cast(v_arg, v_result)
         elif not float_arg and float_res:
             # some int -> some float
-            size1, unsigned1 = rffi.size_and_sign(v_arg.concretetype)
-            assert size1 <= rffi.sizeof(lltype.Signed), (
-                "not implemented: cast_longlong_to_float")
-            from_uint = (unsigned1 and size1 == rffi.sizeof(lltype.Signed))
-            #
             ops = []
             v2 = varoftype(lltype.Float)
-            if not from_uint:
+            sizesign = rffi.size_and_sign(v_arg.concretetype)
+            if sizesign <= rffi.size_and_sign(lltype.Signed):
+                # cast from a type that fits in an int: either the size is
+                # smaller, or it is equal and it is not unsigned
                 v1 = varoftype(lltype.Signed)
                 oplist = self.rewrite_operation(
                     SpaceOperation('force_cast', [v_arg], v1)
@@ -870,8 +868,16 @@
                 )
                 ops.append(op)
             else:
+                if sizesign == rffi.size_and_sign(lltype.Unsigned):
+                    opname = 'cast_uint_to_float'
+                elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
+                    opname = 'cast_longlong_to_float'
+                elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
+                    opname = 'cast_ulonglong_to_float'
+                else:
+                    raise AssertionError('cast_x_to_float: %r' % (sizesign,))
                 ops1 = self.rewrite_operation(
-                    SpaceOperation('cast_uint_to_float', [v_arg], v2)
+                    SpaceOperation(opname, [v_arg], v2)
                 )
                 if not isinstance(ops1, list): ops1 = [ops1]
                 ops.extend(ops1)
@@ -885,11 +891,6 @@
             return ops
         elif float_arg and not float_res:
             # some float -> some int
-            size2, unsigned2 = rffi.size_and_sign(v_result.concretetype)
-            assert size2 <= rffi.sizeof(lltype.Signed), (
-                "not implemented: cast_float_to_longlong")
-            to_uint = (unsigned2 and size2 == rffi.sizeof(lltype.Signed))
-            #
             ops = []
             v1 = varoftype(lltype.Float)
             op1 = self.rewrite_operation(
@@ -899,7 +900,10 @@
                 ops.append(op1)
             else:
                 v1 = v_arg
-            if not to_uint:
+            sizesign = rffi.size_and_sign(v_result.concretetype)
+            if sizesign <= rffi.size_and_sign(lltype.Signed):
+                # cast to a type that fits in an int: either the size is
+                # smaller, or it is equal and it is not unsigned
                 v2 = varoftype(lltype.Signed)
                 op = self.rewrite_operation(
                     SpaceOperation('cast_float_to_int', [v1], v2)
@@ -913,8 +917,16 @@
                 else:
                     op.result = v_result
             else:
+                if sizesign == rffi.size_and_sign(lltype.Unsigned):
+                    opname = 'cast_float_to_uint'
+                elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
+                    opname = 'cast_float_to_longlong'
+                elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
+                    opname = 'cast_float_to_ulonglong'
+                else:
+                    raise AssertionError('cast_float_to_x: %r' % (sizesign,))
                 ops1 = self.rewrite_operation(
-                    SpaceOperation('cast_float_to_uint', [v1], v_result)
+                    SpaceOperation(opname, [v1], v_result)
                 )
                 if not isinstance(ops1, list): ops1 = [ops1]
                 ops.extend(ops1)
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -230,9 +230,13 @@
         return x
 
 def _ll_1_cast_uint_to_float(x):
+    # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
+    # (which is a residual call right now in the x86 backend)
     return llop.cast_uint_to_float(lltype.Float, x)
 
 def _ll_1_cast_float_to_uint(x):
+    # XXX on 32-bit platforms, this should be done using cast_float_to_longlong
+    # (which is a residual call right now in the x86 backend)
     return llop.cast_float_to_uint(lltype.Unsigned, x)
 
 
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -8,7 +8,7 @@
 from pypy.rpython.lltypesystem import lltype, rclass, rstr
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
 from pypy.translator.unsimplify import varoftype
-from pypy.rlib.rarithmetic import ovfcheck, r_uint
+from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
 from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
 from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import jit
@@ -930,6 +930,38 @@
             float_return %f0
         """, transform=True)
 
+        if not longlong.is_64_bit:
+            def f(dbl):
+                return rffi.cast(lltype.SignedLongLong, dbl)
+            self.encoding_test(f, [12.3], """
+                residual_call_irf_f $<* fn llong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(dbl):
+                return rffi.cast(lltype.UnsignedLongLong, dbl)
+            self.encoding_test(f, [12.3], """
+                residual_call_irf_f $<* fn ullong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(x):
+                ll = r_longlong(x)
+                return rffi.cast(lltype.Float, ll)
+            self.encoding_test(f, [12], """
+                residual_call_irf_f $<* fn llong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
+                residual_call_irf_f $<* fn llong_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
+
+            def f(x):
+                ll = r_ulonglong(x)
+                return rffi.cast(lltype.Float, ll)
+            self.encoding_test(f, [12], """
+                residual_call_irf_f $<* fn ullong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
+                residual_call_irf_f $<* fn ullong_u_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
+                float_return %f1
+            """, transform=True)
 
     def test_direct_ptradd(self):
         from pypy.rpython.lltypesystem import rffi
diff --git a/pypy/jit/metainterp/test/test_float.py b/pypy/jit/metainterp/test/test_float.py
--- a/pypy/jit/metainterp/test/test_float.py
+++ b/pypy/jit/metainterp/test/test_float.py
@@ -74,11 +74,6 @@
         res = self.interp_operations(g, [-12345])
         assert type(res) is float and res == float(long(r_uint(-12345)))
 
-    #def test_cast_longlong_to_float(self):
-    #def test_cast_ulonglong_to_float(self):
-    #def test_cast_float_to_longlong(self):
-    #def test_cast_float_to_ulonglong(self):
-
 
 class TestOOtype(FloatTests, OOJitMixin):
     pass


More information about the pypy-commit mailing list