Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r85037:f0e47a0437e8 Date: 2016-06-08 19:47 +0200 http://bitbucket.org/pypy/pypy/changeset/f0e47a0437e8/
Log: Reintroduce some JIT support for int_mod(). Add rarithmetic.int_c_mod(). diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -522,6 +522,7 @@ # but be really compiled rewrite_op_int_abs = _do_builtin_call rewrite_op_int_floordiv = _do_builtin_call + rewrite_op_int_mod = _do_builtin_call rewrite_op_llong_abs = _do_builtin_call rewrite_op_llong_floordiv = _do_builtin_call rewrite_op_llong_mod = _do_builtin_call @@ -531,7 +532,6 @@ rewrite_op_gc_id = _do_builtin_call rewrite_op_gc_pin = _do_builtin_call rewrite_op_gc_unpin = _do_builtin_call - rewrite_op_uint_mod = _do_builtin_call rewrite_op_cast_float_to_uint = _do_builtin_call rewrite_op_cast_uint_to_float = _do_builtin_call rewrite_op_weakref_create = _do_builtin_call diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -260,6 +260,13 @@ # the JIT knows that if x and y are both positive, this is just 'r' return r + (((x ^ y) >> (LONG_BIT - 1)) & (p != x)) +def _ll_2_int_mod(x, y): + # same comments as _ll_2_int_floordiv() + r = x % y + # the JIT knows that if x and y are both positive, this doesn't change 'r' + r -= y & (((x ^ y) & (r | -r)) >> (LONG_BIT - 1)) + return r + def _ll_1_cast_uint_to_float(x): # XXX on 32-bit platforms, this should be done using cast_longlong_to_float @@ -431,6 +438,7 @@ inline_calls_to = [ ('int_abs', [lltype.Signed], lltype.Signed), ('int_floordiv', [lltype.Signed, lltype.Signed], lltype.Signed), + ('int_mod', [lltype.Signed, lltype.Signed], lltype.Signed), ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float), ] diff --git a/rpython/jit/codewriter/test/test_support.py b/rpython/jit/codewriter/test/test_support.py --- a/rpython/jit/codewriter/test/test_support.py +++ b/rpython/jit/codewriter/test/test_support.py @@ -144,11 +144,13 @@ assert _ll_1_int_abs(-10) == 10 assert _ll_1_int_abs(-sys.maxint) == sys.maxint -def test_int_floordiv(): +def test_int_floordiv_mod(): from rpython.rtyper.lltypesystem.lloperation import llop - from rpython.jit.codewriter.support import _ll_2_int_floordiv + from rpython.jit.codewriter.support import _ll_2_int_floordiv, _ll_2_int_mod for x in range(-6, 7): for y in range(-3, 4): if y != 0: assert (_ll_2_int_floordiv(x, y) == llop.int_floordiv(lltype.Signed, x, y)) + assert (_ll_2_int_mod(x, y) == + llop.int_mod(lltype.Signed, x, y)) 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 @@ -97,17 +97,14 @@ self.emit_operation(op) r = self.getintbound(op) - if b2.is_constant(): - val = b2.lower - if val >= 0: - r.intersect(IntBound(0, val)) - elif b1.is_constant(): - val = b1.lower - if val >= 0: - r.intersect(IntBound(0, val)) - elif b1.known_ge(IntBound(0, 0)) and b2.known_ge(IntBound(0, 0)): - lesser = min(b1.upper, b2.upper) - r.intersect(IntBound(0, next_pow2_m1(lesser))) + pos1 = b1.known_ge(IntBound(0, 0)) + pos2 = b2.known_ge(IntBound(0, 0)) + if pos1 or pos2: + r.make_ge(IntBound(0, 0)) + if pos1: + r.make_le(b1) + if pos2: + r.make_le(b2) def optimize_INT_SUB(self, op): self.emit_operation(op) 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 @@ -5188,6 +5188,25 @@ """ self.optimize_loop(ops, ops) + def test_int_and_positive(self): + ops = """ + [i0, i1] + i2 = int_ge(i1, 0) + guard_true(i2) [] + i3 = int_and(i0, i1) + i4 = int_ge(i3, 0) + guard_true(i4) [] + jump(i3) + """ + expected = """ + [i0, i1] + i2 = int_ge(i1, 0) + guard_true(i2) [] + i3 = int_and(i0, i1) + jump(i3) + """ + self.optimize_loop(ops, expected) + def test_int_or_cmp_above_bounds(self): ops = """ [p0,p1] diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -972,6 +972,41 @@ assert res == expected # should contain a call_i(..., OS=OS_INT_PY_DIV) + def test_int_c_mod(self): + from rpython.rlib.rarithmetic import int_c_mod + myjitdriver = JitDriver(greens = [], reds = ['i', 't']) + def f(i): + t = 0 + while i < 10: + myjitdriver.can_enter_jit(i=i, t=t) + myjitdriver.jit_merge_point(i=i, t=t) + t += int_c_mod(-100, i) + i += 1 + return t + expected = -sum([100 % n for n in range(1, 10)]) + assert f(1) == expected + res = self.meta_interp(f, [1]) + assert res == expected + # should contain a call_i(..., OS=OS_INT_PY_MOD) + + def test_positive_c_div_mod(self): + from rpython.rlib.rarithmetic import int_c_div, int_c_mod + myjitdriver = JitDriver(greens = [], reds = ['i', 't']) + def f(i): + t = 0 + while i < 10: + myjitdriver.can_enter_jit(i=i, t=t) + myjitdriver.jit_merge_point(i=i, t=t) + assert i > 0 + t += int_c_div(100, i) - int_c_mod(100, i) + i += 1 + return t + expected = sum([100 // n - 100 % n for n in range(1, 10)]) + assert f(1) == expected + res = self.meta_interp(f, [1]) + assert res == expected + # all the correction code should be dead now, xxx test that + def test_float(self): myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) def f(x, y): diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py --- a/rpython/rlib/rarithmetic.py +++ b/rpython/rlib/rarithmetic.py @@ -662,6 +662,14 @@ from rpython.rtyper.lltypesystem.lloperation import llop return llop.int_floordiv(lltype.Signed, x, y) +def int_c_mod(x, y): + """Return the result of the C-style 'x % y'. This differs from the + Python-style division if (x < 0 xor y < 0). + """ + from rpython.rtyper.lltypesystem import lltype + from rpython.rtyper.lltypesystem.lloperation import llop + return llop.int_mod(lltype.Signed, x, y) + @objectmodel.specialize.ll() def byteswap(arg): """ Convert little->big endian and the opposite diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py --- a/rpython/rlib/test/test_rarithmetic.py +++ b/rpython/rlib/test/test_rarithmetic.py @@ -401,10 +401,13 @@ @given(strategies.integers(min_value=0, max_value=sys.maxint), strategies.integers(min_value=1, max_value=sys.maxint)) -def test_int_c_div(x, y): +def test_int_c_div_mod(x, y): assert int_c_div(~x, y) == -(abs(~x) // y) assert int_c_div( x,-y) == -(x // y) assert int_c_div(~x,-y) == +(abs(~x) // y) + for x1 in [x, ~x]: + for y1 in [y, -y]: + assert int_c_div(x1, y1) * y1 + int_c_mod(x1, y1) == x1 # these can't be prebuilt on 32bit U1 = r_ulonglong(0x0102030405060708L) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit