[pypy-commit] pypy default: Progress a bit on optimizing int_mod.
arigo
noreply at buildbot.pypy.org
Sun Oct 30 15:55:33 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r48604:bfea8fbdeed4
Date: 2011-10-30 09:24 +0100
http://bitbucket.org/pypy/pypy/changeset/bfea8fbdeed4/
Log: Progress a bit on optimizing int_mod.
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():
@@ -4691,11 +4692,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)
@@ -4703,21 +4704,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)
More information about the pypy-commit
mailing list