[pypy-commit] pypy vecopt: enhanced test env to check schedule operation
plan_rich
noreply at buildbot.pypy.org
Tue May 26 16:56:41 CEST 2015
Author: Richard Plangger <rich at 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):
More information about the pypy-commit
mailing list