Author: Richard Plangger <planri...@gmail.com>
Branch: vecopt-merge
Changeset: r79622:289407699445
Date: 2015-09-14 13:31 +0200
http://bitbucket.org/pypy/pypy/changeset/289407699445/

Log:    slowly approaching the first passing scheduling test, code is
        smaller and more compact

diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py 
b/rpython/jit/metainterp/optimizeopt/dependency.py
--- a/rpython/jit/metainterp/optimizeopt/dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/dependency.py
@@ -355,7 +355,7 @@
     def __repr__(self):
         pack = ''
         if self.pack:
-            pack = "p: %d" % self.pack.opcount()
+            pack = "p: %d" % self.pack.numops()
         return "Node(%s,%s i: %d)" % (self.op.getopname(), pack, self.opidx)
 
     def __ne__(self, other):
diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py 
b/rpython/jit/metainterp/optimizeopt/schedule.py
--- a/rpython/jit/metainterp/optimizeopt/schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/schedule.py
@@ -18,7 +18,7 @@
 
     def post_schedule(self):
         loop = self.graph.loop
-        self.renamer.rename(loop.label.getoperation())
+        self.renamer.rename(loop.jump)
 
     def profitable(self):
         return self.costmodel.profitable()
@@ -66,7 +66,7 @@
             Keeps worklist sorted (see priority) """
         op = node.getoperation()
         state.renamer.rename(op)
-        state.unpack_from_vector(op, self)
+        state.unpack_from_vector(op)
         node.position = len(state.oplist)
         worklist = state.worklist
         for dep in node.provides()[:]: # COPY
@@ -97,6 +97,7 @@
         """ Emit all the operations into the oplist parameter.
             Initiates the scheduling. """
         assert isinstance(state, SchedulerState)
+        import pdb; pdb.set_trace()
         while state.has_more():
             node = self.next(state)
             if node:
@@ -177,40 +178,43 @@
                 rop.UINT_LT, rop.UINT_LE,
                 rop.UINT_GT, rop.UINT_GE)
 
-class Type(object):
-    """ The type of one operation. Saves type, size and sign. """
-    @staticmethod
-    def of(op):
-        descr = op.getdescr()
-        if descr:
-            type = INT
-            if descr.is_array_of_floats() or descr.concrete_type == FLOAT:
-                type = FLOAT
-            size = descr.get_item_size_in_bytes()
-            sign = descr.is_item_signed()
-            return Type(type, size, sign)
-        else:
-            size = 8
-            sign = True
-            if op.type == 'f' or op.getopnum() in UNSIGNED_OPS:
-                sign = False
-            return Type(op.type, size, sign)
-
-    def __init__(self, type, size, signed):
-        assert type in (FLOAT, INT)
-        self.type = type
-        self.size = size
-        self.signed = signed
-
-    def clone(self):
-        return Type(self.type, self.size, self.signed)
-
-    def __repr__(self):
-        sign = '-'
-        if not self.signed:
-            sign = '+'
-        return 'Type(%s%s, %d)' % (sign, self.type, self.size)
-
+#class Type(object):
+#    """ The type of one operation. Saves type, size and sign. """
+#    @staticmethod
+#    def of(op):
+#        descr = op.getdescr()
+#        if descr:
+#            type = INT
+#            if descr.is_array_of_floats() or descr.concrete_type == FLOAT:
+#                type = FLOAT
+#            size = descr.get_item_size_in_bytes()
+#            sign = descr.is_item_signed()
+#            return Type(type, size, sign)
+#        else:
+#            size = 8
+#            sign = True
+#            if op.type == 'f' or op.getopnum() in UNSIGNED_OPS:
+#                sign = False
+#            return Type(op.type, size, sign)
+#
+#    def __init__(self, type, size, signed):
+#        assert type in (FLOAT, INT)
+#        self.type = type
+#        self.size = size
+#        self.signed = signed
+#
+#    def bytecount(self):
+#        return self.size
+#
+#    def clone(self):
+#        return Type(self.type, self.size, self.signed)
+#
+#    def __repr__(self):
+#        sign = '-'
+#        if not self.signed:
+#            sign = '+'
+#        return 'Type(%s%s, %d)' % (sign, self.type, self.size)
+#
     #UNKNOWN_TYPE = '-'
 
     #@staticmethod
@@ -268,10 +272,6 @@
     #def getcount(self):
     #    return self.count
 
-    #def pack_byte_size(self, pack):
-    #    if len(pack.operations) == 0:
-    #        return 0
-    #    return self.getsize() * pack.opcount()
 
 class TypeRestrict(object):
     ANY_TYPE = -1
@@ -301,6 +301,20 @@
         self.type = type
         self.count = count
 
+
+    def bytecount(self):
+        return self.count * self.type.bytecount()
+
+class DataTyper(object):
+
+    def infer_type(self, op):
+        # default action, pass through: find the first arg
+        # the output is the same as the first argument!
+        if op.returns_void() or op.argcount() == 0:
+            return
+        arg0 = op.getarg(0)
+        op.setdatatype(arg0.datatype, arg0.bytesize, arg0.signed)
+
 class PassFirstArg(TypeOutput):
     def __init__(self):
         pass
@@ -316,17 +330,14 @@
         op = pack.leftmost()
         args = op.getarglist()
         self.prepare_arguments(state, op.getarglist())
-        #
-        vop = VecOperation(op.vector, args, otype.   op.getdescr())
-        #result = self.transform_result(op)
+        vop = VecOperation(op.vector, args, op, pack.numops(), op.getdescr())
         #
         if op.is_guard():
             assert isinstance(op, GuardResOp)
             assert isinstance(vop, GuardResOp)
             vop.setfailargs(op.getfailargs())
             vop.rd_snapshot = op.rd_snapshot
-        self.vecops.append(vop)
-        self.costmodel.record_pack_savings(self.pack, self.pack.opcount())
+        state.costmodel.record_pack_savings(pack, pack.numops())
         #
         if pack.is_accumulating():
             box = oplist[position].result
@@ -335,8 +346,10 @@
                 op = node.getoperation()
                 assert not op.returns_void()
                 scheduler.renamer.start_renaming(op, box)
+        #
+        state.oplist.append(vop)
 
-    def transform_arguments(self, state, args):
+    def prepare_arguments(self, state, args):
         self.before_argument_transform(args)
         # Transforming one argument to a vector box argument
         # The following cases can occur:
@@ -732,12 +745,12 @@
     def __init__(self):
         OpToVectorOp.__init__(self, (), TypeRestrict())
 
-    def before_argument_transform(self, args):
-        count = min(self.output_type.getcount(), len(self.getoperations()))
-        args.append(ConstInt(count))
+    # OLD def before_argument_transform(self, args):
+        #count = min(self.output_type.getcount(), len(self.getoperations()))
+        #args.append(ConstInt(count))
 
     def get_output_type_given(self, input_type, op):
-        return Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size)
+        return xxx#Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size)
 
     def get_input_type_given(self, output_type, op):
         return None
@@ -760,7 +773,7 @@
         return None
 
     def get_input_type_given(self, output_type, op):
-        return Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size)
+        return xxx#Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size)
 
 class PassThroughOp(OpToVectorOp):
     """ This pass through is only applicable if the target
@@ -778,7 +791,7 @@
 
 
 class trans(object):
-    PASS = PassFirstArg()
+    DT_PASS = DataTyper()
 
     TR_ANY_FLOAT = TypeRestrict(FLOAT)
     TR_ANY_INTEGER = TypeRestrict(INT)
@@ -787,9 +800,9 @@
     TR_LONG = TypeRestrict(INT, 8, 2)
     TR_INT_2 = TypeRestrict(INT, 4, 2)
 
-    INT = OpToVectorOp((TR_ANY_INTEGER, TR_ANY_INTEGER), PASS)
-    FLOAT = OpToVectorOp((TR_ANY_FLOAT, TR_ANY_FLOAT), PASS)
-    FLOAT_UNARY = OpToVectorOp((TR_ANY_FLOAT,), PASS)
+    INT = OpToVectorOp((TR_ANY_INTEGER, TR_ANY_INTEGER), DT_PASS)
+    FLOAT = OpToVectorOp((TR_ANY_FLOAT, TR_ANY_FLOAT), DT_PASS)
+    FLOAT_UNARY = OpToVectorOp((TR_ANY_FLOAT,), DT_PASS)
     LOAD = LoadToVectorLoad()
     STORE = StoreToVectorStore()
     GUARD = PassThroughOp((TR_ANY_INTEGER,))
@@ -839,6 +852,11 @@
         rop.VEC_INT_IS_TRUE: OpToVectorOp((TR_ANY_INTEGER,TR_ANY_INTEGER), 
None), # TR_ANY_INTEGER),
     }
 
+    # TODO?
+    UNSIGNED_OPS = (rop.UINT_FLOORDIV, rop.UINT_RSHIFT,
+                    rop.UINT_LT, rop.UINT_LE,
+                    rop.UINT_GT, rop.UINT_GE)
+
 def determine_input_output_types(pack, node, forward):
     """ This function is two fold. If moving forward, it
         gets an input type from the packs output type and returns
@@ -888,9 +906,11 @@
 
     def post_schedule(self):
         loop = self.graph.loop
-        self.sched_data.unpack_from_vector(loop.jump.getoperation(), self)
+        self.unpack_from_vector(loop.jump)
         SchedulerState.post_schedule(self)
 
+        self.graph.loop.operations = self.oplist
+
         # add accumulation info to the descriptor
         #for version in self.loop.versions:
         #    # this needs to be done for renamed (accum arguments)
@@ -928,11 +948,11 @@
             to emit the actual operation into the oplist of the scheduler.
         """
         if node.pack:
+            assert node.pack.numops() > 1
             for node in node.pack.operations:
                 scheduler.mark_emitted(node, self)
-                assert node.pack.opcount() > 1
-                op2vecop = determine_trans(node.pack.leftmost())
-                op2vecop.as_vector_operation(self, node.pack)
+            op2vecop = determine_trans(node.pack.leftmost())
+            op2vecop.as_vector_operation(self, node.pack)
             return True
         return False
 
@@ -950,7 +970,7 @@
                         return True
         return False
 
-    def unpack_from_vector(self, op, scheduler):
+    def unpack_from_vector(self, op):
         """ If a box is needed that is currently stored within a vector
             box, this utility creates a unpacking instruction.
         """
@@ -959,7 +979,7 @@
         # unpack for an immediate use
         for i, arg in enumerate(op.getarglist()):
             if not arg.is_constant():
-                argument = self._unpack_from_vector(i, arg, scheduler)
+                argument = self._unpack_from_vector(i, arg)
                 if arg is not argument:
                     op.setarg(i, argument)
         if not op.returns_void():
@@ -969,11 +989,11 @@
             fail_args = op.getfailargs()
             for i, arg in enumerate(fail_args):
                 if arg and not arg.is_constant():
-                    argument = self._unpack_from_vector(i, arg, scheduler)
+                    argument = self._unpack_from_vector(i, arg)
                     if arg is not argument:
                         fail_args[i] = argument
 
-    def _unpack_from_vector(self, i, arg, scheduler):
+    def _unpack_from_vector(self, i, arg):
         if arg in self.seen or arg.type == 'V':
             return arg
         (j, vbox) = self.getvector_of_box(arg)
@@ -982,14 +1002,14 @@
                 return arg
             arg_cloned = arg.clonebox()
             self.seen[arg_cloned] = None
-            scheduler.renamer.start_renaming(arg, arg_cloned)
+            self.renamer.start_renaming(arg, arg_cloned)
             self.setvector_of_box(arg_cloned, j, vbox)
             cj = ConstInt(j)
             ci = ConstInt(1)
             opnum = getunpackopnum(vbox.gettype())
             unpack_op = ResOperation(opnum, [vbox, cj, ci], arg_cloned)
             self.costmodel.record_vector_unpack(vbox, j, 1)
-            scheduler.oplist.append(unpack_op)
+            self.oplist.append(unpack_op)
             return arg_cloned
         return arg
 
@@ -1042,15 +1062,19 @@
     """
     FULL = 0
 
-    def __init__(self, ops, input_type, output_type):
+    def __init__(self, ops):
         self.operations = ops
         self.accum = None
-        self.input_type = input_type
-        self.output_type = output_type
-        assert self.input_type is not None or self.output_type is not None
         self.update_pack_of_nodes()
+        # initializes the type
+        # TODO
+        #input_type, output_type = \
+        #    determine_input_output_types(origin_pack, lnode, forward)
+        #self.input_type = input_type
+        #self.output_type = output_type
+        #assert self.input_type is not None or self.output_type is not None
 
-    def opcount(self):
+    def numops(self):
         return len(self.operations)
 
     def leftmost(self):
@@ -1078,22 +1102,25 @@
         return self._byte_size(self.output_type)
 
     def pack_load(self, vec_reg_size):
-        """ Returns the load of the pack. A value
-            smaller than 0 indicates that it is empty
-            or nearly empty, zero indicates that all slots
-            are used and > 0 indicates that too many operations
-            are in this pack instance.
+        """ Returns the load of the pack a vector register would hold
+            just after executing the operation.
+            returns: < 0 - empty, nearly empty
+                     = 0 - full
+                     > 0 - overloaded
         """
-        if len(self.operations) == 0:
+        left = self.leftmost()
+        if left.returns_void():
+            return 0
+        if self.numops() == 0:
             return -1
         size = maximum_byte_size(self, vec_reg_size)
-        if self.input_type is None:
+        return left.bytesize * self.numops() - size
+        #if self.input_type is None:
             # e.g. load operations
-            return self.output_type.pack_byte_size(self) - size
+        #    return self.output_type.bytecount(self) - size
         # default only consider the input type
         # e.g. store operations, int_add, ...
-        return self.input_type.pack_byte_size(self) - size
-
+        #return self.input_type.bytecount(self) - size
 
     def is_full(self, vec_reg_size):
         """ If one input element times the opcount is equal
@@ -1131,12 +1158,14 @@
             newpack = pack.clone(newoplist)
             load = newpack.pack_load(vec_reg_size)
             if load >= Pack.FULL:
+                pack.update_pack_of_nodes()
                 pack = newpack
                 packlist.append(newpack)
             else:
                 newpack.clear()
                 newpack.operations = []
                 break
+        pack.update_pack_of_nodes()
 
     def slice_operations(self, vec_reg_size):
         count = opcount_filling_vector_register(self, vec_reg_size)
@@ -1163,31 +1192,26 @@
 
     def __repr__(self):
         if len(self.operations) == 0:
-            return "Pack(-, [])"
-        opname = self.operations[0].getoperation().getopname()
-        return "Pack(%s,%r)" % (opname, self.operations)
+            return "Pack(empty)"
+        return "Pack(%dx %s)" % (self.numops(), self.operations[0])
 
     def is_accumulating(self):
         return self.accum is not None
 
     def clone(self, oplist):
-        cloned = Pack(oplist, self.input_type, self.output_type)
+        cloned = Pack(oplist)
         cloned.accum = self.accum
         return cloned
 
 
 class Pair(Pack):
     """ A special Pack object with only two statements. """
-    def __init__(self, left, right, input_type, output_type):
+    def __init__(self, left, right):
         assert isinstance(left, Node)
         assert isinstance(right, Node)
         self.left = left
         self.right = right
-        if input_type:
-            input_type = input_type.clone()
-        if output_type:
-            output_type = output_type.clone()
-        Pack.__init__(self, [left, right], input_type, output_type)
+        Pack.__init__(self, [left, right])
 
     def __eq__(self, other):
         if isinstance(other, Pair):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py 
b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
@@ -7,7 +7,7 @@
         Pack, Pair, NotAProfitableLoop, VectorizingOptimizer, X86_CostModel,
         PackSet)
 from rpython.jit.metainterp.optimizeopt.dependency import Node, DependencyGraph
-from rpython.jit.metainterp.optimizeopt.schedule import Type, Scheduler
+from rpython.jit.metainterp.optimizeopt.schedule import Scheduler
 from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
 from rpython.jit.metainterp.optimizeopt.test.test_dependency import 
(DependencyBaseTest,
         FakeDependencyGraph)
@@ -17,13 +17,13 @@
 from rpython.jit.tool.oparser import parse as opparse
 from rpython.jit.tool.oparser_model import get_model
 
-F64 = Type('f',8,False)
-F32 = Type('f',4,False)
-F32_2 =  Type('f',4,False)
-I64 = Type('i',8,True)
-I32 = Type('i',4,True)
-I32_2 =  Type('i',4,True)
-I16 = Type('i',2,True)
+F64 = None #('f',8,False)
+F32 = None #('f',4,False)
+F32_2 =  None #('f',4,False)
+I64 = None #('i',8,True)
+I32 = None #('i',4,True)
+I32_2 =  None #('i',4,True)
+I16 = None #('i',2,True)
 
 class FakePackSet(PackSet):
     def __init__(self, packs):
@@ -68,7 +68,7 @@
         return loop
 
     def pack(self, loop, l, r, input_type, output_type):
-        return Pack(loop.graph.nodes[1+l:1+r], input_type, output_type)
+        return Pack(loop.graph.nodes[1+l:1+r])
 
     def schedule(self, loop, packs, vec_reg_size=16,
                  prepend_invariant=False, overwrite_funcs=None):
@@ -79,7 +79,7 @@
             for i in range(len(pack.operations)-1):
                 o1 = pack.operations[i]
                 o2 = pack.operations[i+1]
-                pair = Pair(o1,o2,pack.input_type,pack.output_type)
+                pair = Pair(o1,o2)
                 pairs.append(pair)
         packset = FakePackSet(pairs)
         state = VecScheduleState(loop.graph, packset, self.cpu, cm)
@@ -94,6 +94,9 @@
             state.prepend_invariant_operations = lambda list, _: list
         opt.combine_packset()
         opt.schedule(state)
+        # works for now. might be the wrong class?
+        # wrap label + operations + jump it in tree loop otherwise
+        return state.graph.loop
 
 class Test(SchedulerBaseTest, LLtypeMixin):
 
@@ -124,7 +127,7 @@
         pack1 = self.pack(loop1, 0, 6, None, F32)
         loop2 = self.schedule(loop1, [pack1])
         loop3 = self.parse_trace("""
