Author: Richard Plangger <r...@pasra.at>
Branch: vecopt
Changeset: r77959:fab36fa4cf6d
Date: 2015-06-08 15:39 +0200
http://bitbucket.org/pypy/pypy/changeset/fab36fa4cf6d/

Log:    finished refactor the structure

diff --git a/rpython/jit/metainterp/optimizeopt/guard.py 
b/rpython/jit/metainterp/optimizeopt/guard.py
--- a/rpython/jit/metainterp/optimizeopt/guard.py
+++ b/rpython/jit/metainterp/optimizeopt/guard.py
@@ -4,6 +4,13 @@
 gathered with IntegralForwardModification
 """
 
+from rpython.jit.metainterp.optimizeopt.util import Renamer
+from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph,
+        MemoryRef, Node, IndexVar)
+from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp)
+from rpython.jit.metainterp.history import (ConstInt, BoxVector, 
+        BoxFloat, BoxInt, ConstFloat, Box)
+
 class Guard(object):
     """ An object wrapper around a guard. Helps to determine
         if one guard implies another
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
@@ -1,3 +1,12 @@
+
+from rpython.jit.metainterp.history import (FLOAT,INT,ConstInt,BoxVector,
+        BoxFloat,BoxInt)
+from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp)
+from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph,
+        MemoryRef, Node, IndexVar)
+from rpython.jit.metainterp.optimizeopt.util import Renamer
+from rpython.rlib.objectmodel import we_are_translated
+
 
 class SchedulerData(object):
     pass
@@ -71,6 +80,60 @@
         node.clear_dependencies()
         node.emitted = True
 
+class PackType(object):
+    UNKNOWN_TYPE = '-'
+
+    def __init__(self, type, size, signed, count=-1):
+        assert type in (FLOAT, INT, PackType.UNKNOWN_TYPE)
+        self.type = type
+        self.size = size
+        self.signed = signed
+        self.count = count
+
+    def gettype(self):
+        return self.type
+
+    def getsize(self):
+        return self.size
+
+    def getsigned(self):
+        return self.signed
+
+    def get_byte_size(self):
+        return self.size
+
+    def getcount(self):
+        return self.count
+
+    @staticmethod
+    def by_descr(descr, vec_reg_size):
+        _t = INT
+        if descr.is_array_of_floats() or descr.concrete_type == FLOAT:
+            _t = FLOAT
+        size = descr.get_item_size_in_bytes()
+        pt = PackType(_t, size, descr.is_item_signed(), vec_reg_size // size)
+        return pt
+
+    def is_valid(self):
+        return self.type != PackType.UNKNOWN_TYPE and self.size > 0
+
+    def new_vector_box(self, count):
+        return BoxVector(self.type, count, self.size, self.signed)
+
+    def __repr__(self):
+        return 'PackType(%s, %d, %d, #%d)' % (self.type, self.size, 
self.signed, self.count)
+
+    @staticmethod
+    def of(box, count=-1):
+        assert isinstance(box, BoxVector)
+        if count == -1:
+            count = box.item_count
+        return PackType(box.item_type, box.item_size, box.item_signed, count)
+
+    def clone(self):
+        return PackType(self.type, self.size, self.signed, self.count)
+
+
 PT_FLOAT_2 = PackType(FLOAT, 4, False, 2)
 PT_DOUBLE_2 = PackType(FLOAT, 8, False, 2)
 PT_FLOAT_GENERIC = PackType(INT, -1, True)
@@ -82,6 +145,285 @@
 INT_RES = PT_INT_GENERIC
 FLOAT_RES = PT_FLOAT_GENERIC
 
+class OpToVectorOp(object):
+    def __init__(self, arg_ptypes, result_ptype):
+        self.arg_ptypes = [a for a in arg_ptypes] # do not use a tuple. 
rpython cannot union
+        self.result_ptype = result_ptype
+        self.preamble_ops = None
+        self.sched_data = None
+        self.pack = None
+        self.input_type = None
+        self.output_type = None
+
+    def clone_vbox_set_count(self, box, count):
+        return BoxVector(box.item_type, count, box.item_size, box.item_signed)
+
+    def is_vector_arg(self, i):
+        if i < 0 or i >= len(self.arg_ptypes):
+            return False
+        return self.arg_ptypes[i] is not None
+
+    def getsplitsize(self):
+        return self.input_type.getsize()
+
+    def determine_input_type(self, op):
+        arg = op.getarg(0)
+        _, vbox = self.sched_data.getvector_of_box(op.getarg(0))
+        if vbox:
+            return PackType.of(vbox)
+        else:
+            vec_reg_size = self.sched_data.vec_reg_size
+            if isinstance(arg, ConstInt) or isinstance(arg, BoxInt):
+                return PackType(INT, 8, True, 2)
+            elif isinstance(arg, ConstFloat) or isinstance(arg, BoxFloat):
+                return PackType(FLOAT, 8, True, 2)
+            else:
+                raise NotImplementedError("arg %s not supported" % (arg,))
+
+    def determine_output_type(self, op):
+        return self.determine_input_type(op)
+
+    def update_input_output(self, pack):
+        op0 = pack.operations[0].getoperation()
+        self.input_type = self.determine_input_type(op0)
+        self.output_type = self.determine_output_type(op0)
+
+    def as_vector_operation(self, pack, sched_data, oplist):
+        self.sched_data = sched_data
+        self.preamble_ops = oplist
+        self.update_input_output(pack)
+
+
+        off = 0
+        stride = self.split_pack(pack)
+        left = len(pack.operations)
+        assert stride > 0
+        while off < len(pack.operations):
+            if left < stride:
+                self.preamble_ops.append(pack.operations[off].getoperation())
+                off += 1
+                continue
+            ops = pack.operations[off:off+stride]
+            self.pack = Pack(ops)
+            self.transform_pack(ops, off, stride)
+            off += stride
+            left -= stride
+
+        self.pack = None
+        self.preamble_ops = None
+        self.sched_data = None
+        self.input_type = None
+        self.output_type = None
+
+    def split_pack(self, pack):
+        pack_count = len(pack.operations)
+        vec_reg_size = self.sched_data.vec_reg_size
+        bytes = pack_count * self.getsplitsize()
+        if bytes > vec_reg_size:
+            return vec_reg_size // self.getsplitsize()
+        if bytes < vec_reg_size:
+            return 1
+        return pack_count
+
+    def before_argument_transform(self, args):
+        pass
+
+    def transform_pack(self, ops, off, stride):
+        op = self.pack.operations[0].getoperation()
+        args = op.getarglist()
+        #
+        self.before_argument_transform(args)
+        #
+        for i,arg in enumerate(args):
+            if self.is_vector_arg(i):
+                args[i] = self.transform_argument(args[i], i, off)
+        #
+        result = op.result
+        result = self.transform_result(result, off)
+        #
+        vop = ResOperation(op.vector, args, result, op.getdescr())
+        self.preamble_ops.append(vop)
+
+    def transform_result(self, result, off):
+        if result is None:
+            return None
+        vbox = self.new_result_vector_box()
+        #
+        # mark the position and the vbox in the hash
+        for i, node in enumerate(self.pack.operations):
+            op = node.getoperation()
+            self.sched_data.setvector_of_box(op.result, i, vbox)
+        return vbox
+
+    def new_result_vector_box(self):
+        type = self.output_type.gettype()
+        size = self.output_type.getsize()
+        count = min(self.output_type.getcount(), len(self.pack.operations))
+        signed = self.output_type.signed
+        return BoxVector(type, count, size, signed)
+
+    def transform_argument(self, arg, argidx, off):
+        ops = self.pack.operations
+        box_pos, vbox = self.sched_data.getvector_of_box(arg)
+        if not vbox:
+            # constant/variable expand this box
+            vbox = self.expand(ops, arg, argidx)
+            box_pos = 0
+
+        # use the input as an indicator for the pack type
+        packable = self.sched_data.vec_reg_size // self.input_type.getsize()
+        packed = vbox.item_count
+        assert packed >= 0
+        assert packable >= 0
+        if packed < packable:
+            # the argument is scattered along different vector boxes
+            args = [op.getoperation().getarg(argidx) for op in ops]
+            vbox = self._pack(vbox, packed, args, packable)
+            self.update_input_output(self.pack)
+        elif packed > packable:
+            # the argument has more items than the operation is able to 
process!
+            vbox = self.unpack(vbox, off, packable, self.input_type)
+            self.update_input_output(self.pack)
+        #
+        if off != 0 and box_pos != 0:
+            # The original box is at a position != 0 but it
+            # is required to be at position 0. Unpack it!
+            vbox = self.unpack(vbox, off, len(ops), self.input_type)
+            self.update_input_output(self.pack)
+        # convert size i64 -> i32, i32 -> i64, ...
+        if self.input_type.getsize() > 0 and \
+           self.input_type.getsize() != vbox.getsize():
+            vbox = self.extend(vbox, self.input_type)
+        #
+        return vbox
+
+    def extend(self, vbox, newtype):
+        assert vbox.gettype() == newtype.gettype()
+        if vbox.gettype() == INT:
+            return self.extend_int(vbox, newtype)
+        else:
+            raise NotImplementedError("cannot yet extend float")
+
+    def extend_int(self, vbox, newtype):
+        vbox_cloned = newtype.new_vector_box(vbox.item_count)
+        op = ResOperation(rop.VEC_INT_SIGNEXT, 
+                          [vbox, ConstInt(newtype.getsize())],
+                          vbox_cloned)
+        self.preamble_ops.append(op)
+        return vbox_cloned
+
+    def unpack(self, vbox, index, count, arg_ptype):
+        vbox_cloned = self.clone_vbox_set_count(vbox, count)
+        opnum = rop.VEC_FLOAT_UNPACK
+        if vbox.item_type == INT:
+            opnum = rop.VEC_INT_UNPACK
+        op = ResOperation(opnum, [vbox, ConstInt(index), ConstInt(count)], 
vbox_cloned)
+        self.preamble_ops.append(op)
+        return vbox_cloned
+
+    def _pack(self, tgt_box, index, args, packable):
+        """ If there are two vector boxes:
+          v1 = [<empty>,<emtpy>,X,Y]
+          v2 = [A,B,<empty>,<empty>]
+          this function creates a box pack instruction to merge them to:
+          v1/2 = [A,B,X,Y]
+        """
+        opnum = rop.VEC_FLOAT_PACK
+        if tgt_box.item_type == INT:
+            opnum = rop.VEC_INT_PACK
+        arg_count = len(args)
+        i = index
+        while i < arg_count and tgt_box.item_count < packable:
+            arg = args[i]
+            pos, src_box = self.sched_data.getvector_of_box(arg)
+            if pos == -1:
+                i += 1
+                continue
+            count = tgt_box.item_count + src_box.item_count
+            new_box = self.clone_vbox_set_count(tgt_box, count)
+            op = ResOperation(opnum, [tgt_box, src_box, ConstInt(i),
+                                      ConstInt(src_box.item_count)], new_box)
+            self.preamble_ops.append(op)
+            if not we_are_translated():
+                self._check_vec_pack(op)
+            i += src_box.item_count
+
+            # overwrite the new positions, arguments now live in new_box
+            # at a new position
+            for j in range(i):
+                arg = args[j]
+                self.sched_data.setvector_of_box(arg, j, new_box)
+            tgt_box = new_box
+        _, vbox = self.sched_data.getvector_of_box(args[0])
+        return vbox
+
+    def _check_vec_pack(self, op):
+        result = op.result
+        arg0 = op.getarg(0)
+        arg1 = op.getarg(1)
+        index = op.getarg(2)
+        count = op.getarg(3)
+        assert isinstance(result, BoxVector)
+        assert isinstance(arg0, BoxVector)
+        assert isinstance(index, ConstInt)
+        assert isinstance(count, ConstInt)
+        assert arg0.item_size == result.item_size
+        if isinstance(arg1, BoxVector):
+            assert arg1.item_size == result.item_size
+        else:
+            assert count.value == 1
+        assert index.value < result.item_count
+        assert index.value + count.value <= result.item_count
+        assert result.item_count > arg0.item_count
+
+    def expand(self, nodes, arg, argidx):
+        vbox = self.input_type.new_vector_box(len(nodes))
+        box_type = arg.type
+        expanded_map = self.sched_data.expanded_map
+        invariant_ops = self.sched_data.invariant_oplist
+        invariant_vars = self.sched_data.invariant_vector_vars
+        if isinstance(arg, BoxVector):
+            box_type = arg.item_type
+
+        # note that heterogenous nodes are not yet tracked
+        already_expanded = expanded_map.get(arg, None)
+        if already_expanded:
+            return already_expanded
+
+        for i, node in enumerate(nodes):
+            op = node.getoperation()
+            if not arg.same_box(op.getarg(argidx)):
+                break
+            i += 1
+        else:
+            expand_opnum = rop.VEC_FLOAT_EXPAND
+            if box_type == INT:
+                expand_opnum = rop.VEC_INT_EXPAND
+            op = ResOperation(expand_opnum, [arg], vbox)
+            invariant_ops.append(op)
+            invariant_vars.append(vbox)
+            expanded_map[arg] = vbox
+            return vbox
+
+        op = ResOperation(rop.VEC_BOX, [ConstInt(len(nodes))], vbox)
+        invariant_ops.append(op)
+        opnum = rop.VEC_FLOAT_PACK
+        if arg.type == INT:
+            opnum = rop.VEC_INT_PACK
+        for i,node in enumerate(nodes):
+            op = node.getoperation()
+            arg = op.getarg(argidx)
+            new_box = vbox.clonebox()
+            ci = ConstInt(i)
+            c1 = ConstInt(1)
+            op = ResOperation(opnum, [vbox,arg,ci,c1], new_box)
+            vbox = new_box
+            invariant_ops.append(op)
+
+        invariant_vars.append(vbox)
+        return vbox
+
+
 class OpToVectorOpConv(OpToVectorOp):
     def __init__(self, intype, outtype):
         self.from_size = intype.getsize()
@@ -264,3 +606,65 @@
 
         return oplist
 
+class Pack(object):
+    """ A pack is a set of n statements that are:
+        * isomorphic
+        * independent
+    """
+    def __init__(self, ops):
+        self.operations = ops
+        for i,node in enumerate(self.operations):
+            node.pack = self
+            node.pack_position = i
+        self.accum_variable = None
+        self.accum_position = -1
+
+    def opcount(self):
+        return len(self.operations)
+
+    def opnum(self):
+        assert len(self.operations) > 0
+        return self.operations[0].getoperation().getopnum()
+
+    def clear(self):
+        for node in self.operations:
+            node.pack = None
+            node.pack_position = -1
+
+    def rightmost_match_leftmost(self, other):
+        assert isinstance(other, Pack)
+        rightmost = self.operations[-1]
+        leftmost = other.operations[0]
+        return rightmost == leftmost and \
+               self.accum_variable == other.accum_variable and \
+               self.accum_position == other.accum_position
+
+    def __repr__(self):
+        return "Pack(%r)" % self.operations
+
+    def is_accumulating(self):
+        return self.accum_variable is not None
+
+class Pair(Pack):
+    """ A special Pack object with only two statements. """
+    def __init__(self, left, right):
+        assert isinstance(left, Node)
+        assert isinstance(right, Node)
+        self.left = left
+        self.right = right
+        Pack.__init__(self, [left, right])
+
+    def __eq__(self, other):
+        if isinstance(other, Pair):
+            return self.left is other.left and \
+                   self.right is other.right
+
+class AccumPair(Pair):
+    def __init__(self, left, right, accum_var, accum_pos):
+        assert isinstance(left, Node)
+        assert isinstance(right, Node)
+        Pair.__init__(self, left, right)
+        self.left = left
+        self.right = right
+        self.accum_variable = accum_var
+        self.accum_position = accum_pos
diff --git a/rpython/jit/metainterp/optimizeopt/util.py 
b/rpython/jit/metainterp/optimizeopt/util.py
--- a/rpython/jit/metainterp/optimizeopt/util.py
+++ b/rpython/jit/metainterp/optimizeopt/util.py
@@ -4,10 +4,11 @@
 from rpython.rlib.objectmodel import r_dict, compute_identity_hash, specialize
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.debug import make_sure_not_resized
+from rpython.rlib.objectmodel import we_are_translated
 from rpython.jit.metainterp import resoperation
-from rpython.rlib.debug import make_sure_not_resized
 from rpython.jit.metainterp.resoperation import rop
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.jit.metainterp.resume import Snapshot
 
 # ____________________________________________________________
 # Misc. utilities
@@ -188,3 +189,53 @@
                         assert False
     assert len(oplist1) == len(oplist2)
     return True
+
+class Renamer(object):
+    def __init__(self):
+        self.rename_map = {}
+
+    def rename_box(self, box):
+        return self.rename_map.get(box, box)
+
+    def start_renaming(self, var, tovar):
+        self.rename_map[var] = tovar
+
+    def rename(self, op):
+        for i, arg in enumerate(op.getarglist()):
+            arg = self.rename_map.get(arg, arg)
+            op.setarg(i, arg)
+
+        if op.is_guard():
+            assert isinstance(op, resoperation.GuardResOp)
+            op.rd_snapshot = self.rename_rd_snapshot(op.rd_snapshot)
+            self.rename_failargs(op)
+
+        return True
+
+    def rename_failargs(self, guard, clone=False):
+        if guard.getfailargs() is not None:
+            if clone:
+                args = guard.getfailargs()[:]
+            else:
+                args = guard.getfailargs()
+            for i,arg in enumerate(args):
+                value = self.rename_map.get(arg,arg)
+                args[i] = value
+            return args
+        return None
+
+    def rename_rd_snapshot(self, snapshot, clone=False):
+        # snapshots are nested like the MIFrames
+        if snapshot is None:
+            return None
+        if clone:
+            boxes = snapshot.boxes[:]
+        else:
+            boxes = snapshot.boxes
+        for i,box in enumerate(boxes):
+            value = self.rename_map.get(box,box)
+            boxes[i] = value
+        #
+        rec_snap = self.rename_rd_snapshot(snapshot.prev, clone)
+        return Snapshot(rec_snap, boxes)
+
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
@@ -7,10 +7,10 @@
 from rpython.jit.metainterp.history import (ConstInt, VECTOR, FLOAT, INT,
         BoxVector, BoxFloat, BoxInt, ConstFloat, TargetToken, JitCellToken, 
Box)
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer, 
Optimization
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph, 
+from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method, 
Renamer
+from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph,
         MemoryRef, Node, IndexVar)
-from rpython.jit.metainterp.optimizeopt.schedule import VecScheduleData, 
Scheduler
+from rpython.jit.metainterp.optimizeopt.schedule import VecScheduleData, 
Scheduler, Pack, Pair, AccumPair
 from rpython.jit.metainterp.optimizeopt.guard import GuardStrengthenOpt
 from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp)
 from rpython.rlib.objectmodel import we_are_translated
@@ -462,55 +462,6 @@
                 guard_node.edge_to(ee_guard_node, label='pullup-last-guard')
                 guard_node.relax_guard_to(ee_guard_node)
 
-class Renamer(object):
-    def __init__(self):
-        self.rename_map = {}
-
-    def rename_box(self, box):
-        return self.rename_map.get(box, box)
-
-    def start_renaming(self, var, tovar):
-        self.rename_map[var] = tovar
-
-    def rename(self, op):
-        for i, arg in enumerate(op.getarglist()):
-            arg = self.rename_map.get(arg, arg)
-            op.setarg(i, arg)
-
-        if op.is_guard():
-            assert isinstance(op, GuardResOp)
-            op.rd_snapshot = self.rename_rd_snapshot(op.rd_snapshot)
-            self.rename_failargs(op)
-
-        return True
-
-    def rename_failargs(self, guard, clone=False):
-        if guard.getfailargs() is not None:
-            if clone:
-                args = guard.getfailargs()[:]
-            else:
-                args = guard.getfailargs()
-            for i,arg in enumerate(args):
-                value = self.rename_map.get(arg,arg)
-                args[i] = value
-            return args
-        return None
-
-    def rename_rd_snapshot(self, snapshot, clone=False):
-        # snapshots are nested like the MIFrames
-        if snapshot is None:
-            return None
-        if clone:
-            boxes = snapshot.boxes[:]
-        else:
-            boxes = snapshot.boxes
-        for i,box in enumerate(boxes):
-            value = self.rename_map.get(box,box)
-            boxes[i] = value
-        #
-        rec_snap = self.rename_rd_snapshot(snapshot.prev, clone)
-        return Snapshot(rec_snap, boxes)
-
 class CostModel(object):
     def __init__(self, threshold):
         self.threshold = threshold
