Author: Richard Plangger <r...@pasra.at> Branch: vecopt Changeset: r77583:9eec1d3c661e Date: 2015-05-26 14:17 +0200 http://bitbucket.org/pypy/pypy/changeset/9eec1d3c661e/
Log: enhanced test env to check schedule operation added same_shape to AbstractValue (needed for comparison of two BoxVector and their shape) found an error where returned box had an invalid shape diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -127,6 +127,10 @@ def same_box(self, other): return self is other + def same_shape(self, other): + # only structured containers can compare their shape (vector box) + return True + class AbstractDescr(AbstractValue): __slots__ = () @@ -391,8 +395,8 @@ t = 'b' self._str = '%s%d' % (t, Box._counter) if self.type == VECTOR: - self._str += '[%s%d#%d]' % (self.item_type, self.item_size * 8, - self.item_count) + self._str = '%s%d[%s%d#%d]' % (t, Box._counter, self.item_type, + self.item_size * 8, self.item_count) Box._counter += 1 return self._str @@ -551,19 +555,19 @@ _attrs_ = ('item_type','item_count','item_size','signed') _extended_display = False - def __init__(self, item_type=FLOAT, item_count=2, item_size=8, signed=True): + def __init__(self, item_type=FLOAT, item_count=2, item_size=8, item_signed=False): assert item_type in (FLOAT, INT) self.item_type = item_type self.item_count = item_count self.item_size = item_size - self.signed = signed + self.item_signed = item_signed def gettype(self): return self.item_type def getsize(self): return self.item_size def getsigned(self): - return self.signed + return self.item_signed def getcount(self): return self.item_count @@ -571,7 +575,7 @@ raise NotImplementedError("cannot forget value of vector") def clonebox(self): - return BoxVector(self.item_type, self.item_count, self.item_size, self.signed) + 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") @@ -582,6 +586,24 @@ def repr_rpython(self): return repr_rpython(self, 'bv') + def same_shape(self, other): + if not isinstance(other, BoxVector): + return False + # + if other.item_size == -1 or self.item_size == -1: + # fallback for tests that do not specify the size + return True + # + if self.item_type != other.item_type: + return False + if self.item_size != other.item_size: + return False + if self.item_count != other.item_count: + return False + if self.item_signed != other.item_signed: + return False + return True + # ____________________________________________________________ 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 @@ -1,13 +1,66 @@ import py +from rpython.jit.metainterp.optimizeopt.util import equaloplists +from rpython.jit.metainterp.optimizeopt.vectorize import (VecScheduleData, + Pack) +from rpython.jit.metainterp.optimizeopt.dependency import Node from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin from rpython.jit.metainterp.optimizeopt.test.test_dependency import DependencyBaseTest +from rpython.jit.tool.oparser import parse as opparse +from rpython.jit.tool.oparser_model import get_model class SchedulerBaseTest(DependencyBaseTest): - def test_schedule_split_arith(self): - pass + def parse(self, source): + ns = { + 'double': self.floatarraydescr, + 'float': self.singlefloatarraydescr, + } + loop = opparse(" [p0,p1,p2,p3,p4,p5,i0,i1,i2,i3,i4,i5,f0,f1,f2,f3,f4,f5]\n" + source + \ + "\n jump(p0,p1,p2,p3,p4,p5,i0,i1,i2,i3,i4,i5,f0,f1,f2,f3,f4,f5)", + cpu=self.cpu, + namespace=ns) + del loop.operations[-1] + return loop + def pack(self, loop, l, r): + return [Node(op,i) for i,op in enumerate(loop.operations[l:r])] + + def schedule(self, loop_orig, packs, vec_reg_size=16): + loop = get_model(False).ExtendedTreeLoop("loop") + loop.original_jitcell_token = loop_orig.original_jitcell_token + loop.inputargs = loop_orig.inputargs + + ops = [] + vsd = VecScheduleData(vec_reg_size) + for pack in packs: + if len(pack) == 1: + ops.append(pack[0]) + else: + for op in vsd.as_vector_operation(Pack(pack)): + ops.append(op) + loop.operations = ops + return loop + + def assert_operations_match(self, loop_a, loop_b): + assert equaloplists(loop_a.operations, loop_b.operations) + + def test_schedule_split_load(self): + loop1 = self.parse(""" + i10 = raw_load(p0, i0, descr=float) + i11 = raw_load(p0, i1, descr=float) + i12 = raw_load(p0, i2, descr=float) + i13 = raw_load(p0, i3, descr=float) + i14 = raw_load(p0, i4, descr=float) + i15 = raw_load(p0, i5, descr=float) + """) + pack1 = self.pack(loop1, 0, 6) + loop2 = self.schedule(loop1, [pack1]) + loop3 = self.parse(""" + v1[i32#4] = vec_raw_load(p0, i0, 4, descr=float) + v1[i32#2] = vec_raw_load(p0, i4, 2, descr=float) + """) + self.assert_equal(loop2, loop3) class TestLLType(SchedulerBaseTest, LLtypeMixin): pass 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 @@ -156,14 +156,17 @@ for i in range(op1.numargs()): x = op1.getarg(i) y = op2.getarg(i) + assert x.same_shape(y) assert x.same_box(remap.get(y, y)) if op2.result in remap: if op2.result is None: assert op1.result == remap[op2.result] else: + assert op1.result.same_shape(op2.result) assert op1.result.same_box(remap[op2.result]) else: remap[op2.result] = op1.result + assert op2.result.same_shape(op1.result) if op1.getopnum() not in [rop.JUMP, rop.LABEL] and not op1.is_guard(): assert op1.getdescr() == op2.getdescr() if op1.getfailargs() or op2.getfailargs(): 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 @@ -743,16 +743,12 @@ class OpToVectorOp(object): - def __init__(self, arg_ptypes, result_ptype, has_descr=False, - arg_clone_ptype=0, - needs_count_in_params=False): + 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.has_descr = has_descr - self.arg_clone_ptype = arg_clone_ptype - self.needs_count_in_params = needs_count_in_params self.preamble_ops = None self.sched_data = None + self.pack = None def is_vector_arg(self, i): if i < 0 or i >= len(self.arg_ptypes): @@ -760,17 +756,11 @@ return self.arg_ptypes[i] is not None def pack_ptype(self, op): - opnum = op.vector - args = op.getarglist() - result = op.result - if self.has_descr: - descr = op.getdescr() - return PackType.by_descr(descr, self.sched_data.vec_reg_size) - if self.arg_clone_ptype >= 0: - arg = args[self.arg_clone_ptype] - _, vbox = self.sched_data.box_to_vbox.get(arg, (-1, None)) - if vbox: - return PackType.of(vbox) + _, vbox = self.getvector_of_box(op.getarg(0)) + if vbox: + return PackType.of(vbox) + else: + raise RuntimeError("fatal: box %s is not in a vector box" % (arg,)) def as_vector_operation(self, pack, sched_data, oplist): self.sched_data = sched_data @@ -783,9 +773,11 @@ assert stride > 0 while off < len(pack.operations): ops = pack.operations[off:off+stride] + self.pack = Pack(ops) self.transform_pack(ops, off, stride) off += stride + self.pack = None self.preamble_ops = None self.sched_data = None self.ptype = None @@ -797,43 +789,47 @@ return vec_reg_size // self.ptype.getsize() return pack_count + def before_argument_transform(self, args): + pass + def transform_pack(self, ops, off, stride): - op = ops[0].getoperation() + op = self.pack.operations[0].getoperation() args = op.getarglist() - if self.needs_count_in_params: - args.append(ConstInt(len(ops))) + # + self.before_argument_transform(args) + # result = op.result - descr = op.getdescr() for i,arg in enumerate(args): if self.is_vector_arg(i): - args[i] = self.transform_argument(ops, args[i], i, off, stride) + args[i] = self.transform_argument(args[i], i, off) # - result = self.transform_result(ops, result, off) + result = self.transform_result(result, off) # - vop = ResOperation(op.vector, args, result, descr) + vop = ResOperation(op.vector, args, result, op.getdescr()) self.preamble_ops.append(vop) - def transform_result(self, ops, result, off): + 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(ops): + 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): size = self.ptype.getsize() - count = self.ptype.getcount() + count = min(self.ptype.getcount(), len(self.pack.operations)) return BoxVector(self.ptype.gettype(), count, size, self.ptype.signed) - def transform_argument(self, ops, arg, argidx, off, count): + 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.ptype.new_vector_box(count) + vbox = self.ptype.new_vector_box(len(ops)) vbox = self.expand_box_to_vector_box(vbox, ops, arg, argidx) box_pos = 0 @@ -1017,6 +1013,25 @@ count = vec_reg_size // self.size return BoxVector(self.result_ptype.gettype(), count, self.size, self.ptype.signed) +PT_GENERIC = PackType(PackType.UNKNOWN_TYPE, -1, False) + +class LoadToVectorLoad(OpToVectorOp): + def __init__(self): + OpToVectorOp.__init__(self, (), PT_GENERIC) + + def pack_ptype(self, op): + return PackType.by_descr(op.getdescr(), self.sched_data.vec_reg_size) + + def before_argument_transform(self, args): + args.append(ConstInt(len(self.pack.operations))) + +class StoreToVectorStore(OpToVectorOp): + def __init__(self): + OpToVectorOp.__init__(self, (None, None, PT_GENERIC), None) + self.has_descr = True + + def pack_ptype(self, op): + return PackType.by_descr(op.getdescr(), self.sched_data.vec_reg_size) PT_FLOAT = PackType(FLOAT, 4, False) PT_DOUBLE = PackType(FLOAT, 8, False) @@ -1024,15 +1039,16 @@ PT_INT64 = PackType(INT, 8, True) PT_INT32 = PackType(INT, 4, True) PT_INT_GENERIC = PackType(INT, -1, True) -PT_GENERIC = PackType(PackType.UNKNOWN_TYPE, -1, True) +PT_GENERIC = PackType(PackType.UNKNOWN_TYPE, -1, False) INT_RES = PT_INT_GENERIC FLOAT_RES = PT_FLOAT_GENERIC -LOAD_RES = PT_GENERIC INT_OP_TO_VOP = OpToVectorOp((PT_INT_GENERIC, PT_INT_GENERIC), INT_RES) FLOAT_OP_TO_VOP = OpToVectorOp((PT_FLOAT_GENERIC, PT_FLOAT_GENERIC), FLOAT_RES) FLOAT_SINGLE_ARG_OP_TO_VOP = OpToVectorOp((PT_FLOAT_GENERIC,), FLOAT_RES) +LOAD_TRANS = LoadToVectorLoad() +STORE_TRANS = StoreToVectorStore() ROP_ARG_RES_VECTOR = { rop.VEC_INT_ADD: INT_OP_TO_VOP, @@ -1052,17 +1068,10 @@ rop.VEC_FLOAT_NEG: FLOAT_SINGLE_ARG_OP_TO_VOP, rop.VEC_FLOAT_EQ: OpToVectorOp((PT_FLOAT_GENERIC,PT_FLOAT_GENERIC), INT_RES), - rop.VEC_RAW_LOAD: OpToVectorOp((), LOAD_RES, has_descr=True, - arg_clone_ptype=-2, - needs_count_in_params=True - ), - rop.VEC_GETARRAYITEM_RAW: OpToVectorOp((), LOAD_RES, - has_descr=True, - arg_clone_ptype=-2, - needs_count_in_params=True - ), - rop.VEC_RAW_STORE: OpToVectorOp((None,None,PT_GENERIC,), None, has_descr=True, arg_clone_ptype=2), - rop.VEC_SETARRAYITEM_RAW: OpToVectorOp((None,None,PT_GENERIC,), None, has_descr=True, arg_clone_ptype=2), + rop.VEC_RAW_LOAD: LOAD_TRANS, + rop.VEC_GETARRAYITEM_RAW: LOAD_TRANS, + rop.VEC_RAW_STORE: STORE_TRANS, + rop.VEC_SETARRAYITEM_RAW: STORE_TRANS, rop.VEC_CAST_FLOAT_TO_SINGLEFLOAT: OpToVectorOpConv(PT_DOUBLE, PT_FLOAT), rop.VEC_CAST_SINGLEFLOAT_TO_FLOAT: OpToVectorOpConv(PT_FLOAT, PT_DOUBLE), diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py --- a/rpython/jit/tool/oparser.py +++ b/rpython/jit/tool/oparser.py @@ -3,6 +3,8 @@ in a nicer fashion """ +import re + from rpython.jit.tool.oparser_model import get_model from rpython.jit.metainterp.resoperation import rop, ResOperation, \ @@ -121,8 +123,20 @@ box = ts.BoxRef() _box_counter_more_than(self.model, elem[1:]) elif elem.startswith('v'): - box = self.model.BoxVector() - _box_counter_more_than(self.model, elem[1:]) + pattern = re.compile('.*\[(-?)(i|f)(\d+)#(\d+)\]') + match = pattern.match(elem) + if match: + item_type = match.group(2)[0] + item_size = int(match.group(3)) // 8 + item_count = int(match.group(4)) + item_signed = match.group(1) == 's' + box = self.model.BoxVector(item_type, item_count, item_size, item_signed) + lbracket = elem.find('[') + number = elem[1:lbracket] + else: + box = self.model.BoxVector() + number = elem[1:] + _box_counter_more_than(self.model, number) else: for prefix, boxclass in self.boxkinds.iteritems(): if elem.startswith(prefix): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit