Author: Richard Plangger <planri...@gmail.com> Branch: vecopt-merge Changeset: r79808:ed1cb45ccbd1 Date: 2015-09-24 12:53 +0200 http://bitbucket.org/pypy/pypy/changeset/ed1cb45ccbd1/
Log: only one test for llgraph failing diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -799,8 +799,8 @@ # vector operations vector_arith_code = """ - def bh_vec_{0}_{1}(self, vx, vy): - assert len(vx) == len(vy) + def bh_vec_{0}_{1}(self, vx, vy, count): + assert len(vx) == len(vy) == count return [_vx {2} _vy for _vx,_vy in zip(vx,vy)] """ exec py.code.Source(vector_arith_code.format('int','add','+')).compile() @@ -812,59 +812,66 @@ exec py.code.Source(vector_arith_code.format('float','truediv','/')).compile() exec py.code.Source(vector_arith_code.format('float','eq','==')).compile() - def bh_vec_float_neg(self, vx): + def bh_vec_float_neg(self, vx, count): return [e * -1 for e in vx] - def bh_vec_float_abs(self, vx): + def bh_vec_float_abs(self, vx, count): return [abs(e) for e in vx] - def bh_vec_float_eq(self, vx, vy): - assert len(vx) == len(vy) + def bh_vec_float_eq(self, vx, vy, count): + assert len(vx) == len(vy) == count return [_vx == _vy for _vx,_vy in zip(vx,vy)] - def bh_vec_float_ne(self, vx, vy): - assert len(vx) == len(vy) + def bh_vec_float_ne(self, vx, vy, count): + assert len(vx) == len(vy) == count return [_vx != _vy for _vx,_vy in zip(vx,vy)] bh_vec_int_eq = bh_vec_float_eq bh_vec_int_ne = bh_vec_float_ne - def bh_vec_int_xor(self, vx, vy): + def bh_vec_int_xor(self, vx, vy, count): return [int(x) ^ int(y) for x,y in zip(vx,vy)] - def bh_vec_float_pack(self, vector, value, index, count): - if isinstance(value, list): - for i in range(count): - vector[index + i] = value[i] - else: - vector[index] = value - return vector - - def bh_vec_cast_float_to_singlefloat(self, vx): + def bh_vec_cast_float_to_singlefloat(self, vx, count): return vx - def bh_vec_box(self, size): - return [0] * size + def bh_vec_f(self, count): + return [0.0] * count - def bh_vec_box_pack(self, vx, index, y): - vx[index] = y + def bh_vec_i(self, count): + return [0] * count - def bh_vec_box_unpack(self, vx, index): - return vx[index] + def _bh_vec_pack(self, tv, sv, index, count, _): + if not isinstance(sv, list): + tv[index] = sv + return tv + for i in range(count): + tv[index+i] = sv[i] + return tv - def bh_vec_float_expand(self, x, count): + bh_vec_pack_f = _bh_vec_pack + bh_vec_pack_i = _bh_vec_pack + + def _bh_vec_unpack(self, vx, index, count): + return vx[index:index+count] + + bh_vec_unpack_f = _bh_vec_unpack + bh_vec_unpack_i = _bh_vec_unpack + + def _bh_vec_expand(self, x, count): return [x] * count - def bh_vec_int_expand(self, x, count): - return [x] * count + bh_vec_expand_f = _bh_vec_expand + bh_vec_expand_i = _bh_vec_expand - def bh_vec_int_signext(self, vx, ext): + def bh_vec_int_signext(self, vx, ext, count): return [heaptracker.int_signext(_vx, ext) for _vx in vx] def build_getarrayitem(func): - def method(self, struct, offset, descr): + def method(self, struct, offset, descr, _count): values = [] count = self.vector_register_size // descr.get_item_size_in_bytes() + assert _count == count assert count > 0 for i in range(count): val = func(self, struct, offset + i, descr) @@ -878,10 +885,11 @@ bh_vec_getarrayitem_raw_f = build_getarrayitem(bh_getarrayitem_raw) del build_getarrayitem - def _bh_vec_raw_load(self, struct, offset, descr): + def _bh_vec_raw_load(self, struct, offset, descr, _count): values = [] stride = descr.get_item_size_in_bytes() count = self.vector_register_size // descr.get_item_size_in_bytes() + assert _count == count assert count > 0 for i in range(count): val = self.bh_raw_load(struct, offset + i*stride, descr) @@ -891,16 +899,16 @@ bh_vec_raw_load_i = _bh_vec_raw_load bh_vec_raw_load_f = _bh_vec_raw_load - def bh_vec_raw_store(self, struct, offset, newvalues, descr): + def bh_vec_raw_store(self, struct, offset, newvalues, descr, count): stride = descr.get_item_size_in_bytes() for i,n in enumerate(newvalues): self.bh_raw_store(struct, offset + i*stride, n, descr) - def bh_vec_setarrayitem_raw(self, struct, offset, newvalues, descr): + def bh_vec_setarrayitem_raw(self, struct, offset, newvalues, descr, count): for i,n in enumerate(newvalues): self.bh_setarrayitem_raw(struct, offset + i, n, descr) - def bh_vec_setarrayitem_gc(self, struct, offset, newvalues, descr): + def bh_vec_setarrayitem_gc(self, struct, offset, newvalues, descr, count): for i,n in enumerate(newvalues): self.bh_setarrayitem_gc(struct, offset + i, n, descr) @@ -1026,9 +1034,9 @@ i = accuminfo.getpos_in_failargs() value = values[i] assert isinstance(value, list) - if accum.operator == '+': + if accuminfo.accum_operation == '+': value = sum(value) - elif accum.operator == '*': + elif accuminfo.accum_operation == '*': def prod(acc, x): return acc * x value = reduce(prod, value, 1) else: @@ -1404,6 +1412,10 @@ new_args = args + (descr,) else: new_args = args + if opname.startswith('vec_'): + count = self.current_op.count + assert count > 1 + new_args = new_args + (count,) return getattr(self.cpu, 'bh_' + opname)(*new_args) execute.func_name = 'execute_' + opname return execute diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py --- a/rpython/jit/metainterp/logger.py +++ b/rpython/jit/metainterp/logger.py @@ -134,6 +134,9 @@ return str(arg.getfloatstorage()) elif arg is None: return 'None' + elif arg.is_vector(): + suffix = '[%dx%s%d]' % (arg.count, arg.datatype, arg.bytesize * 8) + return 'v' + str(mv) + suffix elif arg.type == 'i': return 'i' + str(mv) elif arg.type == 'r': 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 @@ -149,10 +149,6 @@ assert operations[self.index] is self.op operations[self.index] = None descr = self.op.getdescr() - # TODO loop.version_info.remove(descr) - #if descr and descr.loop_version(): - # assert isinstance(descr, CompileLoopVersionDescr) - # descr.version = None if operations[self.index-1] is self.cmp_op: operations[self.index-1] = None 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 @@ -28,12 +28,18 @@ loop.operations = self.oplist loop.prefix = self.invariant_oplist if len(self.invariant_vector_vars) + len(self.invariant_oplist) > 0: + # label args = loop.label.getarglist_copy() + self.invariant_vector_vars opnum = loop.label.getopnum() - # TODO descr? op = loop.label.copy_and_change(opnum, args) self.renamer.rename(op) loop.prefix_label = op + # jump + args = loop.jump.getarglist_copy() + self.invariant_vector_vars + opnum = loop.jump.getopnum() + op = loop.jump.copy_and_change(opnum, args) + self.renamer.rename(op) + loop.jump = op def profitable(self): return True @@ -56,9 +62,11 @@ def ensure_args_unpacked(self, op): pass - def post_emit(self, op): + def post_emit(self, node): pass + def pre_emit(self, node): + pass class Scheduler(object): """ Create an instance of this class to (re)schedule a vector trace. """ @@ -123,7 +131,7 @@ state.renamer.rename(op) if unpack: state.ensure_args_unpacked(op) - state.post_emit(node.getoperation()) + state.post_emit(node) def walk_and_emit(self, state): """ Emit all the operations into the oplist parameter. @@ -134,6 +142,7 @@ if node: if not state.emit(node, self): if not node.emitted: + state.pre_emit(node) self.mark_emitted(node, state) if not node.is_imaginary(): op = node.getoperation() @@ -259,6 +268,8 @@ for i,node in enumerate(pack.operations): op = node.getoperation() state.setvector_of_box(op,i,vecop) + if pack.is_accumulating(): + state.renamer.start_renaming(op, vecop) if op.is_guard(): assert isinstance(op, GuardResOp) assert isinstance(vecop, GuardResOp) @@ -452,7 +463,8 @@ args[index] = vecop return vecop - vecop = OpHelpers.create_vec(arg.type, arg.bytesize, arg.signed) + + vecop = OpHelpers.create_vec(arg.type, arg.bytesize, arg.signed, pack.opnum()) ops.append(vecop) for i,node in enumerate(pack.operations): op = node.getoperation() @@ -519,7 +531,11 @@ return vecop return None - def post_emit(self, op): + def post_emit(self, node): + pass + + def pre_emit(self, node): + op = node.getoperation() if op.is_guard(): # add accumulation info to the descriptor # TODO for version in self.loop.versions: @@ -536,8 +552,9 @@ accum = self.accumulation.get(arg, None) if accum: assert isinstance(accum, AccumPack) - accum.attach_accum_info(descr, i, arg) - seed = accum.getseed() + descr.rd_accum_list = AccumInfo(descr.rd_accum_list, i, + accum.operator, arg, None) + seed = accum.getleftmostseed() failargs[i] = self.renamer.rename_map.get(seed, seed) def profitable(self): @@ -556,6 +573,7 @@ if node.pack: assert node.pack.numops() > 1 for node in node.pack.operations: + self.pre_emit(node) scheduler.mark_emitted(node, self, unpack=False) turn_into_vector(self, node.pack) return True @@ -593,6 +611,7 @@ if argument and not argument.is_constant(): arg = self.ensure_unpacked(i, argument) if argument is not arg: + print "exchange at", i, fail_args[i], "=", arg fail_args[i] = arg def ensure_unpacked(self, index, arg): @@ -603,7 +622,7 @@ if var in self.invariant_vector_vars: return arg if arg in self.accumulation: - return var + return arg args = [var, ConstInt(pos), ConstInt(1)] vecop = OpHelpers.create_vec_unpack(var.type, args, var.bytesize, var.signed, 1) @@ -844,35 +863,34 @@ rop.FLOAT_MUL: '*', } - def __init__(self, nodes, operator, accum, position): + def __init__(self, nodes, operator, position): Pack.__init__(self, nodes) - self.accumulator = accum self.operator = operator self.position = position def getdatatype(self): - return self.accumulator.datatype + accum = self.leftmost().getarg(self.position) + return accum.datatype def getbytesize(self): - return self.accumulator.bytesize + accum = self.leftmost().getarg(self.position) + return accum.bytesize - def getseed(self): + def getleftmostseed(self): + return self.leftmost().getarg(self.position) + + def getseeds(self): """ The accumulatoriable holding the seed value """ - return self.accumulator + return [op.getoperation().getarg(self.position) for op in self.operations] def reduce_init(self): if self.operator == '*': return 1 return 0 - def attach_accum_info(self, descr, position, scalar): - descr.rd_accum_list = AccumInfo(descr.rd_accum_list, position, self.operator, - scalar, None) - def is_accumulating(self): return True def clone(self): - return AccumPack(operations, self.operator, - self.accumulator, self.position) + return AccumPack(operations, self.operator, self.position) 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 @@ -81,11 +81,11 @@ def optimize_vector(metainterp_sd, jitdriver_sd, warmstate, loop_info, loop_ops): """ Enter the world of SIMD. Bails if it cannot transform the trace. """ user_code = not jitdriver_sd.vec and warmstate.vec_all + loop = VectorLoop(loop_info.label_op, loop_ops[1:-1], loop_ops[-1]) if user_code and user_loop_bail_fast_path(loop, warmstate): return # the original loop (output of optimize_unroll) info = LoopVersionInfo(loop_info) - loop = VectorLoop(loop_info.label_op, loop_ops[1:-1], loop_ops[-1]) version = info.snapshot(loop) try: debug_start("vec-opt-loop") @@ -134,7 +134,6 @@ resop_count = 0 # the count of operations minus debug_merge_points vector_instr = 0 guard_count = 0 - blacklist = (rop.CALL, rop.CALL_ASSEMBLER) at_least_one_array_access = True for i,op in enumerate(loop.operations): if op.getopnum() == rop.DEBUG_MERGE_POINT: @@ -149,7 +148,8 @@ at_least_one_array_access = True if warmstate.vec_ratio > 0.0: - if op.getopnum() in blacklist: + # blacklist + if op.is_call() or op.is_call_assembler(): return True if op.is_guard(): @@ -744,7 +744,7 @@ # considered. => tree pattern matching problem. return None operator = AccumPack.SUPPORTED[opnum] - return AccumPack([lnode, rnode], operator, scalar, index) + return AccumPack([lnode, rnode], operator, index) return None @@ -770,7 +770,7 @@ oplist = state.invariant_oplist # reset the box to zeros or ones if pack.reduce_init() == 0: - vecop = OpHelpers.create_vec(datatype, bytesize, signed) + vecop = OpHelpers.create_vec(datatype, bytesize, signed, count) oplist.append(vecop) vecop = VecOperation(rop.VEC_INT_XOR, [vecop, vecop], vecop, count) @@ -783,14 +783,15 @@ else: raise NotImplementedError("cannot handle %s" % pack.operator) # pack the scalar value - args = [vecop, pack.getseed(), ConstInt(0), ConstInt(1)] + args = [vecop, pack.getleftmostseed(), ConstInt(0), ConstInt(1)] vecop = OpHelpers.create_vec_pack(datatype, args, bytesize, signed, count) oplist.append(vecop) + seed = pack.getleftmostseed() + state.accumulation[seed] = pack # rename the variable with the box - state.setvector_of_box(pack.getseed(), 0, vecop) # prevent it from expansion - state.renamer.start_renaming(pack.getseed(), vecop) - + state.setvector_of_box(seed, 0, vecop) # prevent it from expansion + state.renamer.start_renaming(seed, vecop) def split_overloaded_packs(self): newpacks = [] 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 @@ -146,6 +146,10 @@ else: # pass through the type of the first input argument if self.numargs() == 0: + if self.type == 'i': + self.setdatatype('i', INT_WORD, True) + elif self.type == 'f': + self.setdatatype('f', FLOAT_WORD, False) return i = 0 arg = self.getarg(i) @@ -280,6 +284,9 @@ if descr is DONT_CHANGE: descr = None newop = ResOperation(opnum, args, descr) + newop.count = self.count + newop.bytesize = self.bytesize + newop.signed = self.signed if self.type != 'v': newop.copy_value_from(self) return newop @@ -1602,13 +1609,13 @@ return VecOperationNew(opnum, [arg], arg.type, bytesize, signed, count) @staticmethod - def create_vec(datatype, bytesize, signed): + def create_vec(datatype, bytesize, signed, count): if datatype == 'i': opnum = rop.VEC_I else: assert datatype == 'f' opnum = rop.VEC_F - return VecOperationNew(opnum, [], datatype, bytesize, signed, 0) + return VecOperationNew(opnum, [], datatype, bytesize, signed, count) @staticmethod def create_vec_pack(datatype, args, bytesize, signed, count): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit