Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit