[pypy-commit] pypy default: Merge branch bounds-int-add-or
squeaky
noreply at buildbot.pypy.org
Mon Feb 17 23:59:11 CET 2014
Author: Squeaky <squeaky_pl at gmx.com>
Branch:
Changeset: r69201:2b0a11075c0e
Date: 2014-02-17 23:54 +0100
http://bitbucket.org/pypy/pypy/changeset/2b0a11075c0e/
Log: Merge branch bounds-int-add-or Propagate appropriate bounds through
INT_(OR|XOR|AND) operations if the operands are positive to kill
some guards
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -78,3 +78,7 @@
.. branch: optimize-int-and
Optimize away INT_AND with constant mask of 1s that fully cover the bitrange
of other operand.
+
+.. branch: bounds-int-add-or
+Propagate appropriate bounds through INT_(OR|XOR|AND) operations if the
+operands are positive to kill some guards
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
@@ -7,6 +7,7 @@
CONST_0, MODE_ARRAY, MODE_STR, MODE_UNICODE)
from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.backend.llsupport import symbolic
def get_integer_min(is_unsigned, byte_size):
@@ -23,6 +24,17 @@
return (1 << ((byte_size << 3) - 1)) - 1
+def next_pow2_m1(n):
+ """Calculate next power of 2 greater than n minus one."""
+ n |= n >> 1
+ n |= n >> 2
+ n |= n >> 4
+ n |= n >> 8
+ n |= n >> 16
+ n |= n >> 32
+ return n
+
+
class OptIntBounds(Optimization):
"""Keeps track of the bounds placed on integers by guards and remove
redundant guards"""
@@ -56,17 +68,24 @@
optimize_GUARD_FALSE = optimize_GUARD_TRUE
optimize_GUARD_VALUE = optimize_GUARD_TRUE
- def optimize_INT_XOR(self, op):
+ def optimize_INT_OR_or_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)
+ if op.getopnum() == rop.INT_OR:
+ self.make_equal_to(op.result, v1)
+ else:
+ 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))
+ mostsignificant = v1.intbound.upper | v2.intbound.upper
+ r.intbound.intersect(IntBound(0, next_pow2_m1(mostsignificant)))
+
+ optimize_INT_OR = optimize_INT_OR_or_XOR
+ optimize_INT_XOR = optimize_INT_OR_or_XOR
def optimize_INT_AND(self, op):
v1 = self.getvalue(op.getarg(0))
@@ -82,6 +101,10 @@
val = v1.box.getint()
if val >= 0:
r.intbound.intersect(IntBound(0, val))
+ elif v1.intbound.known_ge(IntBound(0, 0)) and \
+ v2.intbound.known_ge(IntBound(0, 0)):
+ lesser = min(v1.intbound.upper, v2.intbound.upper)
+ r.intbound.intersect(IntBound(0, next_pow2_m1(lesser)))
def optimize_INT_SUB(self, op):
v1 = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py b/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py
@@ -0,0 +1,12 @@
+from rpython.jit.metainterp.optimizeopt.intbounds import next_pow2_m1
+
+
+def test_next_pow2_m1():
+ assert next_pow2_m1(0) == 0
+ assert next_pow2_m1(1) == 1
+ assert next_pow2_m1(7) == 7
+ assert next_pow2_m1(256) == 511
+ assert next_pow2_m1(255) == 255
+ assert next_pow2_m1(80) == 127
+ assert next_pow2_m1((1 << 32) - 5) == (1 << 32) - 1
+ assert next_pow2_m1((1 << 64) - 1) == (1 << 64) - 1
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
@@ -5326,6 +5326,114 @@
"""
self.optimize_loop(ops, ops)
+ def test_int_and_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ i3 = int_le(i2, 255)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_and_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ i3 = int_lt(i2, 255)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_or_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ i3 = int_le(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_or_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ i3 = int_lt(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_xor_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ i3 = int_le(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_xor_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ i3 = int_lt(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_or_same_arg(self):
+ ops = """
+ [i0]
+ i1 = int_or(i0, i0)
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ jump(i0)
+ """
+ self.optimize_loop(ops, expected)
+
class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
pass
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -1,6 +1,6 @@
import py, random
-from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr
+from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr, rffi
from rpython.rtyper.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
from rpython.rtyper.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
@@ -208,6 +208,8 @@
chararray = lltype.GcArray(lltype.Char)
chararraydescr = cpu.arraydescrof(chararray)
+ u2array = lltype.GcArray(rffi.USHORT)
+ u2arraydescr = cpu.arraydescrof(u2array)
# array of structs (complex data)
complexarray = lltype.GcArray(
More information about the pypy-commit
mailing list