-        v10[i32|4] = vec_raw_load_i(p0, i0, 4, descr=float)
+        v10[4xi32] = vec_raw_load_i(p0, i0, descr=float)
         f10 = raw_load_f(p0, i4, descr=float)
         f11 = raw_load_f(p0, i5, descr=float)
         """, False)
@@ -144,7 +147,7 @@
         pack3 = self.pack(loop1, 4, 6, I32_2, F32_2)
         loop2 = self.schedule(loop1, [pack1, pack2, pack3])
         loop3 = self.parse_trace("""
-        v10[i64|2] = vec_raw_load_i(p0, i0, 2, descr=long)
+        v10[i64|2] = vec_raw_load_i(p0, i0, descr=long)
         v20[i32|2] = vec_int_signext(v10[i64|2], 4)
         v30[f64|2] = vec_cast_int_to_float(v20[i32|2])
         """, False)
@@ -268,7 +271,7 @@
         """)
         pack1 = self.pack(loop1, 0, 8, None, F64)
         pack2 = self.pack(loop1, 8, 16, F64, I32_2)
-        I16_2 = Type('i',2,True)
+        I16_2 = None #Type('i',2,True)
         pack3 = self.pack(loop1, 16, 24, I32_2, I16_2)
         pack4 = self.pack(loop1, 24, 32, I16, None)
         def void(b,c):
@@ -278,10 +281,10 @@
                                   '_prevent_signext': void
                               })
         loop3 = self.parse_trace("""
-        v10[f64|2] = vec_raw_load_f(p0, i1, 2, descr=double)
-        v11[f64|2] = vec_raw_load_f(p0, i3, 2, descr=double)
-        v12[f64|2] = vec_raw_load_f(p0, i5, 2, descr=double)
-        v13[f64|2] = vec_raw_load_f(p0, i7, 2, descr=double)
+        v10[f64|2] = vec_raw_load_f(p0, i1, descr=double)
+        v11[f64|2] = vec_raw_load_f(p0, i3, descr=double)
+        v12[f64|2] = vec_raw_load_f(p0, i5, descr=double)
+        v13[f64|2] = vec_raw_load_f(p0, i7, descr=double)
         v14[i32|2] = vec_cast_float_to_int(v10[f64|2])
         v15[i32|2] = vec_cast_float_to_int(v11[f64|2])
         v16[i32|2] = vec_cast_float_to_int(v12[f64|2])
@@ -319,8 +322,8 @@
         pack3 = self.pack(loop1, 8, 12, I32, None)
         loop2 = self.schedule(loop1, [pack1,pack2,pack3])
         loop3 = self.parse_trace("""
-        v44[f64|2] = vec_raw_load_f(p0, i1, 2, descr=double) 
-        v45[f64|2] = vec_raw_load_f(p0, i3, 2, descr=double) 
+        v44[f64|2] = vec_raw_load_f(p0, i1, descr=double) 
+        v45[f64|2] = vec_raw_load_f(p0, i3, descr=double) 
         v46[i32|2] = vec_cast_float_to_singlefloat(v44[f64|2]) 
         v47[i32|2] = vec_cast_float_to_singlefloat(v45[f64|2]) 
         v41[i32|4] = vec_int_pack(v46[i32|2], v47[i32|2], 2, 2) 
@@ -345,7 +348,7 @@
         loop2 = self.schedule(loop1, [pack1,pack2,pack3], 
prepend_invariant=True)
         loop3 = self.parse_trace("""
         v9[i64|2] = vec_int_expand(255,2)
-        v10[i64|2] = vec_raw_load_i(p0, i1, 2, descr=long)
+        v10[i64|2] = vec_raw_load_i(p0, i1, descr=long)
         v11[i64|2] = vec_int_and(v10[i64|2], v9[i64|2])
         guard_true(v11[i64|2]) []
         """, False)
@@ -365,7 +368,7 @@
         pack2 = self.pack(loop1, 4, 6, I32_2, None)
         loop2 = self.schedule(loop1, [pack1,pack2], prepend_invariant=True)
         loop3 = self.parse_trace("""
-        v1[i32|4] = vec_raw_load_i(p0, i1, 4, descr=float)
+        v1[i32|4] = vec_raw_load_i(p0, i1, descr=float)
         i10 = vec_int_unpack(v1[i32|4], 0, 1)
         raw_store(p0, i3, i10, descr=float)
         i11 = vec_int_unpack(v1[i32|4], 1, 1)
diff --git a/rpython/jit/metainterp/optimizeopt/vector.py 
b/rpython/jit/metainterp/optimizeopt/vector.py
--- a/rpython/jit/metainterp/optimizeopt/vector.py
+++ b/rpython/jit/metainterp/optimizeopt/vector.py
@@ -22,7 +22,7 @@
 from rpython.jit.metainterp.optimizeopt.version import LoopVersionInfo
 from rpython.jit.metainterp.optimizeopt.schedule import (VecScheduleState,
         Scheduler, Pack, Pair, AccumPair, vectorbox_outof_box, getpackopnum,
-        getunpackopnum, Type, determine_input_output_types)
+        getunpackopnum)
 from rpython.jit.metainterp.optimizeopt.guard import GuardStrengthenOpt
 from rpython.jit.metainterp.resoperation import (rop, ResOperation, 
GuardResOp, Accum)
 from rpython.rlib import listsort
@@ -453,7 +453,7 @@
         state.prepare()
         scheduler = Scheduler()
         scheduler.walk_and_emit(state)
-        if state.profitable():
+        if not state.profitable():
             return
         state.post_schedule()
 
@@ -674,15 +674,11 @@
                 if origin_pack is None:
                     op = lnode.getoperation()
                     if op.is_primitive_load():
-                        # load outputs value, no input
-                        return Pair(lnode, rnode, None, Type.of(op))
+                        return Pair(lnode, rnode)
                     else:
-                        # store only has an input
-                        return Pair(lnode, rnode, Type.of(op), None)
+                        return Pair(lnode, rnode)
                 if self.profitable_pack(lnode, rnode, origin_pack, forward):
-                    input_type, output_type = \
-                        determine_input_output_types(origin_pack, lnode, 
forward)
-                    return Pair(lnode, rnode, input_type, output_type)
+                    return Pair(lnode, rnode)
             else:
                 if self.contains_pair(lnode, rnode):
                     return None
@@ -734,17 +730,9 @@
         operations = pack_i.operations
         for op in pack_j.operations[1:]:
             operations.append(op)
-        input_type = pack_i.input_type
-        output_type = pack_i.output_type
-        if input_type:
-            input_type.combine(pack_j.input_type)
-        if output_type:
-            output_type.combine(pack_j.output_type)
-        pack = Pack(operations, input_type, output_type)
+        pack = Pack(operations)
         self.packs[i] = pack
-        # preserve the accum variable (if present) of the
-        # left most pack, that is the pack with the earliest
-        # operation at index 0 in the trace
+        # preserve the accum variable (if present)
         pack.accum = pack_i.accum
         pack_i.accum = pack_j.accum = None
 
@@ -851,6 +839,5 @@
                 pack.clear()
                 self.packs[i] = None
                 continue
-            pack.update_pack_of_nodes()
         self.packs = [pack for pack in self.packs + newpacks if pack]
 
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
@@ -80,21 +80,70 @@
         elif op.is_guard():
             assert not descr.final_descr
         op.setdescr(descr)
+    op.inittype()
     return op
 
-def VecOperation(opnum, args, type, count, descr=None):
+def VecOperation(opnum, args, baseop, count, descr=None):
+    return VecOperationNew(opnum, args, baseop.datatype, baseop.bytesize, 
baseop.signed, count, descr)
+
+def VecOperationNew(opnum, args, datateyp, bytesize, signed, count, 
descr=None):
     op = ResOperation(opnum, args, descr)
-    op.item_type = type
-    op.item_count = count
+    op.datatype = datateyp
+    op.bytesize = bytesize
+    op.signed = signed
+    op.count = count
     return op
 
-class AbstractResOpOrInputArg(AbstractValue):
+class Typed(object):
+    _mixin_ = True
+    _attrs_ = ('datatype', 'bytesize', 'signed')
+
+    datatype = '\x00'
+    bytesize = -1
+    signed = True
+
+    def inittype(self):
+        if self.returns_void():
+            self.bytesize = 0
+            self.datatype = 'v'
+            return
+
+        if self.is_primitive_array_access():
+            descr = self.getdescr()
+            type = self.type
+            if descr.is_array_of_floats() or descr.concrete_type == 'f':
+                type = FLOAT
+            self.bytesize = descr.get_item_size_in_bytes()
+            self.sign = descr.is_item_signed()
+            self.datatype = type
+        else:
+            # pass through the type of the first input argument
+            if self.numargs() == 0:
+                return
+            arg0 = self.getarg(0)
+            self.setdatatype(arg0.datatype, arg0.bytesize, arg0.signed)
+        assert self.datatype != '\x00'
+        assert self.bytesize > 0
+
+    def setdatatype(self, data_type, bytesize, signed):
+        self.datatype = data_type
+        self.bytesize = bytesize
+        self.signed = signed
+
+    def typestr(self):
+        sign = '-'
+        if not self.signed:
+            sign = '+'
+        return 'Type(%s%s, %d)' % (sign, self.type, self.size)
+
+class AbstractResOpOrInputArg(AbstractValue, Typed):
     _attrs_ = ('_forwarded',)
     _forwarded = None # either another resop or OptInfo  
 
     def get_forwarded(self):
         return self._forwarded
 
+
 class AbstractResOp(AbstractResOpOrInputArg):
     """The central ResOperation class, representing one operation."""
 
@@ -109,6 +158,7 @@
     boolreflex = -1
     boolinverse = -1
     vector = -1 # -1 means, no vector equivalent, -2 it is a vector statement
+    casts = ('\x00', -1, '\x00', -1)
 
     def getopnum(self):
         return self.opnum
@@ -192,7 +242,11 @@
             except KeyError:
                 num = len(memo)
                 memo[self] = num
-            sres = self.type + str(num) + ' = '
+            if self.is_vector():
+                assert isinstance(self, VectorOp)
+                sres = 'v%d[%dx%s%d] = ' % (num, self.count, self.datatype, 
self.bytesize * 8)
+            else:
+                sres = self.type + str(num) + ' = '
         #if self.result is not None:
         #    sres = '%s = ' % (self.result,)
         else:
@@ -219,6 +273,10 @@
         except KeyError:
             num = len(memo)
             memo[self] = num
+        if self.is_vector():
+            assert isinstance(self, VectorOp)
+            return 'v%d[%dx%s%d]' % (num, self.count, self.datatype,
+                                     self.bytesize * 8)
         return self.type + str(num)
 
     def __repr__(self):
@@ -363,6 +421,9 @@
     def is_label(self):
         return self.getopnum() == rop.LABEL
 
+    def is_vector(self):
+        return self.vector == -2
+
     def returns_void(self):
         return self.type == 'v'
 
@@ -376,28 +437,6 @@
 class PlainResOp(AbstractResOp):
     pass
 
-class CastResOp(AbstractResOp):
-    _attrs_ = ('casts')
-    casts = ('\x00', -1, '\x00', -1)
-
-    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:
-                from rpython.jit.metainterp.history import ConstInt
-                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):
 
     _descr = None
@@ -556,68 +595,56 @@
     def accumulates_value(self):
         return True
 
+class CastOp(object):
+    _mixin_ = True
+
+    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:
+                from rpython.jit.metainterp.history import ConstInt
+                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 VectorOp(object):
     _mixin_ = True
-    #_attrs_ = ('item_type','item_count','item_size','item_signed','accum')
-    _attrs_ = ('item_type', 'item_count')
-
-    #def __init__(self, item_type=FLOAT, item_count=2, item_size=8, 
item_signed=False, accum=None):
-    #    assert item_type in (FLOAT, INT)
-    #    self.item_type = item_type
-    #    self.item_count = item_count
-    #    self.item_size = item_size
-    #    self.item_signed = item_signed
-    #    self.accum = None
-
-    def gettype(self):
-        return self.type
-
-    def getbytes(self):
-        return self.slot_bytes
-
-    def getcount(self):
-        return self.item_count
-
-    def fully_packed(self, vec_reg_size):
-        return self.item_size * self.item_count == vec_reg_size
-
-    def forget_value(self):
-        raise NotImplementedError("cannot forget value of vector")
-
-    def clonebox(self):
-        return BoxVector(self.item_type, self.item_count, self.item_size, 
self.item_signed)
-
-    def constbox(self):
-        raise NotImplementedError("not possible to have a constant vector box")
-
-    def nonnull(self):
-        raise NotImplementedError("no value known, nonnull is unkown")
+    _attrs_ = ('count',)
 
     def repr_rpython(self):
         return repr_rpython(self, 'bv')
 
     def same_shape(self, other):
-        if not isinstance(other, BoxVector):
+        """ NOT_RPYTHON """
+        if not other.is_vector():
             return False
         #
-        if other.item_size == -1 or self.item_size == -1:
+        # TODO ? if other.item_size == -1 or self.item_size == -1:
             # fallback for tests that do not specify the size
-            return True
+        #    return True
         #
-        if self.item_type != other.item_type:
+        if self.datatype != other.datatype:
             return False
-        if self.item_size != other.item_size:
+        if self.bytesize != other.bytesize:
             return False
-        if self.item_count != other.item_count:
+        if self.signed!= other.signed:
             return False
-        if self.item_signed != other.item_signed:
+        if self.count != other.count:
             return False
         return True
 
     def getaccum(self):
         return self.accum
 
-
 class AbstractInputArg(AbstractResOpOrInputArg):
     def set_forwarded(self, forwarded_to):
         self._forwarded = forwarded_to
@@ -642,6 +669,9 @@
     def is_inputarg(self):
         return True
 
+    def initinputtype(self, cpu):
+        pass
+
 class InputArgInt(IntOp, AbstractInputArg):
     def __init__(self, intval=0):
         self.setint(intval)
@@ -974,11 +1004,11 @@
 
     '_RAW_LOAD_FIRST',
     'GETARRAYITEM_GC/2d/rfi',
-    'VEC_GETARRAYITEM_GC/3d/fi',
+    'VEC_GETARRAYITEM_GC/2d/fi',
     'GETARRAYITEM_RAW/2d/fi',
-    'VEC_GETARRAYITEM_RAW/3d/fi',
+    'VEC_GETARRAYITEM_RAW/2d/fi',
     'RAW_LOAD/2d/fi',
-    'VEC_RAW_LOAD/3d/fi',
+    'VEC_RAW_LOAD/2d/fi',
     '_RAW_LOAD_LAST',
 
     'GETINTERIORFIELD_GC/2d/rfi',
@@ -1059,19 +1089,15 @@
     '_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),
+    'INT_SIGNEXT': ('i', 0, 'i', 0),
+    'CAST_FLOAT_TO_INT': ('f', 8, 'i', 4),
+    'CAST_INT_TO_FLOAT': ('i', 4, 'f', 8),
+    'CAST_FLOAT_TO_SINGLEFLOAT': ('f', 8, 'f', 4),
+    'CAST_SINGLEFLOAT_TO_FLOAT': ('f', 4, 'f', 8),
+    'CAST_PTR_TO_INT': ('r', 0, 'i', 4),
+    'CAST_INT_TO_PTR': ('i', 4, 'r', 0),
 }
-del FLOAT
-del INT
 
 # ____________________________________________________________
 
@@ -1156,8 +1182,6 @@
     if is_guard:
         assert withdescr
         baseclass = GuardResOp
-    elif name in _cast_ops:
-        baseclass = CastResOp
     elif withdescr:
         baseclass = ResOpWithDescr
     else:
@@ -1171,6 +1195,8 @@
         mixins.append(RefOp)
     else:
         assert result_type == 'n'
+    if name in _cast_ops:
+        mixins.append(CastOp)
     if name.startswith('VEC'):
         mixins.insert(1,VectorOp)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to