Author: Armin Rigo <ar...@tunes.org> Branch: remove-raisingops Changeset: r84291:f69d3f2271bd Date: 2016-05-08 18:59 +0200 http://bitbucket.org/pypy/pypy/changeset/f69d3f2271bd/
Log: fix fix fix diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py b/rpython/jit/metainterp/optimizeopt/dependency.py --- a/rpython/jit/metainterp/optimizeopt/dependency.py +++ b/rpython/jit/metainterp/optimizeopt/dependency.py @@ -930,7 +930,7 @@ exec py.code.Source(multiplicative_func_source .format(name='INT_MUL', op='*', tgt='mul', cop='*')).compile() exec py.code.Source(multiplicative_func_source - .format(name='INT_FLOORDIV', op='*', tgt='div', cop='/')).compile() + .format(name='INT_PY_DIV', op='*', tgt='div', cop='/')).compile() exec py.code.Source(multiplicative_func_source .format(name='UINT_FLOORDIV', op='*', tgt='div', cop='/')).compile() del multiplicative_func_source diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -172,22 +172,21 @@ if b.bounded(): r.intersect(b) - def optimize_INT_FLOORDIV(self, op): + def optimize_INT_PY_DIV(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) self.emit_operation(op) r = self.getintbound(op) - r.intersect(b1.div_bound(b2)) + r.intersect(b1.py_div_bound(b2)) - def optimize_INT_MOD(self, op): + def optimize_INT_PY_MOD(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) - known_nonneg = (b1.known_ge(IntBound(0, 0)) and - b2.known_ge(IntBound(0, 0))) - if known_nonneg and b2.is_constant(): + if b2.is_constant(): val = b2.getint() - if (val & (val-1)) == 0: - # nonneg % power-of-two ==> nonneg & (power-of-two - 1) + if val > 0 and (val & (val-1)) == 0: + # x % power-of-two ==> x & (power-of-two - 1) + # with Python's modulo, this is valid even if 'x' is negative. arg1 = op.getarg(0) arg2 = ConstInt(val-1) op = self.replace_op_with(op, rop.INT_AND, @@ -196,15 +195,12 @@ if b2.is_constant(): val = b2.getint() r = self.getintbound(op) - if val < 0: - if val == -sys.maxint-1: - return # give up - val = -val - if known_nonneg: + if val >= 0: # with Python's modulo: 0 <= (x % pos) < pos r.make_ge(IntBound(0, 0)) - else: - r.make_gt(IntBound(-val, -val)) - r.make_lt(IntBound(val, val)) + r.make_lt(IntBound(val, val)) + else: # with Python's modulo: neg < (x % neg) <= 0 + r.make_gt(IntBound(val, val)) + r.make_le(IntBound(0, 0)) def optimize_INT_LSHIFT(self, op): arg0 = self.get_box_replacement(op.getarg(0)) @@ -613,10 +609,10 @@ b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) r = self.getintbound(op) - b = r.div_bound(b2) + b = r.py_div_bound(b2) if b1.intersect(b): self.propagate_bounds_backward(op.getarg(0)) - b = r.div_bound(b1) + b = r.py_div_bound(b1) if b2.intersect(b): self.propagate_bounds_backward(op.getarg(1)) diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py --- a/rpython/jit/metainterp/optimizeopt/intutils.py +++ b/rpython/jit/metainterp/optimizeopt/intutils.py @@ -171,11 +171,14 @@ else: return IntUnbounded() - def div_bound(self, other): + def py_div_bound(self, other): if self.has_upper and self.has_lower and \ other.has_upper and other.has_lower and \ not other.contains(0): try: + # this gives the bounds for 'int_py_div', so use the + # Python-style handling of negative numbers and not + # the C-style one vals = (ovfcheck(self.upper / other.upper), ovfcheck(self.upper / other.lower), ovfcheck(self.lower / other.upper), diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -678,21 +678,23 @@ def optimize_GUARD_FUTURE_CONDITION(self, op): self.optimizer.notice_guard_future_condition(op) - def optimize_INT_FLOORDIV(self, op): + def optimize_INT_PY_DIV(self, op): arg0 = op.getarg(0) b1 = self.getintbound(arg0) arg1 = op.getarg(1) b2 = self.getintbound(arg1) - if b2.is_constant() and b2.getint() == 1: - self.make_equal_to(op, arg0) - return - elif b1.is_constant() and b1.getint() == 0: + if b1.is_constant() and b1.getint() == 0: self.make_constant_int(op, 0) return - if b1.known_ge(IntBound(0, 0)) and b2.is_constant(): + # This is Python's integer division: 'x // (2**shift)' can always + # be replaced with 'x >> shift', even for negative values of x + if b2.is_constant(): val = b2.getint() - if val & (val - 1) == 0 and val > 0: # val == 2**shift + if val == 1: + self.make_equal_to(op, arg0) + return + elif val > 0 and val & (val - 1) == 0: # val == 2**shift op = self.replace_op_with(op, rop.INT_RSHIFT, args = [op.getarg(0), ConstInt(highest_bit(val))]) self.emit_operation(op) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py --- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py @@ -242,18 +242,18 @@ def test_div_bound(): for _, _, b1 in some_bounds(): for _, _, b2 in some_bounds(): - b3 = b1.div_bound(b2) + b3 = b1.py_div_bound(b2) for n1 in nbr: for n2 in nbr: if b1.contains(n1) and b2.contains(n2): if n2 != 0: - assert b3.contains(n1 / n2) + assert b3.contains(n1 / n2) # Python-style div - a=bound(2, 4).div_bound(bound(1, 2)) + a=bound(2, 4).py_div_bound(bound(1, 2)) assert not a.contains(0) assert not a.contains(5) - a=bound(-3, 2).div_bound(bound(1, 2)) + a=bound(-3, 2).py_div_bound(bound(1, 2)) assert not a.contains(-4) assert not a.contains(3) assert a.contains(-3) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -1849,7 +1849,7 @@ ops = """ [i0] - i1 = int_floordiv(0, i0) + i1 = int_py_div(0, i0) jump(i1) """ expected = """ @@ -4645,94 +4645,63 @@ def test_intmod_bounds(self): ops = """ [i0, i1] - i2 = int_mod(i0, 12) - i3 = int_gt(i2, 12) + i2 = int_py_mod(i0, 12) + i3 = int_ge(i2, 12) guard_false(i3) [] - i4 = int_lt(i2, -12) + i4 = int_lt(i2, 0) guard_false(i4) [] - i5 = int_mod(i1, -12) - i6 = int_lt(i5, -12) + i5 = int_py_mod(i1, -12) + i6 = int_le(i5, -12) guard_false(i6) [] - i7 = int_gt(i5, 12) + i7 = int_gt(i5, 0) guard_false(i7) [] jump(i2, i5) """ expected = """ [i0, i1] - i2 = int_mod(i0, 12) - i5 = int_mod(i1, -12) + i2 = int_py_mod(i0, 12) + i5 = int_py_mod(i1, -12) jump(i2, i5) """ self.optimize_loop(ops, expected) - # This the sequence of resoperations that is generated for a Python - # app-level int % int. When the modulus is constant and when i0 - # is known non-negative it should be optimized to a single int_mod. + # same as above, but all guards are shifted by one so that they + # must stay + ops = """ + [i8, i9] + i0 = escape_i() + i2 = int_py_mod(i0, 12) + i3 = int_ge(i2, 11) + guard_false(i3) [] + i4 = int_lt(i2, 1) + guard_false(i4) [] + i1 = escape_i() + i5 = int_py_mod(i1, -12) + i6 = int_le(i5, -11) + guard_false(i6) [] + i7 = int_gt(i5, -1) + guard_false(i7) [] + jump(i2, i5) + """ + self.optimize_loop(ops, ops) + + # 'n % power-of-two' can always be turned into int_and() ops = """ [i0] - i5 = int_ge(i0, 0) - guard_true(i5) [] - i1 = int_mod(i0, 42) - i2 = int_rshift(i1, %d) - i3 = int_and(42, i2) - i4 = int_add(i1, i3) - finish(i4) - """ % (LONG_BIT-1) + i1 = int_py_mod(i0, 8) + finish(i1) + """ expected = """ [i0] - i5 = int_ge(i0, 0) - guard_true(i5) [] - i1 = int_mod(i0, 42) - finish(i1) - """ - self.optimize_loop(ops, expected) - - # 'n % power-of-two' can be turned into int_and(); at least that's - # easy to do now if n is known to be non-negative. - ops = """ - [i0] - i5 = int_ge(i0, 0) - guard_true(i5) [] - i1 = int_mod(i0, 8) - i2 = int_rshift(i1, %d) - i3 = int_and(42, i2) - i4 = int_add(i1, i3) - finish(i4) - """ % (LONG_BIT-1) - expected = """ - [i0] - i5 = int_ge(i0, 0) - guard_true(i5) [] i1 = int_and(i0, 7) finish(i1) """ self.optimize_loop(ops, expected) - def test_intmod_bounds_harder(self): - py.test.skip("harder") - # Of course any 'maybe-negative % power-of-two' can be turned into - # int_and(), but that's a bit harder to detect here because it turns - # into several operations, and of course it is wrong to just turn - # int_mod(i0, 16) into int_and(i0, 15). + def test_intmod_bounds_bug1(self): ops = """ [i0] - i1 = int_mod(i0, 16) - i2 = int_rshift(i1, %d) - i3 = int_and(16, i2) - i4 = int_add(i1, i3) - finish(i4) - """ % (LONG_BIT-1) - expected = """ - [i0] - i4 = int_and(i0, 15) - finish(i4) - """ - self.optimize_loop(ops, expected) - - def test_intmod_bounds_bug1(self): - ops = """ - [i0] - i1 = int_mod(i0, %d) + i1 = int_py_mod(i0, %d) i2 = int_eq(i1, 0) guard_false(i2) [] finish() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit