def optimize_INT_MOD(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) known_nonneg = (v1.intbound.known_ge(IntBound(0, 0)) and v2.intbound.known_ge(IntBound(0, 0))) if known_nonneg and v2.is_constant(): val = v2.box.getint() if (val & (val - 1)) == 0: # nonneg % power-of-two ==> nonneg & (power-of-two - 1) arg1 = op.getarg(0) arg2 = ConstInt(val - 1) op = op.copy_and_change(rop.INT_AND, args=[arg1, arg2]) self.emit_operation(op) if v2.is_constant(): val = v2.box.getint() r = self.getvalue(op.result) if val < 0: if val == -sys.maxint - 1: return # give up val = -val if known_nonneg: r.intbound.make_ge(IntBound(0, 0)) else: r.intbound.make_gt(IntBound(-val, -val)) r.intbound.make_lt(IntBound(val, val))
def propagate_bounds_INT_IS_TRUE(self, op): r = self.getvalue(op.result) if r.is_constant(): if r.box.same_constant(CONST_1): v1 = self.getvalue(op.getarg(0)) if v1.intbound.known_ge(IntBound(0, 0)): v1.intbound.make_gt(IntBound(0, 0)) self.propagate_bounds_backward(op.getarg(0))
def optimize_INT_XOR(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) if v1 is v2: self.make_constant_int(op.result, 0) return self.emit_operation(op) if v1.intbound.known_ge(IntBound(0, 0)) and \ v2.intbound.known_ge(IntBound(0, 0)): r = self.getvalue(op.result) r.intbound.make_ge(IntLowerBound(0))
def propagate_bounds_INT_IS_ZERO(self, op): r = self.getvalue(op.result) if r.is_constant(): if r.box.same_constant(CONST_1): v1 = self.getvalue(op.getarg(0)) # Clever hack, we can't use self.make_constant_int yet because # the args aren't in the values dictionary yet so it runs into # an assert, this is a clever way of expressing the same thing. v1.intbound.make_ge(IntBound(0, 0)) v1.intbound.make_lt(IntBound(1, 1)) self.propagate_bounds_backward(op.getarg(0))
def test_shift_overflow(): b10 = IntBound(0, 10) b100 = IntBound(0, 100) bmax = IntBound(0, sys.maxint/2) assert not b10.lshift_bound(b100).has_upper assert not bmax.lshift_bound(b10).has_upper assert b10.lshift_bound(b10).has_upper for b in (b10, b100, bmax, IntBound(0, 0)): for shift_count_bound in (IntBound(7, LONG_BIT), IntBound(-7, 7)): #assert not b.lshift_bound(shift_count_bound).has_upper assert not b.rshift_bound(shift_count_bound).has_upper
def optimize_INT_AND(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) self.emit_operation(op) r = self.getvalue(op.result) if v2.is_constant(): val = v2.box.getint() if val >= 0: r.intbound.intersect(IntBound(0, val)) elif v1.is_constant(): val = v1.box.getint() if val >= 0: r.intbound.intersect(IntBound(0, val))
def test_intbounds(self): value1 = OptValue(BoxInt()) value1.intbound.make_ge(IntBound(0, 10)) value1.intbound.make_le(IntBound(20, 30)) info1 = NotVirtualStateInfo(value1) info2 = NotVirtualStateInfo(OptValue(BoxInt())) expected = """ [i0] i1 = int_ge(i0, 0) guard_true(i1) [] i2 = int_le(i0, 30) guard_true(i2) [] """ self.guards(info1, info2, BoxInt(15), expected) py.test.raises(InvalidLoop, self.guards, info1, info2, BoxInt(50), expected)
def make_len_gt(self, mode, descr, val): if self.lenbound: assert self.lenbound.mode == mode assert self.lenbound.descr == descr self.lenbound.bound.make_gt(IntBound(val, val)) else: self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
def is_nonnull(self): level = self.level if level == LEVEL_NONNULL or level == LEVEL_KNOWNCLASS: return True elif level == LEVEL_CONSTANT: box = self.box assert isinstance(box, Const) return box.nonnull() elif self.intbound: if self.intbound.known_gt(IntBound(0, 0)) or \ self.intbound.known_lt(IntBound(0, 0)): return True else: return False else: return False
def bound(a, b): if a is None and b is None: return IntUnbounded() elif a is None: return IntUpperBound(b) elif b is None: return IntLowerBound(a) else: return IntBound(a, b)
def make_constant(self, constbox): """Replace 'self.box' with a Const box.""" assert isinstance(constbox, Const) self.box = constbox self.level = LEVEL_CONSTANT if isinstance(constbox, ConstInt): val = constbox.getint() self.intbound = IntBound(val, val) else: self.intbound = IntUnbounded()
def __init__(self, box, level=None, known_class=None, intbound=None): self.box = box if level is not None: self.level = level self.known_class = known_class if intbound: self.intbound = intbound else: if isinstance(box, BoxInt): self.intbound = IntBound(MININT, MAXINT) else: self.intbound = IntUnbounded() if isinstance(box, Const): self.make_constant(box)
def optimize_INT_FLOORDIV(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) if v2.is_constant() and v2.box.getint() == 1: self.make_equal_to(op.result, v1) return elif v1.is_constant() and v1.box.getint() == 0: self.make_constant_int(op.result, 0) return if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant(): val = v2.box.getint() if val & (val - 1) == 0 and val > 0: # val == 2**shift op = op.copy_and_change( rop.INT_RSHIFT, args=[op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op)
def test_NotVirtualStateInfo_generalization(self): def isgeneral(value1, value2): info1 = NotVirtualStateInfo(value1) info1.position = 0 info2 = NotVirtualStateInfo(value2) info2.position = 0 return info1.generalization_of(info2, {}, {}) assert isgeneral(OptValue(BoxInt()), OptValue(ConstInt(7))) assert not isgeneral(OptValue(ConstInt(7)), OptValue(BoxInt())) ptr = OptValue(BoxPtr()) nonnull = OptValue(BoxPtr()) nonnull.make_nonnull(0) knownclass = OptValue(BoxPtr()) knownclass.make_constant_class(ConstPtr(self.someptr1), 0) const = OptValue(BoxPtr) const.make_constant_class(ConstPtr(self.someptr1), 0) const.make_constant(ConstPtr(self.someptr1)) inorder = [ptr, nonnull, knownclass, const] for i in range(len(inorder)): for j in range(i, len(inorder)): assert isgeneral(inorder[i], inorder[j]) if i != j: assert not isgeneral(inorder[j], inorder[i]) value1 = OptValue(BoxInt()) value2 = OptValue(BoxInt()) value2.intbound.make_lt(IntBound(10, 10)) assert isgeneral(value1, value2) assert not isgeneral(value2, value1) assert isgeneral(OptValue(ConstInt(7)), OptValue(ConstInt(7))) S = lltype.GcStruct('S') foo = lltype.malloc(S) fooref = lltype.cast_opaque_ptr(llmemory.GCREF, foo) assert isgeneral(OptValue(ConstPtr(fooref)), OptValue(ConstPtr(fooref)))
def test_shift_overflow(): b10 = IntBound(0, 10) b100 = IntBound(0, 100) bmax = IntBound(0, sys.maxint / 2) assert not b10.lshift_bound(b100).has_upper assert not bmax.lshift_bound(b10).has_upper assert b10.lshift_bound(b10).has_upper for b in (b10, b100, bmax, IntBound(0, 0)): for shift_count_bound in (IntBound(7, LONG_BIT), IntBound(-7, 7)): #assert not b.lshift_bound(shift_count_bound).has_upper assert not b.rshift_bound(shift_count_bound).has_upper