def expand(state, pack, args, arg, index): """ Expand a value into a vector box. useful for arith metic of one vector with a scalar (either constant/varialbe) """ left = pack.leftmost() box_type = arg.type expanded_map = state.expanded_map ops = state.invariant_oplist variables = state.invariant_vector_vars if not arg.is_constant() and arg not in state.inputargs: # cannot be created before the loop, expand inline ops = state.oplist variables = None for i, node in enumerate(pack.operations): op = node.getoperation() if not arg.same_box(op.getarg(index)): break i += 1 else: # note that heterogenous nodes are not yet tracked vecop = state.find_expanded([arg]) if vecop: args[index] = vecop return vecop left = pack.leftmost() vecinfo = forwarded_vecinfo(left) vecop = OpHelpers.create_vec_expand(arg, vecinfo.bytesize, vecinfo.signed, pack.numops()) ops.append(vecop) if variables is not None: variables.append(vecop) state.expand([arg], vecop) args[index] = vecop return vecop # quick search if it has already been expanded expandargs = [op.getoperation().getarg(index) for op in pack.operations] vecop = state.find_expanded(expandargs) if vecop: args[index] = vecop return vecop arg_vecinfo = forwarded_vecinfo(arg) vecop = OpHelpers.create_vec(arg.type, arg_vecinfo.bytesize, arg_vecinfo.signed, pack.opnum()) ops.append(vecop) for i,node in enumerate(pack.operations): op = node.getoperation() arg = op.getarg(index) arguments = [vecop, arg, ConstInt(i), ConstInt(1)] vecinfo = forwarded_vecinfo(vecop) vecop = OpHelpers.create_vec_pack(arg.type, arguments, vecinfo.bytesize, vecinfo.signed, vecinfo.count+1) ops.append(vecop) state.expand(expandargs, vecop) if variables is not None: variables.append(vecop) args[index] = vecop
def pack_into_vector(state, tgt, tidx, src, sidx, scount): """ tgt = [1,2,3,4,_,_,_,_] src = [5,6,_,_] new_box = [1,2,3,4,5,6,_,_] after the operation, tidx=4, scount=2 """ assert sidx == 0 # restriction newcount = tgt.count + scount args = [tgt, src, ConstInt(tidx), ConstInt(scount)] vecop = OpHelpers.create_vec_pack(tgt.type, args, tgt.bytesize, tgt.signed, newcount) state.oplist.append(vecop) state.costmodel.record_vector_pack(src, sidx, scount) if not we_are_translated(): _check_vec_pack(vecop) return vecop
def accumulate_prepare(self, state): vec_reg_size = state.vec_reg_size for pack in self.packs: if not pack.is_accumulating(): continue if pack.leftmost().is_guard(): # guard breaks dependencies, thus it is an accumulation pack continue for i,node in enumerate(pack.operations): op = node.getoperation() state.accumulation[op] = pack assert isinstance(pack, AccumPack) datatype = pack.getdatatype() bytesize = pack.getbytesize() count = vec_reg_size // bytesize signed = datatype == 'i' oplist = state.invariant_oplist # reset the box to zeros or ones if pack.reduce_init() == 0: vecop = OpHelpers.create_vec(datatype, bytesize, signed, count) oplist.append(vecop) opnum = rop.VEC_INT_XOR if datatype == FLOAT: # see PRECISION loss below raise NotImplementedError vecop = VecOperation(opnum, [vecop, vecop], vecop, count) oplist.append(vecop) elif pack.reduce_init() == 1: # PRECISION loss, because the numbers are accumulated (associative, commutative properties must hold) # you can end up a small number and a huge number that is finally multiplied. giving an # inprecision result, thus this is disabled now raise NotImplementedError # multiply is only supported by floats vecop = OpHelpers.create_vec_expand(ConstFloat(1.0), bytesize, signed, count) oplist.append(vecop) else: raise NotImplementedError("cannot handle %s" % pack.operator) # pack the scalar value 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(seed, 0, vecop) # prevent it from expansion state.renamer.start_renaming(seed, vecop)
def pack_into_vector(state, tgt, tidx, src, sidx, scount): """ tgt = [1,2,3,4,_,_,_,_] src = [5,6,_,_] new_box = [1,2,3,4,5,6,_,_] after the operation, tidx=4, scount=2 """ assert sidx == 0 # restriction vecinfo = forwarded_vecinfo(tgt) newcount = vecinfo.count + scount args = [tgt, src, ConstInt(tidx), ConstInt(scount)] vecop = OpHelpers.create_vec_pack(tgt.type, args, vecinfo.bytesize, vecinfo.signed, newcount) state.oplist.append(vecop) state.costmodel.record_vector_pack(src, sidx, scount) if not we_are_translated(): _check_vec_pack(vecop) return vecop
def accumulate_prepare(self, state): vec_reg_size = state.vec_reg_size for pack in self.packs: if not pack.is_accumulating(): continue if pack.leftmost().is_guard(): # guard breaks dependencies, thus it is an accumulation pack continue for i,node in enumerate(pack.operations): op = node.getoperation() state.accumulation[op] = pack assert isinstance(pack, AccumPack) datatype = pack.getdatatype() bytesize = pack.getbytesize() count = vec_reg_size // bytesize signed = datatype == 'i' oplist = state.invariant_oplist # reset the box to zeros or ones if pack.reduce_init() == 0: vecop = OpHelpers.create_vec(datatype, bytesize, signed, count) oplist.append(vecop) vecop = VecOperation(rop.VEC_INT_XOR, [vecop, vecop], vecop, count) oplist.append(vecop) elif pack.reduce_init() == 1: # multiply is only supported by floats vecop = OpHelpers.create_vec_expand(ConstFloat(1.0), bytesize, signed, count) oplist.append(vecop) else: raise NotImplementedError("cannot handle %s" % pack.operator) # pack the scalar value 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(seed, 0, vecop) # prevent it from expansion state.renamer.start_renaming(seed, vecop)