Author: Richard Plangger <planri...@gmail.com> Branch: vecopt-merge Changeset: r79644:b57463d82b50 Date: 2015-09-15 12:49 +0200 http://bitbucket.org/pypy/pypy/changeset/b57463d82b50/
Log: input arg bytesize default to the hardware offered precision (word size) 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 @@ -19,6 +19,7 @@ def post_schedule(self): loop = self.graph.loop self.renamer.rename(loop.jump) + loop.operations = self.oplist def profitable(self): return self.costmodel.profitable() @@ -93,7 +94,7 @@ node.clear_dependencies() node.emitted = True - def walk_and_emit(self, state): # TODO oplist, renamer, unpack=False): + def walk_and_emit(self, state): """ Emit all the operations into the oplist parameter. Initiates the scheduling. """ assert isinstance(state, SchedulerState) @@ -515,9 +516,6 @@ #assert vecop is not None #args[i] = vecop -def before_argument_transform(self, args): - pass - def check_if_pack_supported(self, pack): op0 = pack.operations[0].getoperation() if self.input_type is None: @@ -534,90 +532,6 @@ # see assembler for comment why raise NotAProfitableLoop -#def transform_result(self, result): -# 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.getoperations()): -# if i >= vbox.getcount(): -# break -# op = node.getoperation() -# self.sched_data.setvector_of_box(op, 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 getoperations(self): -# return self.pack.operations - -#def transform_arguments(self, args): -# """ Transforming one argument to a vector box argument -# The following cases can occur: -# 1) argument is present in the box_to_vbox map. -# a) vector can be reused immediatly (simple case) -# b) vector is to big -# c) vector is to small -# 2) argument is not known to reside in a vector -# a) expand vars/consts before the label and add as argument -# b) expand vars created in the loop body -# """ -# for i,arg in enumerate(args): -# if arg.returns_vector(): -# continue -# if not self.is_vector_arg(i): -# continue -# box_pos, vbox = self.sched_data.getvector_of_box(arg) -# if not vbox: -# # constant/variable expand this box -# vbox = self.expand(arg, i) -# self.sched_data.setvector_of_box(arg, 0, vbox) -# box_pos = 0 -# # 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) - -# # use the input as an indicator for the pack type -# packable = self.input_type.getcount() -# packed = vbox.getcount() -# assert packed >= 0 -# assert packable >= 0 -# if packed > packable: -# # the argument has more items than the operation is able to process! -# # box_pos == 0 then it is already at the right place -# if box_pos != 0: -# args[i] = self.unpack(vbox, box_pos, packed - box_pos, self.input_type) -# self.update_arg_in_vector_pos(i, args[i]) -# #self.update_input_output(self.pack) -# continue -# else: -# assert vbox is not None -# args[i] = vbox -# continue -# vboxes = self.vector_boxes_for_args(i) -# if packed < packable and len(vboxes) > 1: -# # the argument is scattered along different vector boxes -# args[i] = self.gather(vboxes, packable) -# self.update_arg_in_vector_pos(i, args[i]) -# continue -# if box_pos != 0: -# # The vector box is at a position != 0 but it -# # is required to be at position 0. Unpack it! -# args[i] = self.unpack(vbox, box_pos, packed - box_pos, self.input_type) -# self.update_arg_in_vector_pos(i, args[i]) -# continue -# #self.update_input_output(self.pack) -# # -# assert vbox is not None -# args[i] = vbox - def extend(self, vbox, newtype): assert vbox.gettype() == newtype.gettype() if vbox.gettype() == INT: @@ -734,154 +648,6 @@ variables.append(vecop) args[index] = vecop -class OpToVectorOp(object): - def __init__(self): #, restrictargs, typeoutput): - pass - #self.args = list(restrictargs) # do not use a tuple. rpython cannot union - #self.out = typeoutput - -class OpToVectorOpConv(OpToVectorOp): - def __init__(self, intype, outtype): - #self.from_size = intype.getsize() - #self.to_size = outtype.getsize() - #OpToVectorOp.__init__(self, (intype, ), outtype) - pass - - def new_result_vector_box(self): - type = self.output_type.gettype() - size = self.to_size - count = self.output_type.getcount() - vec_reg_size = self.sched_data.vec_reg_size - if count * size > vec_reg_size: - count = vec_reg_size // size - signed = self.output_type.signed - assert type in ('i','f') - assert size > 0 - assert count > 1 - return BoxVector(type, count, size, signed) - - def get_output_type_given(self, input_type, op): - return self.result_ptype - - def get_input_type_given(self, output_type, op): - return self.arg_ptypes[0] - - def force_input(self, ptype): - return self.arg_ptypes[0] - -class SignExtToVectorOp(OpToVectorOp): - def __init__(self, intype, outtype): - OpToVectorOp.__init__(self, intype, outtype) - self.size = -1 - - def before_argument_transform(self, args): - sizearg = args[1] - assert isinstance(sizearg, ConstInt) - self.size = sizearg.value - - def new_result_vector_box(self): - type = self.output_type.gettype() - count = self.input_type.getcount() - vec_reg_size = self.sched_data.vec_reg_size - if count * self.size > vec_reg_size: - count = vec_reg_size // self.size - signed = self.input_type.signed - assert type in ('i','f') - assert self.size > 0 - assert count > 1 - return BoxVector(type, count, self.size, signed) - - def get_output_type_given(self, input_type, op): - sizearg = op.getarg(1) - assert isinstance(sizearg, ConstInt) - output_type = input_type.clone() - output_type.setsize(sizearg.value) - return output_type - - def get_input_type_given(self, output_type, op): - raise AssertionError("can never infer input type!") - -class LoadToVectorLoad(OpToVectorOp): - def __init__(self): - OpToVectorOp.__init__(self, (), TypeRestrict()) - - # 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 xxx#Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size) - - def get_input_type_given(self, output_type, op): - return None - -class StoreToVectorStore(OpToVectorOp): - """ Storing operations are special because they are not allowed - to store to memory if the vector is not fully filled. - Thus a modified split_pack function. - """ - def __init__(self): - OpToVectorOp.__init__(self, (None, None, TypeRestrict()), None) - self.has_descr = True - - def must_be_full_but_is_not(self, pack): - vrs = self.sched_data.vec_reg_size - it = pack.input_type - return it.getsize() * it.getcount() < vrs - - def get_output_type_given(self, input_type, op): - return None - - def get_input_type_given(self, output_type, op): - 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 - operation is capable of handling vector operations. - Guard true/false is such an example. - """ - def __init__(self, args): - OpToVectorOp.__init__(self, args, None) - - def get_output_type_given(self, input_type, op): - return None - - def get_input_type_given(self, output_type, op): - raise AssertionError("cannot infer input type from output type") - - - -#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 -# the transformed packtype. -# -# Moving backward, the origins pack input type is the output -# type and the transformation of the packtype (in reverse direction) -# is the input -# """ -# op = node.getoperation() -# op2vecop = determine_trans(op) -# if forward: -# input_type = op2vecop.force_input(pack.output_type) -# output_type = op2vecop.get_output_type_given(input_type, op) -# if output_type: -# output_type = output_type.clone() -# else: -# # going backwards, things are not that easy anymore -# output_type = pack.input_type -# input_type = op2vecop.get_input_type_given(output_type, op) -# if input_type: -# input_type = input_type.clone() -# -# return input_type, output_type - -def determine_trans(op): - op2vecop = trans.MAPPING.get(op.vector, None) - if op2vecop is None: - raise NotImplementedError("missing vecop for '%s'" % (op.getopname(),)) - return op2vecop - class VecScheduleState(SchedulerState): def __init__(self, graph, packset, cpu, costmodel): SchedulerState.__init__(self, graph) @@ -903,8 +669,6 @@ 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) @@ -945,7 +709,6 @@ assert node.pack.numops() > 1 for node in node.pack.operations: scheduler.mark_emitted(node, self) - # TODO op2vecop = determine_trans(node.pack.leftmost()) turn_to_vector(self, node.pack) return True return False @@ -1219,3 +982,239 @@ self.left = left self.right = right self.accum = accum + +#class OpToVectorOp(object): +# def __init__(self): #, restrictargs, typeoutput): +# pass +# #self.args = list(restrictargs) # do not use a tuple. rpython cannot union +# #self.out = typeoutput +# +#class OpToVectorOpConv(OpToVectorOp): +# def __init__(self, intype, outtype): +# #self.from_size = intype.getsize() +# #self.to_size = outtype.getsize() +# #OpToVectorOp.__init__(self, (intype, ), outtype) +# pass +# +# def new_result_vector_box(self): +# type = self.output_type.gettype() +# size = self.to_size +# count = self.output_type.getcount() +# vec_reg_size = self.sched_data.vec_reg_size +# if count * size > vec_reg_size: +# count = vec_reg_size // size +# signed = self.output_type.signed +# assert type in ('i','f') +# assert size > 0 +# assert count > 1 +# return BoxVector(type, count, size, signed) +# +# def get_output_type_given(self, input_type, op): +# return self.result_ptype +# +# def get_input_type_given(self, output_type, op): +# return self.arg_ptypes[0] +# +# def force_input(self, ptype): +# return self.arg_ptypes[0] +# +#class SignExtToVectorOp(OpToVectorOp): +# def __init__(self, intype, outtype): +# OpToVectorOp.__init__(self, intype, outtype) +# self.size = -1 +# +# def before_argument_transform(self, args): +# sizearg = args[1] +# assert isinstance(sizearg, ConstInt) +# self.size = sizearg.value +# +# def new_result_vector_box(self): +# type = self.output_type.gettype() +# count = self.input_type.getcount() +# vec_reg_size = self.sched_data.vec_reg_size +# if count * self.size > vec_reg_size: +# count = vec_reg_size // self.size +# signed = self.input_type.signed +# assert type in ('i','f') +# assert self.size > 0 +# assert count > 1 +# return BoxVector(type, count, self.size, signed) +# +# def get_output_type_given(self, input_type, op): +# sizearg = op.getarg(1) +# assert isinstance(sizearg, ConstInt) +# output_type = input_type.clone() +# output_type.setsize(sizearg.value) +# return output_type +# +# def get_input_type_given(self, output_type, op): +# raise AssertionError("can never infer input type!") +# +#class LoadToVectorLoad(OpToVectorOp): +# def __init__(self): +# OpToVectorOp.__init__(self, (), TypeRestrict()) +# +# # 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 xxx#Type.by_descr(op.getdescr(), self.sched_data.vec_reg_size) +# +# def get_input_type_given(self, output_type, op): +# return None +# +#class StoreToVectorStore(OpToVectorOp): +# """ Storing operations are special because they are not allowed +# to store to memory if the vector is not fully filled. +# Thus a modified split_pack function. +# """ +# def __init__(self): +# OpToVectorOp.__init__(self, (None, None, TypeRestrict()), None) +# self.has_descr = True +# +# def must_be_full_but_is_not(self, pack): +# vrs = self.sched_data.vec_reg_size +# it = pack.input_type +# return it.getsize() * it.getcount() < vrs +# +# def get_output_type_given(self, input_type, op): +# return None +# +# def get_input_type_given(self, output_type, op): +# 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 +# operation is capable of handling vector operations. +# Guard true/false is such an example. +# """ +# def __init__(self, args): +# OpToVectorOp.__init__(self, args, None) +# +# def get_output_type_given(self, input_type, op): +# return None +# +# def get_input_type_given(self, output_type, op): +# raise AssertionError("cannot infer input type from output type") +# +# +# +##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 +## the transformed packtype. +## +## Moving backward, the origins pack input type is the output +## type and the transformation of the packtype (in reverse direction) +## is the input +## """ +## op = node.getoperation() +## op2vecop = determine_trans(op) +## if forward: +## input_type = op2vecop.force_input(pack.output_type) +## output_type = op2vecop.get_output_type_given(input_type, op) +## if output_type: +## output_type = output_type.clone() +## else: +## # going backwards, things are not that easy anymore +## output_type = pack.input_type +## input_type = op2vecop.get_input_type_given(output_type, op) +## if input_type: +## input_type = input_type.clone() +## +## return input_type, output_type +# +#def determine_trans(op): +# op2vecop = trans.MAPPING.get(op.vector, None) +# if op2vecop is None: +# raise NotImplementedError("missing vecop for '%s'" % (op.getopname(),)) +# return op2vecop + + +#def before_argument_transform(self, args): +# pass + +#def transform_result(self, result): +# 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.getoperations()): +# if i >= vbox.getcount(): +# break +# op = node.getoperation() +# self.sched_data.setvector_of_box(op, 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 getoperations(self): +# return self.pack.operations + +#def transform_arguments(self, args): +# """ Transforming one argument to a vector box argument +# The following cases can occur: +# 1) argument is present in the box_to_vbox map. +# a) vector can be reused immediatly (simple case) +# b) vector is to big +# c) vector is to small +# 2) argument is not known to reside in a vector +# a) expand vars/consts before the label and add as argument +# b) expand vars created in the loop body +# """ +# for i,arg in enumerate(args): +# if arg.returns_vector(): +# continue +# if not self.is_vector_arg(i): +# continue +# box_pos, vbox = self.sched_data.getvector_of_box(arg) +# if not vbox: +# # constant/variable expand this box +# vbox = self.expand(arg, i) +# self.sched_data.setvector_of_box(arg, 0, vbox) +# box_pos = 0 +# # 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) + +# # use the input as an indicator for the pack type +# packable = self.input_type.getcount() +# packed = vbox.getcount() +# assert packed >= 0 +# assert packable >= 0 +# if packed > packable: +# # the argument has more items than the operation is able to process! +# # box_pos == 0 then it is already at the right place +# if box_pos != 0: +# args[i] = self.unpack(vbox, box_pos, packed - box_pos, self.input_type) +# self.update_arg_in_vector_pos(i, args[i]) +# #self.update_input_output(self.pack) +# continue +# else: +# assert vbox is not None +# args[i] = vbox +# continue +# vboxes = self.vector_boxes_for_args(i) +# if packed < packable and len(vboxes) > 1: +# # the argument is scattered along different vector boxes +# args[i] = self.gather(vboxes, packable) +# self.update_arg_in_vector_pos(i, args[i]) +# continue +# if box_pos != 0: +# # The vector box is at a position != 0 but it +# # is required to be at position 0. Unpack it! +# args[i] = self.unpack(vbox, box_pos, packed - box_pos, self.input_type) +# self.update_arg_in_vector_pos(i, args[i]) +# continue +# #self.update_input_output(self.pack) +# # +# assert vbox is not None +# args[i] = vbox 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 @@ -226,12 +226,10 @@ i11 = int_signext(i1, 4) """, additional_args=['v10[2xi64]']) pack1 = self.pack(loop1, 0, 2) - var = self.find_input_arg('v10', loop1) - def i1inv103204(v): - return 0, var + var = loop1.inputargs[-1] loop2 = self.schedule(loop1, [pack1], prepend_invariant=True, overwrite_funcs = { - 'getvector_of_box': i1inv103204, + 'getvector_of_box': lambda v: (0, var), }) loop3 = self.parse_trace(""" v11[2xi32] = vec_int_signext(v10[2xi64], 4) 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 @@ -734,11 +734,15 @@ def __init__(self, intval=0): self.setint(intval) self.datatype = 'i' + self.bytesize = INT_WORD + self.signed = True class InputArgFloat(FloatOp, AbstractInputArg): def __init__(self, f=longlong.ZEROF): self.setfloatstorage(f) self.datatype = 'f' + self.bytesize = FLOAT_WORD + self.signed = True @staticmethod def fromfloat(x): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit