[pypy-svn] r76661 - in pypy/branch/jit-bounds/pypy: jit/metainterp jit/metainterp/test module/pypyjit/test
hakanardo at codespeak.net
hakanardo at codespeak.net
Wed Aug 18 07:33:29 CEST 2010
Author: hakanardo
Date: Wed Aug 18 07:33:27 2010
New Revision: 76661
Modified:
pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py
pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py
Log:
Removing guard_no_overflow, intbound support for int_add_ovf, int_sub_ovf, int_and
Modified: pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py Wed Aug 18 07:33:27 2010
@@ -19,6 +19,10 @@
from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int
from pypy.rlib.rarithmetic import ovfcheck
+import sys
+MAXINT = sys.maxint
+MININT = -sys.maxint - 1
+
def optimize_loop_1(metainterp_sd, loop):
"""Optimize loop.operations to make it match the input of loop.specnodes
and to remove internal overheadish operations. Note that loop.specnodes
@@ -118,25 +122,37 @@
def add_bound(self, other):
res = self.copy()
if other.has_upper:
- res.upper += other.upper
+ try:
+ res.upper = ovfcheck(res.upper + other.upper)
+ except OverflowError:
+ res.has_upper = False
else:
res.has_upper = False
if other.has_lower:
- res.lower += other.lower
+ try:
+ res.lower = ovfcheck(res.lower + other.lower)
+ except OverflowError:
+ res.has_lower = False
else:
res.has_lower = False
return res
def sub_bound(self, other):
res = self.copy()
- if other.has_upper:
- res.lower -= other.upper
- else:
- res.has_lower = False
if other.has_lower:
- res.upper -= other.lower
+ try:
+ res.upper = ovfcheck(res.upper - other.lower)
+ except OverflowError:
+ res.has_upper = False
else:
res.has_upper = False
+ if other.has_upper:
+ try:
+ res.lower = ovfcheck(res.lower - other.upper)
+ except OverflowError:
+ res.has_lower = False
+ else:
+ res.has_lower = False
return res
def contains(self, val):
@@ -201,7 +217,7 @@
def __init__(self, box):
self.box = box
- self.intbound = IntUnbounded()
+ self.intbound = IntBound(MININT, MAXINT) #IntUnbounded()
if isinstance(box, Const):
self.make_constant(box)
# invariant: box is a Const if and only if level == LEVEL_CONSTANT
@@ -678,7 +694,9 @@
def propagate_forward(self):
self.exception_might_have_happened = False
self.newoperations = []
- for op in self.loop.operations:
+ self.i = 0
+ while self.i < len(self.loop.operations):
+ op = self.loop.operations[self.i]
self.producer[op.result] = op
opnum = op.opnum
for value, func in optimize_ops:
@@ -687,6 +705,7 @@
break
else:
self.optimize_default(op)
+ self.i += 1
self.loop.operations = self.newoperations
# accumulate counters
self.resumedata_memo.update_counters(self.metainterp_sd.profiler)
@@ -757,7 +776,7 @@
arg = args[i]
if arg in self.values:
args[i] = self.values[arg].get_key_box()
- args.append(ConstInt(op.opnum))
+ args.append(ConstInt(op.opnum))
return args
def optimize_default(self, op):
@@ -1199,6 +1218,15 @@
self.make_constant_int(op.result, 0)
else:
self.optimize_default(op)
+ r = self.getvalue(op.result)
+ if v2.is_constant():
+ val = v2.box.getint()
+ if val >= 0:
+ r.intbound.intersect(IntBound(0,val))
+ elif v1.is_constant():
+ val = v1.box.getint()
+ if val >= 0:
+ r.intbound.intersect(IntBound(0,val))
def optimize_INT_OR(self, op):
v1 = self.getvalue(op.args[0])
@@ -1209,6 +1237,10 @@
self.make_equal_to(op.result, v1)
else:
self.optimize_default(op)
+
+ def pure(self, opnum, args, result):
+ op = ResOperation(opnum, args, result)
+ self.pure_operations[self.make_args_key(op)] = op
def optimize_INT_SUB(self, op):
v1 = self.getvalue(op.args[0])
@@ -1218,8 +1250,11 @@
else:
self.optimize_default(op)
r = self.getvalue(op.result)
- print v1.intbound.sub_bound(v2.intbound)
r.intbound.intersect(v1.intbound.sub_bound(v2.intbound))
+
+ # Synthesize the reverse ops for optimize_default to reuse
+ self.pure(rop.INT_ADD, [op.result, op.args[1]], op.args[0])
+ self.pure(rop.INT_SUB, [op.args[0], op.result], op.args[1])
def optimize_INT_ADD(self, op):
v1 = self.getvalue(op.args[0])
@@ -1235,13 +1270,38 @@
r.intbound.intersect(v1.intbound.add_bound(v2.intbound))
# Synthesize the reverse op for optimize_default to reuse
- revop = ResOperation(rop.INT_SUB, [op.result, op.args[1]], \
- op.args[0], op.descr)
- self.pure_operations[self.make_args_key(revop)] = revop
- revop = ResOperation(rop.INT_SUB, [op.result, op.args[0]], \
- op.args[1], op.descr)
- self.pure_operations[self.make_args_key(revop)] = revop
+ self.pure(rop.INT_SUB, [op.result, op.args[1]], op.args[0])
+ self.pure(rop.INT_SUB, [op.result, op.args[0]], op.args[1])
+ def optimize_INT_ADD_OVF(self, op):
+ v1 = self.getvalue(op.args[0])
+ v2 = self.getvalue(op.args[1])
+ resbound = v1.intbound.add_bound(v2.intbound)
+ if resbound.has_lower and resbound.has_upper and \
+ self.loop.operations[self.i+1].opnum == rop.GUARD_NO_OVERFLOW:
+ # Transform into INT_SUB and remove guard
+ op.opnum = rop.INT_ADD
+ self.i += 1
+ self.optimize_INT_ADD(op)
+ else:
+ self.optimize_default(op)
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
+
+ def optimize_INT_SUB_OVF(self, op):
+ v1 = self.getvalue(op.args[0])
+ v2 = self.getvalue(op.args[1])
+ resbound = v1.intbound.sub_bound(v2.intbound)
+ if resbound.has_lower and resbound.has_upper and \
+ self.loop.operations[self.i+1].opnum == rop.GUARD_NO_OVERFLOW:
+ # Transform into INT_SUB and remove guard
+ op.opnum = rop.INT_SUB
+ self.i += 1
+ self.optimize_INT_SUB(op)
+ else:
+ self.optimize_default(op)
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_LT(self, op):
v1 = self.getvalue(op.args[0])
@@ -1360,6 +1420,9 @@
# b = r.intbound.sub_bound(v1.intbound).mul(-1)
# if v2.intbound.intersect(b):
+ propagate_bounds_INT_ADD_OVF = propagate_bounds_INT_ADD
+ propagate_bounds_INT_SUB_OVF = propagate_bounds_INT_SUB
+
optimize_ops = _findall(Optimizer, 'optimize_')
propagate_bounds_ops = _findall(Optimizer, 'propagate_bounds_')
Modified: pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py Wed Aug 18 07:33:27 2010
@@ -3169,6 +3169,47 @@
"""
self.optimize_loop(ops, 'Not', expected)
+ def test_bound_lt_add_ovf(self):
+ ops = """
+ [i0]
+ i1 = int_lt(i0, 4)
+ guard_true(i1) []
+ i2 = int_add_ovf(i0, 10)
+ guard_no_overflow() []
+ i3 = int_lt(i2, 15)
+ guard_true(i3) []
+ jump(i0)
+ """
+ expected = """
+ [i0]
+ i1 = int_lt(i0, 4)
+ guard_true(i1) []
+ i2 = int_add(i0, 10)
+ jump(i0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_bound_lt_add_ovf_before(self):
+ ops = """
+ [i0]
+ i2 = int_add_ovf(i0, 10)
+ guard_no_overflow() []
+ i3 = int_lt(i2, 15)
+ guard_true(i3) []
+ i1 = int_lt(i0, 6)
+ guard_true(i1) []
+ jump(i0)
+ """
+ expected = """
+ [i0]
+ i2 = int_add_ovf(i0, 10)
+ guard_no_overflow() []
+ i3 = int_lt(i2, 15)
+ guard_true(i3) []
+ jump(i0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
def test_bound_lt_sub(self):
ops = """
[i0]
@@ -3292,6 +3333,79 @@
"""
self.optimize_loop(ops, 'Not', expected)
+ def test_bound_ovf(self):
+ ops = """
+ [i0]
+ i1 = int_ge(i0, 0)
+ guard_true(i1) []
+ i2 = int_lt(i0, 10)
+ guard_true(i2) []
+ i3 = int_add_ovf(i0, 1)
+ guard_no_overflow() []
+ jump(i3)
+ """
+ expected = """
+ [i0]
+ i1 = int_ge(i0, 0)
+ guard_true(i1) []
+ i2 = int_lt(i0, 10)
+ guard_true(i2) []
+ i3 = int_add(i0, 1)
+ jump(i3)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_addsub_const(self):
+ ops = """
+ [i0]
+ i1 = int_add(i0, 1)
+ i2 = int_sub(i1, 1)
+ i3 = int_add(i2, 1)
+ i4 = int_mul(i2, i3)
+ jump(i4)
+ """
+ expected = """
+ [i0]
+ i1 = int_add(i0, 1)
+ i4 = int_mul(i0, i1)
+ jump(i4)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_addsub_int(self):
+ ops = """
+ [i0, i10]
+ i1 = int_add(i0, i10)
+ i2 = int_sub(i1, i10)
+ i3 = int_add(i2, i10)
+ i4 = int_add(i2, i3)
+ jump(i4, i10)
+ """
+ expected = """
+ [i0, i10]
+ i1 = int_add(i0, i10)
+ i4 = int_add(i0, i1)
+ jump(i4, i10)
+ """
+ self.optimize_loop(ops, 'Not, Not', expected)
+
+ def test_addsub_int2(self):
+ ops = """
+ [i0, i10]
+ i1 = int_add(i10, i0)
+ i2 = int_sub(i1, i10)
+ i3 = int_add(i10, i2)
+ i4 = int_add(i2, i3)
+ jump(i4, i10)
+ """
+ expected = """
+ [i0, i10]
+ i1 = int_add(i10, i0)
+ i4 = int_add(i0, i1)
+ jump(i4, i10)
+ """
+ self.optimize_loop(ops, 'Not, Not', expected)
+
def test_framestackdepth_overhead(self):
ops = """
[p0, i22]
@@ -3321,6 +3435,115 @@
jump(p0, i22)
"""
self.optimize_loop(ops, 'Not, Not', expected)
+
+ def test_addsub_ovf(self):
+ ops = """
+ [i0]
+ i1 = int_add_ovf(i0, 10)
+ guard_no_overflow() []
+ i2 = int_sub_ovf(i1, 5)
+ guard_no_overflow() []
+ jump(i2)
+ """
+ expected = """
+ [i0]
+ i1 = int_add_ovf(i0, 10)
+ guard_no_overflow() []
+ i2 = int_sub(i1, 5)
+ jump(i2)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_subadd_ovf(self):
+ ops = """
+ [i0]
+ i1 = int_sub_ovf(i0, 10)
+ guard_no_overflow() []
+ i2 = int_add_ovf(i1, 5)
+ guard_no_overflow() []
+ jump(i2)
+ """
+ expected = """
+ [i0]
+ i1 = int_sub_ovf(i0, 10)
+ guard_no_overflow() []
+ i2 = int_add(i1, 5)
+ jump(i2)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_bound_and(self):
+ ops = """
+ [i0]
+ i1 = int_and(i0, 255)
+ i2 = int_lt(i1, 500)
+ guard_true(i2) []
+ i3 = int_le(i1, 255)
+ guard_true(i3) []
+ i4 = int_gt(i1, -1)
+ guard_true(i4) []
+ i5 = int_ge(i1, 0)
+ guard_true(i5) []
+ i6 = int_lt(i1, 0)
+ guard_false(i6) []
+ i7 = int_le(i1, -1)
+ guard_false(i7) []
+ i8 = int_gt(i1, 255)
+ guard_false(i8) []
+ i9 = int_ge(i1, 500)
+ guard_false(i9) []
+ i12 = int_lt(i1, 100)
+ guard_true(i12) []
+ i13 = int_le(i1, 90)
+ guard_true(i13) []
+ i14 = int_gt(i1, 10)
+ guard_true(i14) []
+ i15 = int_ge(i1, 20)
+ guard_true(i15) []
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ i1 = int_and(i0, 255)
+ i12 = int_lt(i1, 100)
+ guard_true(i12) []
+ i13 = int_le(i1, 90)
+ guard_true(i13) []
+ i14 = int_gt(i1, 10)
+ guard_true(i14) []
+ i15 = int_ge(i1, 20)
+ guard_true(i15) []
+ jump(i1)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_subsub_ovf(self):
+ ops = """
+ [i0]
+ i1 = int_sub_ovf(1, i0)
+ guard_no_overflow() []
+ i2 = int_gt(i1, 1)
+ guard_true(i2) []
+ i3 = int_sub_ovf(1, i0)
+ guard_no_overflow() []
+ i4 = int_gt(i3, 1)
+ guard_true(i4) []
+ jump(i0)
+ """
+ expected = """
+ [i0]
+ i1 = int_sub_ovf(1, i0)
+ guard_no_overflow() []
+ i2 = int_gt(i1, 1)
+ guard_true(i2) []
+ i3 = int_sub_ovf(1, i0)
+ guard_no_overflow() []
+ i4 = int_gt(i3, 1)
+ guard_true(i4) []
+ jump(i0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
Modified: pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py (original)
+++ pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py Wed Aug 18 07:33:27 2010
@@ -110,6 +110,7 @@
if sys.platform.startswith('win'):
py.test.skip("XXX this is not Windows-friendly")
+ print logfilepath
child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
logfilepath, self.pypy_c, filepath), 'r')
result = child_stdout.read()
@@ -847,7 +848,7 @@
return intimg[i - 1]
''', maxops, ([tc], res))
- def test_intbound(self):
+ def test_intbound_simple(self):
ops = ('<', '>', '<=', '>=')
nbr = (3, 7)
for o1 in ops:
@@ -881,11 +882,12 @@
res[f(i)] += 1500
self.run_source(src, 220, ([], res))
- def test_intbound_addsub(self):
+ def test_intbound_addsub_mix(self):
tests = ('i > 4', 'i > 2', 'i + 1 > 2', '1 + i > 4',
'i - 1 > 1', '1 - i > 1', '1 - i < -3')
for t1 in tests:
for t2 in tests:
+ print t1, t2
src = '''
def f(i):
a, b = 3, 3
@@ -926,6 +928,16 @@
return (a, b)
''', 48, ([], (2000, 2000)))
+ def test_intbound_sub_lt(self):
+ self.run_source('''
+ def main():
+ i, a, b = 0, 0, 0
+ while i < 2000:
+ if i - 10 < 1995:
+ a += 1
+ i += 1
+ return (a, b)
+ ''', 38, ([], (2000, 0)))
def test_intbound_addsub_ge(self):
self.run_source('''
@@ -934,24 +946,38 @@
while i < 2000:
if i + 5 >= 5:
a += 1
- #if i - 1 >= -1:
if i - 1 >= -1:
b += 1
i += 1
return (a, b)
- ''', 0, ([], (2000, 2000)))
+ ''', 56, ([], (2000, 2000)))
- def test_intbound_sub_lt(self):
+ def test_zeropadded(self):
self.run_source('''
+ from array import array
+ class ZeroPadded(array):
+ def __new__(cls, l):
+ self = array.__new__(cls, 'd', range(l))
+ return self
+
+ def __getitem__(self, i):
+ if i < 0 or i >= self.__len__():
+ return 0
+ return array.__getitem__(self, i)
+
+
def main():
- i, a, b = 0, 0, 0
- while i < 2000:
- if i - 10 < 1995:
- a += 1
+ buf = ZeroPadded(2000)
+ i = 10
+ sa = 0
+ while i < 2000 - 10:
+ sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
i += 1
- return (a, b)
- ''', 0, ([], (2000, 0)))
+ return sa
+
+ ''', 232, ([], 9895050.0))
+ # test_circular
class AppTestJIT(PyPyCJITTests):
def setup_class(cls):
More information about the Pypy-commit
mailing list