def isomorphic(l_op, r_op): """ Subject of definition, here it is equal operation. See limintations (vectorization.rst). """ if l_op.getopnum() == r_op.getopnum(): l_vecinfo = forwarded_vecinfo(l_op) r_vecinfo = forwarded_vecinfo(r_op) return l_vecinfo.bytesize == r_vecinfo.bytesize return False
def accumulates_pair(self, lnode, rnode, origin_pack): # lnode and rnode are isomorphic and dependent assert isinstance(origin_pack, Pair) left = lnode.getoperation() opnum = left.getopnum() try: operator = AccumPack.SUPPORTED(opnum) except KeyError: pass else: right = rnode.getoperation() assert left.numargs() == 2 and not left.returns_void() scalar, index = self.getaccumulator_variable( left, right, origin_pack) if not scalar: return None # the dependency exists only because of the left? for dep in lnode.provides(): if dep.to is rnode: if not dep.because_of(scalar): # not quite ... this is not handlable return None # get the original variable scalar = left.getarg(index) # in either of the two cases the arguments are mixed, # which is not handled currently other_index = (index + 1) % 2 if left.getarg(other_index) is not origin_pack.leftmost(): return None if right.getarg(other_index) is not origin_pack.rightmost(): return None # this can be handled by accumulation size = INT_WORD if left.type == 'f': size = FLOAT_WORD l_vecinfo = forwarded_vecinfo(left) r_vecinfo = forwarded_vecinfo(right) if not (l_vecinfo.bytesize == r_vecinfo.bytesize and l_vecinfo.bytesize == size): # do not support if if the type size is smaller # than the cpu word size. # WHY? # to ensure accum is done on the right size, the dependencies # of leading/preceding signext/floatcast instructions needs to be # considered. => tree pattern matching problem. return None return AccumPack([lnode, rnode], operator, index) is_guard = left.is_guard() and left.getopnum() in (rop.GUARD_TRUE, rop.GUARD_FALSE) if is_guard: return AccumPack([lnode, rnode], 'g', 0) return None
def accumulates_pair(self, lnode, rnode, origin_pack): # lnode and rnode are isomorphic and dependent assert isinstance(origin_pack, Pair) left = lnode.getoperation() opnum = left.getopnum() if opnum in AccumPack.SUPPORTED: right = rnode.getoperation() assert left.numargs() == 2 and not left.returns_void() scalar, index = self.getaccumulator_variable(left, right, origin_pack) if not scalar: return None # the dependency exists only because of the left? for dep in lnode.provides(): if dep.to is rnode: if not dep.because_of(scalar): # not quite ... this is not handlable return None # get the original variable scalar = left.getarg(index) # in either of the two cases the arguments are mixed, # which is not handled currently other_index = (index + 1) % 2 if left.getarg(other_index) is not origin_pack.leftmost(): return None if right.getarg(other_index) is not origin_pack.rightmost(): return None # this can be handled by accumulation size = INT_WORD if left.type == 'f': size = FLOAT_WORD l_vecinfo = forwarded_vecinfo(left) r_vecinfo = forwarded_vecinfo(right) if not (l_vecinfo.bytesize == r_vecinfo.bytesize and l_vecinfo.bytesize == size): # do not support if if the type size is smaller # than the cpu word size. # WHY? # to ensure accum is done on the right size, the dependencies # of leading/preceding signext/floatcast instructions needs to be # considered. => tree pattern matching problem. return None operator = AccumPack.SUPPORTED[opnum] return AccumPack([lnode, rnode], operator, index) is_guard = left.is_guard() and left.getopnum() in (rop.GUARD_TRUE, rop.GUARD_FALSE) if is_guard: return AccumPack([lnode, rnode], 'g', 0) return None
def check(self, value): vecinfo = forwarded_vecinfo(value) assert vecinfo.datatype != '\x00' if self.type != TypeRestrict.ANY_TYPE: if self.type != vecinfo.datatype: msg = "type mismatch %s != %s" % \ (self.type, vecinfo.datatype) failnbail_transformation(msg) assert vecinfo.bytesize > 0 if not self.any_size(): if self.bytesize != vecinfo.bytesize: msg = "bytesize mismatch %s != %s" % \ (self.bytesize, vecinfo.bytesize) failnbail_transformation(msg) assert vecinfo.count > 0 if self.count != TypeRestrict.ANY_COUNT: if vecinfo.count < self.count: msg = "count mismatch %s < %s" % \ (self.count, vecinfo.count) failnbail_transformation(msg) if self.sign != TypeRestrict.ANY_SIGN: if bool(self.sign) == vecinfo.sign: msg = "sign mismatch %s < %s" % \ (self.sign, vecinfo.sign) failnbail_transformation(msg)
def record_vector_pack(self, src, index, count): vecinfo = forwarded_vecinfo(src) if vecinfo.datatype == FLOAT: if index == 1 and count == 1: self.savings -= 2 return self.savings -= count
def opcount_filling_vector_register(self, op, vec_reg_size): """ How many operations of that kind can one execute with a machine instruction of register size X? """ if op.is_typecast(): if op.casts_down(): size = op.cast_input_bytesize(vec_reg_size) return size // op.cast_from_bytesize() else: return vec_reg_size // op.cast_to_bytesize() vecinfo = forwarded_vecinfo(op) return vec_reg_size // vecinfo.bytesize
def check_operation(self, state, pack, op): i = 0 infos = [forwarded_vecinfo(o) for o in op.getarglist()] arg0 = op.getarg(i) while arg0.is_constant() and i < op.numargs(): i += 1 arg0 = op.getarg(i) vecinfo = forwarded_vecinfo(arg0) bytesize = vecinfo.bytesize datatype = vecinfo.datatype for arg in op.getarglist(): if arg.is_constant(): continue curvecinfo = forwarded_vecinfo(arg) if curvecinfo.bytesize != bytesize: debug_print("op match size first type failed") raise NotAVectorizeableLoop if curvecinfo.datatype != datatype: debug_print("op match size first type failed (datatype)") raise NotAVectorizeableLoop return None
def must_crop_vector(self, op, index): restrict = self.argument_restrictions[index] vecinfo = forwarded_vecinfo(op.getarg(index)) size = vecinfo.bytesize newsize = self.crop_to_size(op, index) return not restrict.any_size() and newsize != size
def must_crop_vector(self, op, index): vecinfo = forwarded_vecinfo(op.getarg(index)) bytesize = vecinfo.bytesize return self.crop_to_size(op, index) != bytesize
def opcount_filling_vector_register(self, op, vec_reg_size): arg = op.getarg(0) vecinfo = forwarded_vecinfo(arg) return vec_reg_size // vecinfo.bytesize