@@ -556,336 +507,6 @@
         return 1
 
 
-class PackType(object):
-    UNKNOWN_TYPE = '-'
-
-    def __init__(self, type, size, signed, count=-1):
-        assert type in (FLOAT, INT, PackType.UNKNOWN_TYPE)
-        self.type = type
-        self.size = size
-        self.signed = signed
-        self.count = count
-
-    def gettype(self):
-        return self.type
-
-    def getsize(self):
-        return self.size
-
-    def getsigned(self):
-        return self.signed
-
-    def get_byte_size(self):
-        return self.size
-
-    def getcount(self):
-        return self.count
-
-    @staticmethod
-    def by_descr(descr, vec_reg_size):
-        _t = INT
-        if descr.is_array_of_floats() or descr.concrete_type == FLOAT:
-            _t = FLOAT
-        size = descr.get_item_size_in_bytes()
-        pt = PackType(_t, size, descr.is_item_signed(), vec_reg_size // size)
-        return pt
-
-    def is_valid(self):
-        return self.type != PackType.UNKNOWN_TYPE and self.size > 0
-
-    def new_vector_box(self, count):
-        return BoxVector(self.type, count, self.size, self.signed)
-
-    def __repr__(self):
-        return 'PackType(%s, %d, %d, #%d)' % (self.type, self.size, 
self.signed, self.count)
-
-    @staticmethod
-    def of(box, count=-1):
-        assert isinstance(box, BoxVector)
-        if count == -1:
-            count = box.item_count
-        return PackType(box.item_type, box.item_size, box.item_signed, count)
-
-    def clone(self):
-        return PackType(self.type, self.size, self.signed, self.count)
-
-class OpToVectorOp(object):
-    def __init__(self, arg_ptypes, result_ptype):
-        self.arg_ptypes = [a for a in arg_ptypes] # do not use a tuple. 
rpython cannot union
-        self.result_ptype = result_ptype
-        self.preamble_ops = None
-        self.sched_data = None
-        self.pack = None
-        self.input_type = None
-        self.output_type = None
-
-    def clone_vbox_set_count(self, box, count):
-        return BoxVector(box.item_type, count, box.item_size, box.item_signed)
-
-    def is_vector_arg(self, i):
-        if i < 0 or i >= len(self.arg_ptypes):
-            return False
-        return self.arg_ptypes[i] is not None
-
-    def getsplitsize(self):
-        return self.input_type.getsize()
-
-    def determine_input_type(self, op):
-        arg = op.getarg(0)
-        _, vbox = self.sched_data.getvector_of_box(op.getarg(0))
-        if vbox:
-            return PackType.of(vbox)
-        else:
-            vec_reg_size = self.sched_data.vec_reg_size
-            if isinstance(arg, ConstInt) or isinstance(arg, BoxInt):
-                return PackType(INT, 8, True, 2)
-            elif isinstance(arg, ConstFloat) or isinstance(arg, BoxFloat):
-                return PackType(FLOAT, 8, True, 2)
-            else:
-                raise NotImplementedError("arg %s not supported" % (arg,))
-
-    def determine_output_type(self, op):
-        return self.determine_input_type(op)
-
-    def update_input_output(self, pack):
-        op0 = pack.operations[0].getoperation()
-        self.input_type = self.determine_input_type(op0)
-        self.output_type = self.determine_output_type(op0)
-
-    def as_vector_operation(self, pack, sched_data, oplist):
-        self.sched_data = sched_data
-        self.preamble_ops = oplist
-        self.update_input_output(pack)
-
-
-        off = 0
-        stride = self.split_pack(pack)
-        left = len(pack.operations)
-        assert stride > 0
-        while off < len(pack.operations):
-            if left < stride:
-                self.preamble_ops.append(pack.operations[off].getoperation())
-                off += 1
-                continue
-            ops = pack.operations[off:off+stride]
-            self.pack = Pack(ops)
-            self.transform_pack(ops, off, stride)
-            off += stride
-            left -= stride
-
-        self.pack = None
-        self.preamble_ops = None
-        self.sched_data = None
-        self.input_type = None
-        self.output_type = None
-
-    def split_pack(self, pack):
-        pack_count = len(pack.operations)
-        vec_reg_size = self.sched_data.vec_reg_size
-        bytes = pack_count * self.getsplitsize()
-        if bytes > vec_reg_size:
-            return vec_reg_size // self.getsplitsize()
-        if bytes < vec_reg_size:
-            return 1
-        return pack_count
-
-    def before_argument_transform(self, args):
-        pass
-
-    def transform_pack(self, ops, off, stride):
-        op = self.pack.operations[0].getoperation()
-        args = op.getarglist()
-        #
-        self.before_argument_transform(args)
-        #
-        for i,arg in enumerate(args):
-            if self.is_vector_arg(i):
-                args[i] = self.transform_argument(args[i], i, off)
-        #
-        result = op.result
-        result = self.transform_result(result, off)
-        #
-        vop = ResOperation(op.vector, args, result, op.getdescr())
-        self.preamble_ops.append(vop)
-
-    def transform_result(self, result, off):
-        if result is None:
-            return None
-        vbox = self.new_result_vector_box()
-        #
-        # mark the position and the vbox in the hash
-        for i, node in enumerate(self.pack.operations):
-            op = node.getoperation()
-            self.sched_data.setvector_of_box(op.result, i, vbox)
-        return vbox
-
-    def new_result_vector_box(self):
-        type = self.output_type.gettype()
-        size = self.output_type.getsize()
-        count = min(self.output_type.getcount(), len(self.pack.operations))
-        signed = self.output_type.signed
-        return BoxVector(type, count, size, signed)
-
-    def transform_argument(self, arg, argidx, off):
-        ops = self.pack.operations
-        box_pos, vbox = self.sched_data.getvector_of_box(arg)
-        if not vbox:
-            # constant/variable expand this box
-            vbox = self.expand(ops, arg, argidx)
-            box_pos = 0
-
-        # use the input as an indicator for the pack type
-        packable = self.sched_data.vec_reg_size // self.input_type.getsize()
-        packed = vbox.item_count
-        assert packed >= 0
-        assert packable >= 0
-        if packed < packable:
-            # the argument is scattered along different vector boxes
-            args = [op.getoperation().getarg(argidx) for op in ops]
-            vbox = self._pack(vbox, packed, args, packable)
-            self.update_input_output(self.pack)
-        elif packed > packable:
-            # the argument has more items than the operation is able to 
process!
-            vbox = self.unpack(vbox, off, packable, self.input_type)
-            self.update_input_output(self.pack)
-        #
-        if off != 0 and box_pos != 0:
-            # The original box is at a position != 0 but it
-            # is required to be at position 0. Unpack it!
-            vbox = self.unpack(vbox, off, len(ops), self.input_type)
-            self.update_input_output(self.pack)
-        # convert size i64 -> i32, i32 -> i64, ...
-        if self.input_type.getsize() > 0 and \
-           self.input_type.getsize() != vbox.getsize():
-            vbox = self.extend(vbox, self.input_type)
-        #
-        return vbox
-
-    def extend(self, vbox, newtype):
-        assert vbox.gettype() == newtype.gettype()
-        if vbox.gettype() == INT:
-            return self.extend_int(vbox, newtype)
-        else:
-            raise NotImplementedError("cannot yet extend float")
-
-    def extend_int(self, vbox, newtype):
-        vbox_cloned = newtype.new_vector_box(vbox.item_count)
-        op = ResOperation(rop.VEC_INT_SIGNEXT, 
-                          [vbox, ConstInt(newtype.getsize())],
-                          vbox_cloned)
-        self.preamble_ops.append(op)
-        return vbox_cloned
-
-    def unpack(self, vbox, index, count, arg_ptype):
-        vbox_cloned = self.clone_vbox_set_count(vbox, count)
-        opnum = rop.VEC_FLOAT_UNPACK
-        if vbox.item_type == INT:
-            opnum = rop.VEC_INT_UNPACK
-        op = ResOperation(opnum, [vbox, ConstInt(index), ConstInt(count)], 
vbox_cloned)
-        self.preamble_ops.append(op)
-        return vbox_cloned
-
-    def _pack(self, tgt_box, index, args, packable):
-        """ If there are two vector boxes:
-          v1 = [<empty>,<emtpy>,X,Y]
-          v2 = [A,B,<empty>,<empty>]
-          this function creates a box pack instruction to merge them to:
-          v1/2 = [A,B,X,Y]
-        """
-        opnum = rop.VEC_FLOAT_PACK
-        if tgt_box.item_type == INT:
-            opnum = rop.VEC_INT_PACK
-        arg_count = len(args)
-        i = index
-        while i < arg_count and tgt_box.item_count < packable:
-            arg = args[i]
-            pos, src_box = self.sched_data.getvector_of_box(arg)
-            if pos == -1:
-                i += 1
-                continue
-            count = tgt_box.item_count + src_box.item_count
-            new_box = self.clone_vbox_set_count(tgt_box, count)
-            op = ResOperation(opnum, [tgt_box, src_box, ConstInt(i),
-                                      ConstInt(src_box.item_count)], new_box)
-            self.preamble_ops.append(op)
-            if not we_are_translated():
-                self._check_vec_pack(op)
-            i += src_box.item_count
-
-            # overwrite the new positions, arguments now live in new_box
-            # at a new position
-            for j in range(i):
-                arg = args[j]
-                self.sched_data.setvector_of_box(arg, j, new_box)
-            tgt_box = new_box
-        _, vbox = self.sched_data.getvector_of_box(args[0])
-        return vbox
-
-    def _check_vec_pack(self, op):
-        result = op.result
-        arg0 = op.getarg(0)
-        arg1 = op.getarg(1)
-        index = op.getarg(2)
-        count = op.getarg(3)
-        assert isinstance(result, BoxVector)
-        assert isinstance(arg0, BoxVector)
-        assert isinstance(index, ConstInt)
-        assert isinstance(count, ConstInt)
-        assert arg0.item_size == result.item_size
-        if isinstance(arg1, BoxVector):
-            assert arg1.item_size == result.item_size
-        else:
-            assert count.value == 1
-        assert index.value < result.item_count
-        assert index.value + count.value <= result.item_count
-        assert result.item_count > arg0.item_count
-
-    def expand(self, nodes, arg, argidx):
-        vbox = self.input_type.new_vector_box(len(nodes))
-        box_type = arg.type
-        expanded_map = self.sched_data.expanded_map
-        invariant_ops = self.sched_data.invariant_oplist
-        invariant_vars = self.sched_data.invariant_vector_vars
-        if isinstance(arg, BoxVector):
-            box_type = arg.item_type
-
-        # note that heterogenous nodes are not yet tracked
-        already_expanded = expanded_map.get(arg, None)
-        if already_expanded:
-            return already_expanded
-
-        for i, node in enumerate(nodes):
-            op = node.getoperation()
-            if not arg.same_box(op.getarg(argidx)):
-                break
-            i += 1
-        else:
-            expand_opnum = rop.VEC_FLOAT_EXPAND
-            if box_type == INT:
-                expand_opnum = rop.VEC_INT_EXPAND
-            op = ResOperation(expand_opnum, [arg], vbox)
-            invariant_ops.append(op)
-            invariant_vars.append(vbox)
-            expanded_map[arg] = vbox
-            return vbox
-
-        op = ResOperation(rop.VEC_BOX, [ConstInt(len(nodes))], vbox)
-        invariant_ops.append(op)
-        opnum = rop.VEC_FLOAT_PACK
-        if arg.type == INT:
-            opnum = rop.VEC_INT_PACK
-        for i,node in enumerate(nodes):
-            op = node.getoperation()
-            arg = op.getarg(argidx)
-            new_box = vbox.clonebox()
-            ci = ConstInt(i)
-            c1 = ConstInt(1)
-            op = ResOperation(opnum, [vbox,arg,ci,c1], new_box)
-            vbox = new_box
-            invariant_ops.append(op)
-
-        invariant_vars.append(vbox)
-        return vbox
 
 def isomorphic(l_op, r_op):
     """ Subject of definition """
@@ -1021,65 +642,3 @@
             del self.packs[last_pos]
         return last_pos
 
-class Pack(object):
-    """ A pack is a set of n statements that are:
-        * isomorphic
-        * independent
-    """
-    def __init__(self, ops):
-        self.operations = ops
-        for i,node in enumerate(self.operations):
-            node.pack = self
-            node.pack_position = i
-        self.accum_variable = None
-        self.accum_position = -1
-
-    def opcount(self):
-        return len(self.operations)
-
-    def opnum(self):
-        assert len(self.operations) > 0
-        return self.operations[0].getoperation().getopnum()
-
-    def clear(self):
-        for node in self.operations:
-            node.pack = None
-            node.pack_position = -1
-
-    def rightmost_match_leftmost(self, other):
-        assert isinstance(other, Pack)
-        rightmost = self.operations[-1]
-        leftmost = other.operations[0]
-        return rightmost == leftmost and \
-               self.accum_variable == other.accum_variable and \
-               self.accum_position == other.accum_position
-
-    def __repr__(self):
-        return "Pack(%r)" % self.operations
-
-    def is_accumulating(self):
-        return self.accum_variable is not None
-
-class Pair(Pack):
-    """ A special Pack object with only two statements. """
-    def __init__(self, left, right):
-        assert isinstance(left, Node)
-        assert isinstance(right, Node)
-        self.left = left
-        self.right = right
-        Pack.__init__(self, [left, right])
-
-    def __eq__(self, other):
-        if isinstance(other, Pair):
-            return self.left is other.left and \
-                   self.right is other.right
-
-class AccumPair(Pair):
-    def __init__(self, left, right, accum_var, accum_pos):
-        assert isinstance(left, Node)
-        assert isinstance(right, Node)
-        Pair.__init__(self, left, right)
-        self.left = left
-        self.right = right
-        self.accum_variable = accum_var
-        self.accum_position = accum_pos
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to