def test_index_var_basic(self): b = FakeBox() i = IndexVar(b,1,1,0) j = IndexVar(b,1,1,0) assert i.is_identity() assert i.same_variable(j) assert i.constant_diff(j) == 0
def __init__(self, index, op, cmp_op, index_vars): self.index = index self.op = op self.cmp_op = cmp_op lhs = cmp_op.getarg(0) self.lhs = index_vars.get(lhs, None) if self.lhs is None: self.lhs = IndexVar(lhs) # rhs = cmp_op.getarg(1) self.rhs = index_vars.get(rhs, None) if self.rhs is None: self.rhs = IndexVar(rhs)
def test_index_var_diff(self): b = FakeBox() i = IndexVar(b, 4, 2, 0) j = IndexVar(b, 1, 1, 1) assert not i.is_identity() assert not j.is_identity() assert not i.same_mulfactor(j) assert i.constant_diff(j) == -1
def memoryref(array, var, mod=(1,1,0), descr=None, raw=False): if descr is None: descr = FLOAT mul, div, off = mod op = FakeMemoryRefResOp(array, descr) return MemoryRef(op, IndexVar(var, mul, div, off), raw)
def test_index_var_basic(self): b = FakeBox() i = IndexVar(b, 1, 1, 0) j = IndexVar(b, 1, 1, 0) assert i.is_identity() assert i.same_variable(j) assert i.constant_diff(j) == 0
def test_index_var_diff(self): b = FakeBox() i = IndexVar(b,4,2,0) j = IndexVar(b,1,1,1) assert not i.is_identity() assert not j.is_identity() assert not i.same_mulfactor(j) assert i.constant_diff(j) == -1
def iv(value, coeff=(1, 1, 0)): var = IndexVar(value) var.coefficient_mul = coeff[0] var.coefficient_div = coeff[1] var.constant = coeff[2] return var
class Guard(object): """ An object wrapper around a guard. Helps to determine if one guard implies another """ _attrs_ = ('index', 'op', 'cmp_op', 'rhs', 'lhs') def __init__(self, index, op, cmp_op, index_vars): self.index = index self.op = op self.cmp_op = cmp_op lhs = cmp_op.getarg(0) self.lhs = index_vars.get(lhs, None) if self.lhs is None: self.lhs = IndexVar(lhs) # rhs = cmp_op.getarg(1) self.rhs = index_vars.get(rhs, None) if self.rhs is None: self.rhs = IndexVar(rhs) def setindex(self, index): self.index = index def setoperation(self, op): self.op = op def setcmp(self, c): self.cmp_op = c def getleftkey(self): return self.lhs.getvariable() def getrightkey(self): return self.rhs.getvariable() def implies(self, guard, opt=None): if self.op.getopnum() != guard.op.getopnum(): return False if self.getleftkey() is guard.getleftkey(): # same operation valid, lc = self.lhs.compare(guard.lhs) if not valid: return False valid, rc = self.rhs.compare(guard.rhs) if not valid: return False opnum = self.get_compare_opnum() if opnum == -1: return False # x < y = -1,-2,... # x == y = 0 # x > y = 1,2,... if opnum in (rop.INT_LE, rop.INT_LT): return (lc >= 0 and rc <= 0) if opnum in (rop.INT_GE, rop.INT_GT): return (lc <= 0 and rc >= 0) return False def transitive_imply(self, other, opt, loop): if self.op.getopnum() != other.op.getopnum(): # stronger restriction, intermixing e.g. <= and < would be possible return None if self.getleftkey() is not other.getleftkey(): return None if not self.rhs.is_identity(): # stronger restriction return None # this is a valid transitive guard that eliminates the loop guard opnum = self.transitive_cmpop(self.cmp_op.getopnum()) box_rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) other_rhs = self.emit_varops(opt, other.rhs, other.cmp_op.getarg(1)) compare = ResOperation(opnum, [box_rhs, other_rhs]) opt.emit_operation(compare) # guard descr = CompileLoopVersionDescr() descr.copy_all_attributes_from(self.op.getdescr()) descr.rd_vector_info = None # do not copy the accum list assert isinstance(descr, AbstractFailDescr) guard = ResOperation(self.op.getopnum(), [compare], descr=descr) guard.setfailargs(loop.label.getarglist_copy()) opt.emit_operation(guard) return guard def transitive_cmpop(self, opnum): if opnum == rop.INT_LT: return rop.INT_LE if opnum == rop.INT_GT: return rop.INT_GE return opnum def get_compare_opnum(self): opnum = self.op.getopnum() if opnum == rop.GUARD_TRUE: return self.cmp_op.getopnum() else: return self.cmp_op.boolinverse def inhert_attributes(self, other): myop = self.op otherop = other.op assert isinstance(otherop, GuardResOp) assert isinstance(myop, GuardResOp) self.index = other.index descr = myop.getdescr() descr.copy_all_attributes_from(other.op.getdescr()) myop.rd_frame_info_list = otherop.rd_frame_info_list myop.setfailargs(otherop.getfailargs()[:]) myop.rd_snapshot = otherop.rd_snapshot def emit_varops(self, opt, var, old_arg): assert isinstance(var, IndexVar) if var.is_identity(): return var.var box = var.emit_operations(opt) opt.renamer.start_renaming(old_arg, box) return box def emit_operations(self, opt): # create trace instructions for the index lhs = self.emit_varops(opt, self.lhs, self.cmp_op.getarg(0)) rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) opnum = self.cmp_op.getopnum() cmp_op = ResOperation(opnum, [lhs, rhs]) opt.emit_operation(cmp_op) # emit that actual guard guard = ResOperation(self.op.getopnum(), [cmp_op], self.op.getdescr()) guard.setfailargs(self.op.getfailargs()[:]) opt.emit_operation(guard) self.setindex(opt.operation_position()-1) self.setoperation(guard) self.setcmp(cmp_op) def set_to_none(self, info, loop): operations = loop.operations assert operations[self.index] is self.op operations[self.index] = None descr = self.op.getdescr() if operations[self.index-1] is self.cmp_op: operations[self.index-1] = None @staticmethod def of(boolarg, operations, index, index_vars): guard_op = operations[index] cmp_op = guard_op.getarg(0) if not (rop.INT_LT <= cmp_op.getopnum() <= rop.INT_GE): return None return Guard(index, guard_op, cmp_op, index_vars)
class Guard(object): """ An object wrapper around a guard. Helps to determine if one guard implies another """ _attrs_ = ('index', 'op', 'cmp_op', 'rhs', 'lhs') def __init__(self, index, op, cmp_op, index_vars): self.index = index self.op = op self.cmp_op = cmp_op lhs = cmp_op.getarg(0) self.lhs = index_vars.get(lhs, None) if self.lhs is None: self.lhs = IndexVar(lhs) # rhs = cmp_op.getarg(1) self.rhs = index_vars.get(rhs, None) if self.rhs is None: self.rhs = IndexVar(rhs) def setindex(self, index): self.index = index def setoperation(self, op): self.op = op def setcmp(self, c): self.cmp_op = c def getleftkey(self): return self.lhs.getvariable() def getrightkey(self): return self.rhs.getvariable() def implies(self, guard, opt=None): if self.op.getopnum() != guard.op.getopnum(): return False if self.getleftkey() is guard.getleftkey(): # same operation valid, lc = self.lhs.compare(guard.lhs) if not valid: return False valid, rc = self.rhs.compare(guard.rhs) if not valid: return False opnum = self.get_compare_opnum() if opnum == -1: return False # x < y = -1,-2,... # x == y = 0 # x > y = 1,2,... if opnum in (rop.INT_LE, rop.INT_LT): return (lc >= 0 and rc <= 0) if opnum in (rop.INT_GE, rop.INT_GT): return (lc <= 0 and rc >= 0) return False def transitive_imply(self, other, opt, loop): if self.op.getopnum() != other.op.getopnum(): # stronger restriction, intermixing e.g. <= and < would be possible return None if self.getleftkey() is not other.getleftkey(): return None if not self.rhs.is_identity(): # stronger restriction return None # this is a valid transitive guard that eliminates the loop guard opnum = self.transitive_cmpop(self.cmp_op.getopnum()) box_rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) other_rhs = self.emit_varops(opt, other.rhs, other.cmp_op.getarg(1)) compare = ResOperation(opnum, [box_rhs, other_rhs]) opt.emit_operation(compare) # guard descr = CompileLoopVersionDescr() descr.copy_all_attributes_from(self.op.getdescr()) descr.rd_vector_info = None # do not copy the accum list assert isinstance(descr, AbstractFailDescr) guard = ResOperation(self.op.getopnum(), [compare], descr=descr) guard.setfailargs(loop.label.getarglist_copy()) opt.emit_operation(guard) return guard def transitive_cmpop(self, opnum): if opnum == rop.INT_LT: return rop.INT_LE if opnum == rop.INT_GT: return rop.INT_GE return opnum def get_compare_opnum(self): opnum = self.op.getopnum() if opnum == rop.GUARD_TRUE: return self.cmp_op.getopnum() else: return self.cmp_op.boolinverse def inhert_attributes(self, other): myop = self.op otherop = other.op assert isinstance(otherop, GuardResOp) assert isinstance(myop, GuardResOp) self.index = other.index descr = myop.getdescr() descr.copy_all_attributes_from(other.op.getdescr()) # TODO myop.rd_frame_info_list = otherop.rd_frame_info_list myop.setfailargs(otherop.getfailargs()[:]) # TODO myop.rd_snapshot = otherop.rd_snapshot def emit_varops(self, opt, var, old_arg): assert isinstance(var, IndexVar) if var.is_identity(): return var.var box = var.emit_operations(opt) opt.renamer.start_renaming(old_arg, box) return box def emit_operations(self, opt): # create trace instructions for the index lhs = self.emit_varops(opt, self.lhs, self.cmp_op.getarg(0)) rhs = self.emit_varops(opt, self.rhs, self.cmp_op.getarg(1)) opnum = self.cmp_op.getopnum() cmp_op = ResOperation(opnum, [lhs, rhs]) opt.emit_operation(cmp_op) # emit that actual guard guard = ResOperation(self.op.getopnum(), [cmp_op], self.op.getdescr()) guard.setfailargs(self.op.getfailargs()[:]) opt.emit_operation(guard) self.setindex(opt.operation_position() - 1) self.setoperation(guard) self.setcmp(cmp_op) def set_to_none(self, info, loop): operations = loop.operations assert operations[self.index] is self.op operations[self.index] = None descr = self.op.getdescr() if operations[self.index - 1] is self.cmp_op: operations[self.index - 1] = None @staticmethod def of(boolarg, operations, index, index_vars): guard_op = operations[index] cmp_op = guard_op.getarg(0) if not (rop.INT_LT <= cmp_op.getopnum() <= rop.INT_GE): return None return Guard(index, guard_op, cmp_op, index_vars)
def iv(value, coeff=(1,1,0)): var = IndexVar(value) var.coefficient_mul = coeff[0] var.coefficient_div = coeff[1] var.constant = coeff[2] return var