Author: Richard Plangger <r...@pasra.at>
Branch: vecopt
Changeset: r78286:e812d5febce9
Date: 2015-06-24 10:36 +0200
http://bitbucket.org/pypy/pypy/changeset/e812d5febce9/

Log:    added a new resop class for casting operations, added a test to
        ensure they are created correctly

diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -2683,14 +2683,7 @@
         tosize = tosizeloc.value
         if size == tosize:
             return # already the right size
-        if size == 4 and tosize == 2:
-            scratch = X86_64_SCRATCH_REG
-            self.mc.PSHUFLW_xxi(resloc.value, srcloc.value, 0b11111000)
-            self.mc.PEXTRW_rxi(scratch.value, srcloc.value, 4)
-            self.mc.PINSRW_xri(resloc.value, scratch.value, 2)
-            self.mc.PEXTRW_rxi(scratch.value, srcloc.value, 6)
-            self.mc.PINSRW_xri(resloc.value, scratch.value, 3)
-        elif size == 4 and tosize == 8:
+        if size == 4 and tosize == 8:
             scratch = X86_64_SCRATCH_REG.value
             self.mc.PEXTRD_rxi(scratch, srcloc.value, 1)
             self.mc.PINSRQ_xri(resloc.value, scratch, 1)
@@ -2704,7 +2697,13 @@
             self.mc.PEXTRQ_rxi(scratch, srcloc.value, 1)
             self.mc.PINSRD_xri(resloc.value, scratch, 1)
         else:
-            raise NotImplementedError("sign ext missing: " + str(size) + " -> 
" + str(tosize))
+            # note that all other conversions are not implemented
+            # on purpose. it needs many x86 op codes to implement
+            # the missing combinations. even if they are implemented
+            # the speedup might only be modest...
+            # the optimization does not emit such code!
+            msg = "vec int signext (%d->%d)" % (size, tosize)
+            raise NotImplementedError(msg)
 
     def genop_vec_float_expand(self, op, arglocs, resloc):
         srcloc, sizeloc = arglocs
@@ -2716,6 +2715,8 @@
             self.mc.SHUFPS_xxi(resloc.value, srcloc.value, 0)
         elif size == 8:
             self.mc.MOVDDUP(resloc, srcloc)
+        else:
+            raise AssertionError("float of size %d not supported" % (size,))
 
     def genop_vec_int_expand(self, op, arglocs, resloc):
         srcloc, sizeloc = arglocs
@@ -2737,7 +2738,7 @@
             self.mc.PINSRQ_xri(resloc.value, srcloc.value, 0)
             self.mc.PINSRQ_xri(resloc.value, srcloc.value, 1)
         else:
-            raise NotImplementedError("missing size %d for int expand" % 
(size,))
+            raise AssertionError("cannot handle size %d (int expand)" % 
(size,))
 
     def genop_vec_int_pack(self, op, arglocs, resloc):
         resultloc, sourceloc, residxloc, srcidxloc, countloc, sizeloc = arglocs
@@ -2748,7 +2749,9 @@
         residx = residxloc.value
         count = countloc.value
         # for small data type conversion this can be quite costy
-        # j = pack(i,4,4)
+        # NOTE there might be some combinations that can be handled
+        # more efficiently! e.g.
+        # v2 = pack(v0,v1,4,4)
         si = srcidx
         ri = residx
         k = count
diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py 
b/rpython/jit/metainterp/optimizeopt/vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/vectorize.py
@@ -642,15 +642,15 @@
 
     def profitable_pack(self, lnode, rnode, origin_pack):
         lpacknode = origin_pack.left
-        if self.prohibit_packing(lpacknode.getoperation(), 
lnode.getoperation()):
+        if self.prohibit_packing(origin_pack, lpacknode.getoperation(), 
lnode.getoperation()):
             return False
         rpacknode = origin_pack.right
-        if self.prohibit_packing(rpacknode.getoperation(), 
rnode.getoperation()):
+        if self.prohibit_packing(origin_pack, rpacknode.getoperation(), 
rnode.getoperation()):
             return False
 
         return True
 
-    def prohibit_packing(self, packed, inquestion):
+    def prohibit_packing(self, pack, packed, inquestion):
         """ Blocks the packing of some operations """
         if inquestion.vector == -1:
             return True
@@ -658,10 +658,15 @@
             if packed.getarg(1) == inquestion.result:
                 return True
         if inquestion.casts_box():
-            #input_type = packed.output_type
-            #if not input_type:
-            #    return True
-            pass
+            # prohibit the packing of signext calls that
+            # cast to int16/int8.
+            input_type = pack.output_type
+            if input_type:
+                py.test.set_trace()
+                insize = input_type.getsize()
+                outtype,outsize = inquestion.cast_to()
+                if outsize < 4 and insize != outsize:
+                    return True
         return False
 
     def combine(self, i, j):
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -1,6 +1,5 @@
 from rpython.rlib.objectmodel import we_are_translated
 
-
 def ResOperation(opnum, args, result, descr=None):
     cls = opclasses[opnum]
     op = cls(result)
@@ -26,6 +25,7 @@
     boolreflex = -1
     boolinverse = -1
     vector = -1
+    casts = ('\x00', -1, '\x00', -1)
 
     _attrs_ = ('result',)
 
@@ -190,12 +190,13 @@
         return self._cls_has_bool_result
 
     def casts_box(self):
-        opnum = self.getopnum()
-        return opnum == rop.INT_SIGNEXT or \
-               rop.CAST_FLOAT_TO_INT <= opnum <= rop.CAST_SINGLEFLOAT_TO_FLOAT 
or \
-               rop._VEC_CAST_FIRST <= opnum <= rop._VEC_CAST_LAST or \
-               rop.CAST_PTR_TO_INT == opnum or \
-               rop.CAST_INT_TO_PTR == opnum
+        return False
+
+    def cast_to(self):
+        return ('\x00',-1)
+
+    def cast_from(self):
+        return ('\x00',-1)
 
 # ===================
 # Top of the hierachy
@@ -204,6 +205,23 @@
 class PlainResOp(AbstractResOp):
     pass
 
+class CastResOp(AbstractResOp):
+    def casts_box(self):
+        return True
+
+    def cast_to(self):
+        _, _, to_type, size = self.casts
+        if self.casts[3] == 0:
+            if self.getopnum() == rop.INT_SIGNEXT:
+                arg = self.getarg(1)
+                assert isinstance(arg, ConstInt)
+                return (to_type,arg.value)
+            else:
+                raise NotImplementedError
+        return (to_type,size)
+
+    def cast_from(self):
+        return ('\x00',-1)
 
 class ResOpWithDescr(AbstractResOp):
 
@@ -629,6 +647,20 @@
     '_LAST',     # for the backend to add more internal operations
 ]
 
+FLOAT = 'f'
+INT = 'i'
+_cast_ops = {
+    'INT_SIGNEXT': (INT, 0, INT, 0),
+    'CAST_FLOAT_TO_INT': (FLOAT, 8, INT, 4),
+    'CAST_INT_TO_FLOAT': (INT, 4, FLOAT, 8),
+    'CAST_FLOAT_TO_SINGLEFLOAT': (FLOAT, 8, FLOAT, 4),
+    'CAST_SINGLEFLOAT_TO_FLOAT': (FLOAT, 4, FLOAT, 8),
+    'CAST_PTR_TO_INT': (INT, 0, INT, 4),
+    'CAST_INT_TO_PTR': (INT, 4, INT, 0),
+}
+del FLOAT
+del INT
+
 # ____________________________________________________________
 
 class rop(object):
@@ -639,7 +671,6 @@
 oparity = []     # mapping numbers to the arity of the operation or -1
 opwithdescr = [] # mapping numbers to a flag "takes a descr"
 
-
 def setup(debug_print=False):
     for i, name in enumerate(_oplist):
         if debug_print:
@@ -691,6 +722,8 @@
     if is_guard:
         assert withdescr
         baseclass = GuardResOp
+    elif name in _cast_ops:
+        baseclass = CastResOp
     elif withdescr:
         baseclass = ResOpWithDescr
     else:
@@ -780,21 +813,26 @@
     rop.CAST_FLOAT_TO_INT: rop.VEC_CAST_FLOAT_TO_INT,
 }
 
+
 def setup2():
     for cls in opclasses:
         if cls is None:
             continue
         opnum = cls.opnum
+        name = opname[opnum]
         if opnum in _opboolreflex:
             cls.boolreflex = _opboolreflex[opnum]
         if opnum in _opboolinverse:
             cls.boolinverse = _opboolinverse[opnum]
         if opnum in _opvector:
             cls.vector = _opvector[opnum]
+        if name in _cast_ops:
+            cls.casts = _cast_ops[name]
 setup2()
 del _opboolinverse
 del _opboolreflex
 del _opvector
+del _cast_ops
 
 def get_deep_immutable_oplist(operations):
     """
diff --git a/rpython/jit/metainterp/test/test_resoperation.py 
b/rpython/jit/metainterp/test/test_resoperation.py
--- a/rpython/jit/metainterp/test/test_resoperation.py
+++ b/rpython/jit/metainterp/test/test_resoperation.py
@@ -83,3 +83,12 @@
     py.test.raises(TypeError, "newops[0] = 'foobar'")
     py.test.raises(AssertionError, "newops[0].setarg(0, 'd')")
     py.test.raises(AssertionError, "newops[0].setdescr('foobar')")
+
+def test_cast_ops():
+    op = rop.ResOperation(rop.rop.INT_SIGNEXT, ['a', 1], 'c')
+    assert op.casts_box()
+    assert isinstance(op, rop.CastResOp)
+    assert op.cast_to == ('i',1)
+    op = rop.ResOperation(rop.rop.CAST_FLOAT_TO_INT, ['a'], 'c')
+    assert op.casts_box()
+    assert isinstance(op, rop.CastResOp)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to