Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r48606:8e8835c75415 Date: 2011-10-30 15:55 +0100 http://bitbucket.org/pypy/pypy/changeset/8e8835c75415/
Log: merge heads diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py --- a/pypy/jit/metainterp/optimizeopt/intbounds.py +++ b/pypy/jit/metainterp/optimizeopt/intbounds.py @@ -5,6 +5,7 @@ IntUpperBound) from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method from pypy.jit.metainterp.resoperation import rop +from pypy.rlib.rarithmetic import LONG_BIT class OptIntBounds(Optimization): @@ -126,14 +127,27 @@ r.intbound.intersect(v1.intbound.div_bound(v2.intbound)) 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) - v2 = self.getvalue(op.getarg(1)) if v2.is_constant(): val = v2.box.getint() r = self.getvalue(op.result) if val < 0: val = -val - r.intbound.make_gt(IntBound(-val, -val)) + if known_nonneg: + r.intbound.make_gt(IntBound(0, 0)) + else: + r.intbound.make_gt(IntBound(-val, -val)) r.intbound.make_lt(IntBound(val, val)) def optimize_INT_LSHIFT(self, op): @@ -153,9 +167,14 @@ def optimize_INT_RSHIFT(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) - self.emit_operation(op) - r = self.getvalue(op.result) - r.intbound.intersect(v1.intbound.rshift_bound(v2.intbound)) + b = v1.intbound.rshift_bound(v2.intbound) + if b.has_lower and b.has_upper and b.lower == b.upper: + # constant result (likely 0, for rshifts that kill all bits) + self.make_constant_int(op.result, b.lower) + else: + self.emit_operation(op) + r = self.getvalue(op.result) + r.intbound.intersect(b) def optimize_INT_ADD_OVF(self, op): v1 = self.getvalue(op.getarg(0)) diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -9,6 +9,7 @@ from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from pypy.jit.metainterp import executor, compile, resume, history from pypy.jit.metainterp.resoperation import rop, opname, ResOperation +from pypy.rlib.rarithmetic import LONG_BIT def test_store_final_boxes_in_guard(): @@ -4714,11 +4715,11 @@ i5 = int_ge(i0, 0) guard_true(i5) [] i1 = int_mod(i0, 42) - i2 = int_rshift(i1, 63) + 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) @@ -4726,21 +4727,41 @@ i1 = int_mod(i0, 42) finish(i1) """ - py.test.skip("in-progress") self.optimize_loop(ops, expected) - # Also, 'n % 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 + # '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) + + # 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). ops = """ [i0] i1 = int_mod(i0, 16) - i2 = int_rshift(i1, 63) + 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) diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -4783,6 +4783,52 @@ """ self.optimize_loop(ops, expected) + + def test_division_nonneg(self): + py.test.skip("harder") + # this is how an app-level division turns into right now + ops = """ + [i4] + i1 = int_ge(i4, 0) + guard_true(i1) [] + i16 = int_floordiv(i4, 3) + i18 = int_mul(i16, 3) + i19 = int_sub(i4, i18) + i21 = int_rshift(i19, %d) + i22 = int_add(i16, i21) + finish(i22) + """ % (LONG_BIT-1) + expected = """ + [i4] + i1 = int_ge(i4, 0) + guard_true(i1) [] + i16 = int_floordiv(i4, 3) + finish(i16) + """ + self.optimize_loop(ops, expected) + + def test_division_by_2(self): + py.test.skip("harder") + ops = """ + [i4] + i1 = int_ge(i4, 0) + guard_true(i1) [] + i16 = int_floordiv(i4, 2) + i18 = int_mul(i16, 2) + i19 = int_sub(i4, i18) + i21 = int_rshift(i19, %d) + i22 = int_add(i16, i21) + finish(i22) + """ % (LONG_BIT-1) + expected = """ + [i4] + i1 = int_ge(i4, 0) + guard_true(i1) [] + i16 = int_rshift(i4, 1) + finish(i16) + """ + self.optimize_loop(ops, expected) + def test_subsub_ovf(self): ops = """ [i0] _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit