Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r84727:a4bb2ae13c0a
Date: 2016-05-27 14:53 +0200
http://bitbucket.org/pypy/pypy/changeset/a4bb2ae13c0a/

Log:    hg merge remove-raisingops

        Kill many lines of code. This is done by removing most of the _ovf,
        _zer and _val operations from RPython. Left: only int_add_ovf,
        int_sub_ovf and int_mul_ovf. Handling of all the other cases is done
        in rint.py.

        This gives more flexibility, which we use in the JIT for '/' and
        '%'. Now the JIT sees the Python-style behavior wrt negative
        arguments to '/' and '%', instead of the C-style one.

        This in turn allows the JIT to do better optimizations: for example,
        app-level code like 'x % 2' can now be turned into 'int_and 1' even
        if x is possibly negative.

        The JIT backends no longer directly support div and mod, which
        removes quite a lot of mess in the ARM case. In fact, even where the
        CPU supports division, it's a very slow operation (particularly on
        64-bit), so the overhead of calling a helper is small (and anyway it
        is usually needed now, to do the C-to-Python-style corrections).

diff too long, truncating to 2000 out of 3566 lines

diff --git a/pypy/module/__pypy__/interp_intop.py 
b/pypy/module/__pypy__/interp_intop.py
--- a/pypy/module/__pypy__/interp_intop.py
+++ b/pypy/module/__pypy__/interp_intop.py
@@ -2,6 +2,19 @@
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib import jit
+
+
+# XXX maybe temporary: hide llop.int_{floordiv,mod} from the JIT,
+#     because now it expects only Python-style divisions, not the
+#     C-style divisions of these two ll operations
+@jit.dont_look_inside
+def _int_floordiv(n, m):
+    return llop.int_floordiv(lltype.Signed, n, m)
+
+@jit.dont_look_inside
+def _int_mod(n, m):
+    return llop.int_mod(lltype.Signed, n, m)
 
 
 @unwrap_spec(n=int, m=int)
@@ -18,11 +31,11 @@
 
 @unwrap_spec(n=int, m=int)
 def int_floordiv(space, n, m):
-    return space.wrap(llop.int_floordiv(lltype.Signed, n, m))
+    return space.wrap(_int_floordiv(n, m))
 
 @unwrap_spec(n=int, m=int)
 def int_mod(space, n, m):
-    return space.wrap(llop.int_mod(lltype.Signed, n, m))
+    return space.wrap(_int_mod(n, m))
 
 @unwrap_spec(n=int, m=int)
 def int_lshift(space, n, m):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py 
b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -262,7 +262,7 @@
             [i0]
             i1 = int_add(i0, 1)
             i2 = int_sub(i1, 10)
-            i3 = int_floordiv(i2, 100)
+            i3 = int_xor(i2, 100)
             i4 = int_mul(i1, 1000)
             jump(i4)
         """
@@ -298,7 +298,7 @@
             [i0]
             i1 = int_add(i0, 1)
             i2 = int_sub(i1, 10)
-            i3 = int_floordiv(i2, 100)
+            i3 = int_xor(i2, 100)
             i4 = int_mul(i1, 1000)
             jump(i4)
         """
diff --git a/pypy/module/pypyjit/test_pypy_c/test_shift.py 
b/pypy/module/pypyjit/test_pypy_c/test_shift.py
--- a/pypy/module/pypyjit/test_pypy_c/test_shift.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_shift.py
@@ -47,26 +47,24 @@
             res = 0
             a = 0
             while a < 300:
-                assert a >= 0
-                assert 0 <= b <= 10
-                res = a/b     # ID: div
+                res1 = a/b     # ID: div
+                res2 = a/2     # ID: shift
+                res += res1 + res2
                 a += 1
             return res
         #
         log = self.run(main, [3])
-        assert log.result == 99
+        assert log.result == main(3)
         loop, = log.loops_by_filename(self.filepath)
-        if sys.maxint == 2147483647:
-            SHIFT = 31
-        else:
-            SHIFT = 63
         assert loop.match_by_id('div', """
-            i10 = int_floordiv(i6, i7)
-            i11 = int_mul(i10, i7)
-            i12 = int_sub(i6, i11)
-            i14 = int_rshift(i12, %d)
-            i15 = int_add(i10, i14)
-        """ % SHIFT)
+            i56 = int_eq(i48, %d)
+            i57 = int_and(i56, i37)
+            guard_false(i57, descr=...)
+            i1 = call_i(_, i48, i3, descr=...)
+        """ % (-sys.maxint-1,))
+        assert loop.match_by_id('shift', """
+            i1 = int_rshift(i2, 1)
+        """)
 
     def test_division_to_rshift_allcases(self):
         """
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py 
b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -1,11 +1,6 @@
 import sys
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 
-if sys.maxint == 2147483647:
-    SHIFT = 31
-else:
-    SHIFT = 63
-
 # XXX review the <Call> descrs to replace some EF=5 with EF=4 (elidable)
 
 
@@ -28,10 +23,7 @@
             guard_true(i14, descr=...)
             guard_not_invalidated(descr=...)
             i16 = int_eq(i6, %d)
-            i15 = int_mod(i6, i10)
-            i17 = int_rshift(i15, %d)
-            i18 = int_and(i10, i17)
-            i19 = int_add(i15, i18)
+            i19 = call_i(ConstClass(ll_int_mod__Signed_Signed), i6, i10, 
descr=<Calli . ii EF=0 OS=14>)
             i21 = int_lt(i19, 0)
             guard_false(i21, descr=...)
             i22 = int_ge(i19, i10)
@@ -49,7 +41,7 @@
             i34 = int_add(i6, 1)
             --TICK--
             jump(..., descr=...)
-        """ % (-sys.maxint-1, SHIFT))
+        """ % (-sys.maxint-1,))
 
     def test_long(self):
         def main(n):
@@ -67,14 +59,7 @@
             guard_true(i11, descr=...)
             guard_not_invalidated(descr=...)
             i13 = int_eq(i6, %d)         # value provided below
-            i15 = int_mod(i6, 10)
-            i17 = int_rshift(i15, %d)    # value provided below
-            i18 = int_and(10, i17)
-            i19 = int_add(i15, i18)
-            i21 = int_lt(i19, 0)
-            guard_false(i21, descr=...)
-            i22 = int_ge(i19, 10)
-            guard_false(i22, descr=...)
+            i19 = call_i(ConstClass(ll_int_mod__Signed_Signed), i6, 10, 
descr=<Calli . ii EF=0 OS=14>)
             i23 = strgetitem(p10, i19)
             p25 = newstr(1)
             strsetitem(p25, 0, i23)
@@ -89,7 +74,7 @@
             guard_no_overflow(descr=...)
             --TICK--
             jump(..., descr=...)
-        """ % (-sys.maxint-1, SHIFT))
+        """ % (-sys.maxint-1,))
 
     def test_str_mod(self):
         def main(n):
diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -7,6 +7,7 @@
 from rpython.rlib import rstring, runicode, rlocale, rfloat, jit
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rfloat import copysign, formatd
+from rpython.rlib.rarithmetic import r_uint, intmask
 
 
 @specialize.argtype(1)
@@ -828,33 +829,37 @@
                 return s
             # This part is slow.
             negative = value < 0
-            value = abs(value)
+            base = r_uint(base)
+            value = r_uint(value)
+            if negative:   # change the sign on the unsigned number: otherwise,
+                value = -value   #   we'd risk overflow if value==-sys.maxint-1
+            #
             buf = ["\0"] * (8 * 8 + 6) # Too much on 32 bit, but who cares?
             i = len(buf) - 1
             while True:
-                div = value // base
-                mod = value - div * base
-                digit = abs(mod)
+                div = value // base         # unsigned
+                mod = value - div * base    # unsigned, always in range(0,base)
+                digit = intmask(mod)
                 digit += ord("0") if digit < 10 else ord("a") - 10
                 buf[i] = chr(digit)
-                value = div
+                value = div                 # unsigned
                 i -= 1
                 if not value:
                     break
-            if base == 2:
+            if base == r_uint(2):
                 buf[i] = "b"
                 buf[i - 1] = "0"
-            elif base == 8:
+            elif base == r_uint(8):
                 buf[i] = "o"
                 buf[i - 1] = "0"
-            elif base == 16:
+            elif base == r_uint(16):
                 buf[i] = "x"
                 buf[i - 1] = "0"
             else:
                 buf[i] = "#"
-                buf[i - 1] = chr(ord("0") + base % 10)
-                if base > 10:
-                    buf[i - 2] = chr(ord("0") + base // 10)
+                buf[i - 1] = chr(ord("0") + intmask(base % r_uint(10)))
+                if base > r_uint(10):
+                    buf[i - 2] = chr(ord("0") + intmask(base // r_uint(10)))
                     i -= 1
             i -= 1
             if negative:
diff --git a/rpython/config/translationoption.py 
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -213,11 +213,6 @@
                    default=False),
         BoolOption("merge_if_blocks", "Merge if ... elif chains",
                    cmdline="--if-block-merge", default=True),
-        BoolOption("raisingop2direct_call",
-                   "Transform operations that can implicitly raise an "
-                   "exception into calls to functions that explicitly "
-                   "raise exceptions",
-                   default=False, cmdline="--raisingop2direct_call"),
         BoolOption("mallocs", "Remove mallocs", default=True),
         BoolOption("constfold", "Constant propagation",
                    default=True),
diff --git a/rpython/jit/backend/arm/codebuilder.py 
b/rpython/jit/backend/arm/codebuilder.py
--- a/rpython/jit/backend/arm/codebuilder.py
+++ b/rpython/jit/backend/arm/codebuilder.py
@@ -1,6 +1,5 @@
 from rpython.jit.backend.arm import conditions as cond
 from rpython.jit.backend.arm import registers as reg
-from rpython.jit.backend.arm import support
 from rpython.jit.backend.arm.arch import WORD, PC_OFFSET
 from rpython.jit.backend.arm.instruction_builder import define_instructions
 from rpython.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin
@@ -17,17 +16,6 @@
     sandboxsafe=True)
 
 
-def binary_helper_call(name):
-    function = getattr(support, 'arm_%s' % name)
-
-    def f(self, c=cond.AL):
-        """Generates a call to a helper function, takes its
-        arguments in r0 and r1, result is placed in r0"""
-        addr = rffi.cast(lltype.Signed, function)
-        self.BL(addr, c)
-    return f
-
-
 class AbstractARMBuilder(object):
     def __init__(self, arch_version=7):
         self.arch_version = arch_version
@@ -348,10 +336,6 @@
         self.write32(c << 28
                     | 0x157ff05f)
 
-    DIV = binary_helper_call('int_div')
-    MOD = binary_helper_call('int_mod')
-    UDIV = binary_helper_call('uint_div')
-
     FMDRR = VMOV_cr     # uh, there are synonyms?
     FMRRD = VMOV_rc
 
diff --git a/rpython/jit/backend/arm/helper/assembler.py 
b/rpython/jit/backend/arm/helper/assembler.py
--- a/rpython/jit/backend/arm/helper/assembler.py
+++ b/rpython/jit/backend/arm/helper/assembler.py
@@ -46,20 +46,6 @@
     f.__name__ = 'emit_op_%s' % name
     return f
 
-def gen_emit_op_by_helper_call(name, opname):
-    helper = getattr(InstrBuilder, opname)
-    def f(self, op, arglocs, regalloc, fcond):
-        assert fcond is not None
-        if op.type != 'v':
-            regs = r.caller_resp[1:] + [r.ip]
-        else:
-            regs = r.caller_resp
-        with saved_registers(self.mc, regs, r.caller_vfp_resp):
-            helper(self.mc, fcond)
-        return fcond
-    f.__name__ = 'emit_op_%s' % name
-    return f
-
 def gen_emit_cmp_op(name, true_cond):
     def f(self, op, arglocs, regalloc, fcond):
         l0, l1, res = arglocs
diff --git a/rpython/jit/backend/arm/helper/regalloc.py 
b/rpython/jit/backend/arm/helper/regalloc.py
--- a/rpython/jit/backend/arm/helper/regalloc.py
+++ b/rpython/jit/backend/arm/helper/regalloc.py
@@ -72,25 +72,6 @@
     res = self.force_allocate_reg_or_cc(op)
     return [loc1, loc2, res]
 
-def prepare_op_by_helper_call(name):
-    def f(self, op, fcond):
-        assert fcond is not None
-        a0 = op.getarg(0)
-        a1 = op.getarg(1)
-        arg1 = self.rm.make_sure_var_in_reg(a0, selected_reg=r.r0)
-        arg2 = self.rm.make_sure_var_in_reg(a1, selected_reg=r.r1)
-        assert arg1 == r.r0
-        assert arg2 == r.r1
-        if not isinstance(a0, Const) and self.stays_alive(a0):
-            self.force_spill_var(a0)
-        self.possibly_free_vars_for_op(op)
-        self.free_temp_vars()
-        self.after_call(op)
-        self.possibly_free_var(op)
-        return []
-    f.__name__ = name
-    return f
-
 def prepare_int_cmp(self, op, fcond):
     assert fcond is not None
     boxes = list(op.getarglist())
diff --git a/rpython/jit/backend/arm/opassembler.py 
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -3,7 +3,7 @@
 from rpython.jit.backend.arm import registers as r
 from rpython.jit.backend.arm import shift
 from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
-from rpython.jit.backend.arm.helper.assembler import 
(gen_emit_op_by_helper_call,
+from rpython.jit.backend.arm.helper.assembler import (
                                                 gen_emit_op_unary_cmp,
                                                 gen_emit_op_ri,
                                                 gen_emit_cmp_op,
@@ -132,10 +132,6 @@
         self.guard_success_cc = c.VC
         return fcond
 
-    emit_op_int_floordiv = gen_emit_op_by_helper_call('int_floordiv', 'DIV')
-    emit_op_int_mod = gen_emit_op_by_helper_call('int_mod', 'MOD')
-    emit_op_uint_floordiv = gen_emit_op_by_helper_call('uint_floordiv', 'UDIV')
-
     emit_op_int_and = gen_emit_op_ri('int_and', 'AND')
     emit_op_int_or = gen_emit_op_ri('int_or', 'ORR')
     emit_op_int_xor = gen_emit_op_ri('int_xor', 'EOR')
diff --git a/rpython/jit/backend/arm/regalloc.py 
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -7,7 +7,7 @@
 from rpython.jit.backend.arm import conditions as c
 from rpython.jit.backend.arm import locations
 from rpython.jit.backend.arm.locations import imm, get_fp_offset
-from rpython.jit.backend.arm.helper.regalloc import (prepare_op_by_helper_call,
+from rpython.jit.backend.arm.helper.regalloc import (
                                                     prepare_unary_cmp,
                                                     prepare_op_ri,
                                                     prepare_int_cmp,
@@ -478,10 +478,6 @@
         resloc = self.force_allocate_reg(op)
         return [argloc, imm(numbytes), resloc]
 
-    prepare_op_int_floordiv = prepare_op_by_helper_call('int_floordiv')
-    prepare_op_int_mod = prepare_op_by_helper_call('int_mod')
-    prepare_op_uint_floordiv = prepare_op_by_helper_call('unit_floordiv')
-
     prepare_op_int_and = prepare_op_ri('int_and')
     prepare_op_int_or = prepare_op_ri('int_or')
     prepare_op_int_xor = prepare_op_ri('int_xor')
diff --git a/rpython/jit/backend/arm/support.py 
b/rpython/jit/backend/arm/support.py
deleted file mode 100644
--- a/rpython/jit/backend/arm/support.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rlib.rarithmetic import r_uint
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-
-eci = ExternalCompilationInfo(post_include_bits=["""
-static int pypy__arm_int_div(int a, int b) {
-    return a/b;
-}
-static unsigned int pypy__arm_uint_div(unsigned int a, unsigned int b) {
-    return a/b;
-}
-static int pypy__arm_int_mod(int a, int b) {
-    return a % b;
-}
-"""])
-
-
-def arm_int_div_emulator(a, b):
-    return int(a / float(b))
-arm_int_div_sign = lltype.Ptr(
-        lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
-arm_int_div = rffi.llexternal(
-    "pypy__arm_int_div", [lltype.Signed, lltype.Signed], lltype.Signed,
-                        _callable=arm_int_div_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
-
-
-def arm_uint_div_emulator(a, b):
-    return r_uint(a) / r_uint(b)
-arm_uint_div_sign = lltype.Ptr(
-        lltype.FuncType([lltype.Unsigned, lltype.Unsigned], lltype.Unsigned))
-arm_uint_div = rffi.llexternal(
-    "pypy__arm_uint_div", [lltype.Unsigned, lltype.Unsigned], lltype.Unsigned,
-                        _callable=arm_uint_div_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
-
-
-def arm_int_mod_emulator(a, b):
-    sign = 1
-    if a < 0:
-        a = -1 * a
-        sign = -1
-    if b < 0:
-        b = -1 * b
-    res = a % b
-    return sign * res
-arm_int_mod_sign = arm_int_div_sign
-arm_int_mod = rffi.llexternal(
-    "pypy__arm_int_mod", [lltype.Signed, lltype.Signed], lltype.Signed,
-                        _callable=arm_int_mod_emulator,
-                        compilation_info=eci,
-                        _nowrapper=True, elidable_function=True)
diff --git a/rpython/jit/backend/arm/test/test_arch.py 
b/rpython/jit/backend/arm/test/test_arch.py
deleted file mode 100644
--- a/rpython/jit/backend/arm/test/test_arch.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from rpython.jit.backend.arm import support
-
-def test_mod():
-    assert support.arm_int_mod(10, 2) == 0
-    assert support.arm_int_mod(11, 2) == 1
-    assert support.arm_int_mod(11, 3) == 2
-
-def test_mod2():
-    assert support.arm_int_mod(-10, 2) == 0
-    assert support.arm_int_mod(-11, 2) == -1
-    assert support.arm_int_mod(-11, 3) == -2
-
-def test_mod3():
-    assert support.arm_int_mod(10, -2) == 0
-    assert support.arm_int_mod(11, -2) == 1
-    assert support.arm_int_mod(11, -3) == 2
-
-
-def test_div():
-    assert support.arm_int_div(-7, 2) == -3
-    assert support.arm_int_div(9, 2) == 4
-    assert support.arm_int_div(10, 5) == 2
-
diff --git a/rpython/jit/backend/arm/test/test_assembler.py 
b/rpython/jit/backend/arm/test/test_assembler.py
--- a/rpython/jit/backend/arm/test/test_assembler.py
+++ b/rpython/jit/backend/arm/test/test_assembler.py
@@ -193,32 +193,6 @@
         self.a.gen_func_epilog()
         assert run_asm(self.a) == 61
 
-    def test_DIV(self):
-        self.a.gen_func_prolog()
-        self.a.mc.MOV_ri(r.r0.value, 123)
-        self.a.mc.MOV_ri(r.r1.value, 2)
-        self.a.mc.DIV()
-        self.a.gen_func_epilog()
-        assert run_asm(self.a) == 61
-
-    def test_DIV2(self):
-        self.a.gen_func_prolog()
-        self.a.mc.gen_load_int(r.r0.value, -110)
-        self.a.mc.gen_load_int(r.r1.value, 3)
-        self.a.mc.DIV()
-        self.a.gen_func_epilog()
-        assert run_asm(self.a) == -36
-
-    def test_DIV3(self):
-        self.a.gen_func_prolog()
-        self.a.mc.gen_load_int(r.r8.value, 110)
-        self.a.mc.gen_load_int(r.r9.value, -3)
-        self.a.mc.MOV_rr(r.r0.value, r.r8.value)
-        self.a.mc.MOV_rr(r.r1.value, r.r9.value)
-        self.a.mc.DIV()
-        self.a.gen_func_epilog()
-        assert run_asm(self.a) == -36
-
     def test_bl_with_conditional_exec(self):
         functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
         call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py 
b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
@@ -496,22 +496,6 @@
         self.interpret(ops, [s, ord('a')])
         assert s[1] == 'a'
 
-    def test_division_optimized(self):
-        ops = '''
-        [i7, i6]
-        label(i7, i6, descr=targettoken)
-        i18 = int_floordiv(i7, i6)
-        i19 = int_xor(i7, i6)
-        i21 = int_lt(i19, 0)
-        i22 = int_mod(i7, i6)
-        i23 = int_is_true(i22)
-        i24 = int_eq(i6, 4)
-        guard_false(i24) [i18]
-        jump(i18, i6, descr=targettoken)
-        '''
-        self.interpret(ops, [10, 4])
-        assert self.getint(0) == 2
-        # FIXME: Verify that i19 - i23 are removed
 
 class TestRegallocFloats(BaseTestRegalloc):
     def setup_class(cls):
diff --git a/rpython/jit/backend/ppc/opassembler.py 
b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -80,24 +80,6 @@
         else:
             self.mc.mulldox(*self.do_emit_int_binary_ovf(op, arglocs))
 
-    def emit_int_floordiv(self, op, arglocs, regalloc):
-        l0, l1, res = arglocs
-        if IS_PPC_32:
-            self.mc.divw(res.value, l0.value, l1.value)
-        else:
-            self.mc.divd(res.value, l0.value, l1.value)
-
-    def emit_int_mod(self, op, arglocs, regalloc):
-        l0, l1, res = arglocs
-        if IS_PPC_32:
-            self.mc.divw(r.r0.value, l0.value, l1.value)
-            self.mc.mullw(r.r0.value, r.r0.value, l1.value)
-        else:
-            self.mc.divd(r.r0.value, l0.value, l1.value)
-            self.mc.mulld(r.r0.value, r.r0.value, l1.value)
-        self.mc.subf(r.r0.value, r.r0.value, l0.value)
-        self.mc.mr(res.value, r.r0.value)
-
     def emit_int_and(self, op, arglocs, regalloc):
         l0, l1, res = arglocs
         self.mc.and_(res.value, l0.value, l1.value)
@@ -130,13 +112,6 @@
             self.mc.srw(res.value, l0.value, l1.value)
         else:
             self.mc.srd(res.value, l0.value, l1.value)
-    
-    def emit_uint_floordiv(self, op, arglocs, regalloc):
-        l0, l1, res = arglocs
-        if IS_PPC_32:
-            self.mc.divwu(res.value, l0.value, l1.value)
-        else:
-            self.mc.divdu(res.value, l0.value, l1.value)
 
     emit_int_le = gen_emit_cmp_op(c.LE)
     emit_int_lt = gen_emit_cmp_op(c.LT)
diff --git a/rpython/jit/backend/ppc/regalloc.py 
b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -432,15 +432,12 @@
     prepare_int_mul = helper.prepare_int_add_or_mul
     prepare_nursery_ptr_increment = prepare_int_add
 
-    prepare_int_floordiv = helper.prepare_binary_op
-    prepare_int_mod = helper.prepare_binary_op
     prepare_int_and = helper.prepare_binary_op
     prepare_int_or = helper.prepare_binary_op
     prepare_int_xor = helper.prepare_binary_op
     prepare_int_lshift = helper.prepare_binary_op
     prepare_int_rshift = helper.prepare_binary_op
     prepare_uint_rshift = helper.prepare_binary_op
-    prepare_uint_floordiv = helper.prepare_binary_op
 
     prepare_int_add_ovf = helper.prepare_binary_op
     prepare_int_sub_ovf = helper.prepare_binary_op
diff --git a/rpython/jit/backend/test/test_random.py 
b/rpython/jit/backend/test/test_random.py
--- a/rpython/jit/backend/test/test_random.py
+++ b/rpython/jit/backend/test/test_random.py
@@ -548,8 +548,8 @@
             ]:
     OPERATIONS.append(BinaryOperation(_op, boolres=True))
 
-OPERATIONS.append(BinaryOperation(rop.INT_FLOORDIV, ~3, 2))
-OPERATIONS.append(BinaryOperation(rop.INT_MOD, ~3, 2))
+#OPERATIONS.append(BinaryOperation(rop.INT_FLOORDIV, ~3, 2))
+#OPERATIONS.append(BinaryOperation(rop.INT_MOD, ~3, 2))
 OPERATIONS.append(BinaryOperation(rop.INT_RSHIFT, LONG_BIT-1))
 OPERATIONS.append(BinaryOperation(rop.INT_LSHIFT, LONG_BIT-1))
 OPERATIONS.append(BinaryOperation(rop.UINT_RSHIFT, LONG_BIT-1))
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1444,20 +1444,6 @@
         self.mov(imm0, resloc)
         self.mc.CMOVNS(resloc, arglocs[0])
 
-    def genop_int_mod(self, op, arglocs, resloc):
-        if IS_X86_32:
-            self.mc.CDQ()
-        elif IS_X86_64:
-            self.mc.CQO()
-
-        self.mc.IDIV_r(ecx.value)
-
-    genop_int_floordiv = genop_int_mod
-
-    def genop_uint_floordiv(self, op, arglocs, resloc):
-        self.mc.XOR_rr(edx.value, edx.value)
-        self.mc.DIV_r(ecx.value)
-
     genop_llong_add = _binaryop("PADDQ")
     genop_llong_sub = _binaryop("PSUBQ")
     genop_llong_and = _binaryop("PAND")
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -585,29 +585,6 @@
     consider_int_rshift  = consider_int_lshift
     consider_uint_rshift = consider_int_lshift
 
-    def _consider_int_div_or_mod(self, op, resultreg, trashreg):
-        l0 = self.rm.make_sure_var_in_reg(op.getarg(0), selected_reg=eax)
-        l1 = self.rm.make_sure_var_in_reg(op.getarg(1), selected_reg=ecx)
-        l2 = self.rm.force_allocate_reg(op, selected_reg=resultreg)
-        # the register (eax or edx) not holding what we are looking for
-        # will be just trash after that operation
-        tmpvar = TempVar()
-        self.rm.force_allocate_reg(tmpvar, selected_reg=trashreg)
-        assert l0 is eax
-        assert l1 is ecx
-        assert l2 is resultreg
-        self.rm.possibly_free_var(tmpvar)
-
-    def consider_int_mod(self, op):
-        self._consider_int_div_or_mod(op, edx, eax)
-        self.perform(op, [eax, ecx], edx)
-
-    def consider_int_floordiv(self, op):
-        self._consider_int_div_or_mod(op, eax, edx)
-        self.perform(op, [eax, ecx], eax)
-
-    consider_uint_floordiv = consider_int_floordiv
-
     def _consider_compop(self, op):
         vx = op.getarg(0)
         vy = op.getarg(1)
diff --git a/rpython/jit/codewriter/effectinfo.py 
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -28,6 +28,11 @@
     OS_THREADLOCALREF_GET       = 5    # llop.threadlocalref_get
     OS_NOT_IN_TRACE             = 8    # for calls not recorded in the jit 
trace
     #
+    OS_INT_PY_DIV               = 12   # python signed division (neg. 
corrected)
+    OS_INT_UDIV                 = 13   # regular unsigned division
+    OS_INT_PY_MOD               = 14   # python signed modulo (neg. corrected)
+    OS_INT_UMOD                 = 15   # regular unsigned modulo
+    #
     OS_STR_CONCAT               = 22   # "stroruni.concat"
     OS_STR_SLICE                = 23   # "stroruni.slice"
     OS_STR_EQUAL                = 24   # "stroruni.equal"
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
@@ -436,6 +436,8 @@
         # dispatch to various implementations depending on the oopspec_name
         if oopspec_name.startswith('list.') or 
oopspec_name.startswith('newlist'):
             prepare = self._handle_list_call
+        elif oopspec_name.startswith('int.'):
+            prepare = self._handle_int_special
         elif oopspec_name.startswith('stroruni.'):
             prepare = self._handle_stroruni_call
         elif oopspec_name == 'str.str2unicode':
@@ -518,23 +520,12 @@
 
     # XXX some of the following functions should not become residual calls
     # but be really compiled
-    rewrite_op_int_floordiv_ovf_zer   = _do_builtin_call
-    rewrite_op_int_floordiv_ovf       = _do_builtin_call
-    rewrite_op_int_floordiv_zer       = _do_builtin_call
-    rewrite_op_int_mod_ovf_zer        = _do_builtin_call
-    rewrite_op_int_mod_ovf            = _do_builtin_call
-    rewrite_op_int_mod_zer            = _do_builtin_call
-    rewrite_op_int_lshift_ovf         = _do_builtin_call
     rewrite_op_int_abs                = _do_builtin_call
     rewrite_op_llong_abs              = _do_builtin_call
     rewrite_op_llong_floordiv         = _do_builtin_call
-    rewrite_op_llong_floordiv_zer     = _do_builtin_call
     rewrite_op_llong_mod              = _do_builtin_call
-    rewrite_op_llong_mod_zer          = _do_builtin_call
     rewrite_op_ullong_floordiv        = _do_builtin_call
-    rewrite_op_ullong_floordiv_zer    = _do_builtin_call
     rewrite_op_ullong_mod             = _do_builtin_call
-    rewrite_op_ullong_mod_zer         = _do_builtin_call
     rewrite_op_gc_identityhash        = _do_builtin_call
     rewrite_op_gc_id                  = _do_builtin_call
     rewrite_op_gc_pin                 = _do_builtin_call
@@ -1532,12 +1523,6 @@
                 return self.rewrite_operation(op1)
         ''' % (_old, _new)).compile()
 
-    def rewrite_op_int_neg_ovf(self, op):
-        op1 = SpaceOperation('int_sub_ovf',
-                             [Constant(0, lltype.Signed), op.args[0]],
-                             op.result)
-        return self.rewrite_operation(op1)
-
     def rewrite_op_float_is_true(self, op):
         op1 = SpaceOperation('float_ne',
                              [op.args[0], Constant(0.0, lltype.Float)],
@@ -1929,6 +1914,20 @@
                 llmemory.cast_ptr_to_adr(c_func.value))
         self.callcontrol.callinfocollection.add(oopspecindex, calldescr, func)
 
+    def _handle_int_special(self, op, oopspec_name, args):
+        if oopspec_name == 'int.neg_ovf':
+            [v_x] = args
+            op0 = SpaceOperation('int_sub_ovf',
+                                 [Constant(0, lltype.Signed), v_x],
+                                 op.result)
+            return self.rewrite_operation(op0)
+        else:
+            # int.py_div, int.udiv, int.py_mod, int.umod
+            opname = oopspec_name.replace('.', '_')
+            os = getattr(EffectInfo, 'OS_' + opname.upper())
+            return self._handle_oopspec_call(op, args, os,
+                                    EffectInfo.EF_ELIDABLE_CANNOT_RAISE)
+
     def _handle_stroruni_call(self, op, oopspec_name, args):
         SoU = args[0].concretetype     # Ptr(STR) or Ptr(UNICODE)
         can_raise_memoryerror = {
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
@@ -243,45 +243,6 @@
     return llop.jit_force_virtual(lltype.typeOf(inst), inst)
 
 
-def _ll_2_int_floordiv_ovf_zer(x, y):
-    if y == 0:
-        raise ZeroDivisionError
-    return _ll_2_int_floordiv_ovf(x, y)
-
-def _ll_2_int_floordiv_ovf(x, y):
-    # intentionally not short-circuited to produce only one guard
-    # and to remove the check fully if one of the arguments is known
-    if (x == -sys.maxint - 1) & (y == -1):
-        raise OverflowError
-    return llop.int_floordiv(lltype.Signed, x, y)
-
-def _ll_2_int_floordiv_zer(x, y):
-    if y == 0:
-        raise ZeroDivisionError
-    return llop.int_floordiv(lltype.Signed, x, y)
-
-def _ll_2_int_mod_ovf_zer(x, y):
-    if y == 0:
-        raise ZeroDivisionError
-    return _ll_2_int_mod_ovf(x, y)
-
-def _ll_2_int_mod_ovf(x, y):
-    #see comment in _ll_2_int_floordiv_ovf
-    if (x == -sys.maxint - 1) & (y == -1):
-        raise OverflowError
-    return llop.int_mod(lltype.Signed, x, y)
-
-def _ll_2_int_mod_zer(x, y):
-    if y == 0:
-        raise ZeroDivisionError
-    return llop.int_mod(lltype.Signed, x, y)
-
-def _ll_2_int_lshift_ovf(x, y):
-    result = x << y
-    if (result >> y) != x:
-        raise OverflowError
-    return result
-
 def _ll_1_int_abs(x):
     # this version doesn't branch
     mask = x >> (LONG_BIT - 1)
@@ -452,51 +413,9 @@
     else:
         return xll
 
-def _ll_2_llong_floordiv(xll, yll):
-    return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
-
-def _ll_2_llong_floordiv_zer(xll, yll):
-    if yll == 0:
-        raise ZeroDivisionError
-    return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
-
-def _ll_2_llong_mod(xll, yll):
-    return llop.llong_mod(lltype.SignedLongLong, xll, yll)
-
-def _ll_2_llong_mod_zer(xll, yll):
-    if yll == 0:
-        raise ZeroDivisionError
-    return llop.llong_mod(lltype.SignedLongLong, xll, yll)
-
-def _ll_2_ullong_floordiv(xll, yll):
-    return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
-
-def _ll_2_ullong_floordiv_zer(xll, yll):
-    if yll == 0:
-        raise ZeroDivisionError
-    return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
-
-def _ll_2_ullong_mod(xll, yll):
-    return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
-
-def _ll_2_ullong_mod_zer(xll, yll):
-    if yll == 0:
-        raise ZeroDivisionError
-    return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
-
-def _ll_2_uint_mod(xll, yll):
-    return llop.uint_mod(lltype.Unsigned, xll, yll)
-
 
 # in the following calls to builtins, the JIT is allowed to look inside:
 inline_calls_to = [
-    ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_floordiv_ovf',     [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_floordiv_zer',     [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_mod_ovf_zer',      [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_mod_ovf',          [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_mod_zer',          [lltype.Signed, lltype.Signed], lltype.Signed),
-    ('int_lshift_ovf',       [lltype.Signed, lltype.Signed], lltype.Signed),
     ('int_abs',              [lltype.Signed],                lltype.Signed),
     ('ll_math.ll_math_sqrt', [lltype.Float],                 lltype.Float),
 ]
diff --git a/rpython/jit/codewriter/test/test_flatten.py 
b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -478,7 +478,7 @@
             except ZeroDivisionError:
                 return -42
         self.encoding_test(f, [7, 2], """
-            residual_call_ir_i $<* fn int_floordiv_ovf_zer>, I[%i0, %i1], R[], 
<Descr> -> %i2
+            residual_call_ir_i $<* fn ll_int_floordiv_ovf_zer__Signed_Signed>, 
I[%i0, %i1], R[], <Descr> -> %i2
             -live-
             catch_exception L1
             int_return %i2
@@ -505,7 +505,7 @@
                 return 42
         # XXX so far, this really produces a int_mod_ovf_zer...
         self.encoding_test(f, [7, 2], """
-            residual_call_ir_i $<* fn int_mod_ovf_zer>, I[%i0, %i1], R[], 
<Descr> -> %i2
+            residual_call_ir_i $<* fn ll_int_mod_ovf_zer__Signed_Signed>, 
I[%i0, %i1], R[], <Descr> -> %i2
             -live-
             catch_exception L1
             int_return %i2
@@ -548,6 +548,36 @@
             int_return $42
         """, transform=True, liveness=True)
 
+    def test_int_sub_ovf(self):
+        def f(i, j):
+            try:
+                return ovfcheck(i - j)
+            except OverflowError:
+                return 42
+        self.encoding_test(f, [7, 2], """
+            -live- %i0, %i1
+            int_sub_jump_if_ovf L1, %i0, %i1 -> %i2
+            int_return %i2
+            ---
+            L1:
+            int_return $42
+        """, transform=True, liveness=True)
+
+    def test_int_mul_ovf(self):
+        def f(i, j):
+            try:
+                return ovfcheck(i * j)
+            except OverflowError:
+                return 42
+        self.encoding_test(f, [7, 2], """
+            -live- %i0, %i1
+            int_mul_jump_if_ovf L1, %i0, %i1 -> %i2
+            int_return %i2
+            ---
+            L1:
+            int_return $42
+        """, transform=True, liveness=True)
+
     def test_multiple_int_add_ovf(self):
         def f(i, j):
             try:
diff --git a/rpython/jit/codewriter/test/test_jtransform.py 
b/rpython/jit/codewriter/test/test_jtransform.py
--- a/rpython/jit/codewriter/test/test_jtransform.py
+++ b/rpython/jit/codewriter/test/test_jtransform.py
@@ -135,6 +135,10 @@
              EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR),
              EI.OS_RAW_FREE:             ([ARRAYPTR], lltype.Void),
              EI.OS_THREADLOCALREF_GET:   ([INT], INT),   # for example
+             EI.OS_INT_PY_DIV: ([INT, INT], INT),
+             EI.OS_INT_UDIV:   ([INT, INT], INT),
+             EI.OS_INT_PY_MOD: ([INT, INT], INT),
+             EI.OS_INT_UMOD:   ([INT, INT], INT),
             }
             argtypes = argtypes[oopspecindex]
             assert argtypes[0] == [v.concretetype for v in op.args[1:]]
@@ -268,15 +272,17 @@
                     assert op1.result == v3
                     assert op1.opname == name2[0]
 
-def test_symmetric_int_add_ovf():
+@py.test.mark.parametrize('opname', ['add_ovf', 'sub_ovf', 'mul_ovf'])
+def test_int_op_ovf(opname):
     v3 = varoftype(lltype.Signed)
     for v1 in [varoftype(lltype.Signed), const(42)]:
         for v2 in [varoftype(lltype.Signed), const(43)]:
-            op = SpaceOperation('int_add_nonneg_ovf', [v1, v2], v3)
+            op = SpaceOperation('int_' + opname, [v1, v2], v3)
             oplist = Transformer(FakeCPU()).rewrite_operation(op)
             op1, op0 = oplist
-            assert op0.opname == 'int_add_ovf'
-            if isinstance(v1, Constant) and isinstance(v2, Variable):
+            assert op0.opname == 'int_' + opname
+            if (isinstance(v1, Constant) and isinstance(v2, Variable)
+                    and opname != 'sub_ovf'):
                 assert op0.args == [v2, v1]
                 assert op0.result == v3
             else:
@@ -286,6 +292,34 @@
             assert op1.args == []
             assert op1.result is None
 
+def test_neg_ovf():
+    v3 = varoftype(lltype.Signed)
+    for v1 in [varoftype(lltype.Signed), const(42)]:
+        op = SpaceOperation('direct_call', [Constant('neg_ovf'), v1], v3)
+        oplist = Transformer(FakeCPU())._handle_int_special(op, 'int.neg_ovf',
+                                                            [v1])
+        op1, op0 = oplist
+        assert op0.opname == 'int_sub_ovf'
+        assert op0.args == [Constant(0), v1]
+        assert op0.result == v3
+        assert op1.opname == '-live-'
+        assert op1.args == []
+        assert op1.result is None
+
+@py.test.mark.parametrize('opname', ['py_div', 'udiv', 'py_mod', 'umod'])
+def test_int_op_residual(opname):
+    v3 = varoftype(lltype.Signed)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    for v1 in [varoftype(lltype.Signed), const(42)]:
+        for v2 in [varoftype(lltype.Signed), const(43)]:
+            op = SpaceOperation('direct_call', [Constant(opname), v1, v2], v3)
+            op0 = tr._handle_int_special(op, 'int.'+opname, [v1, v2])
+            assert op0.opname == 'residual_call_ir_i'
+            assert op0.args[0].value == opname  # pseudo-function as str
+            expected = ('int_' + opname).upper()
+            assert (op0.args[-1] == 'calldescr-%d' %
+                     getattr(effectinfo.EffectInfo, 'OS_' + expected))
+
 def test_calls():
     for RESTYPE, with_void, with_i, with_r, with_f in product(
         [lltype.Signed, rclass.OBJECTPTR, lltype.Float, lltype.Void],
diff --git a/rpython/jit/metainterp/blackhole.py 
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -430,19 +430,6 @@
             return 0, label
 
     @arguments("i", "i", returns="i")
-    def bhimpl_int_floordiv(a, b):
-        return llop.int_floordiv(lltype.Signed, a, b)
-
-    @arguments("i", "i", returns="i")
-    def bhimpl_uint_floordiv(a, b):
-        c = llop.uint_floordiv(lltype.Unsigned, r_uint(a), r_uint(b))
-        return intmask(c)
-
-    @arguments("i", "i", returns="i")
-    def bhimpl_int_mod(a, b):
-        return llop.int_mod(lltype.Signed, a, b)
-
-    @arguments("i", "i", returns="i")
     def bhimpl_int_and(a, b):
         return a & b
 
diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py 
b/rpython/jit/metainterp/optimizeopt/dependency.py
--- a/rpython/jit/metainterp/optimizeopt/dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/dependency.py
@@ -929,10 +929,10 @@
     """
     exec py.code.Source(multiplicative_func_source
             .format(name='INT_MUL', op='*', tgt='mul', cop='*')).compile()
-    exec py.code.Source(multiplicative_func_source
-            .format(name='INT_FLOORDIV', op='*', tgt='div', cop='/')).compile()
-    exec py.code.Source(multiplicative_func_source
-            .format(name='UINT_FLOORDIV', op='*', tgt='div', 
cop='/')).compile()
+    #exec py.code.Source(multiplicative_func_source
+    #        .format(name='INT_PY_DIV', op='*', tgt='div', cop='/')).compile()
+    #exec py.code.Source(multiplicative_func_source
+    #        .format(name='UINT_FLOORDIV', op='*', tgt='div', 
cop='/')).compile()
     del multiplicative_func_source
 
     array_access_source = """
@@ -1042,9 +1042,11 @@
             var = ResOperation(rop.INT_MUL, args)
             opt.emit_operation(var)
         if self.coefficient_div != 1:
-            args = [var, ConstInt(self.coefficient_div)]
-            var = ResOperation(rop.INT_FLOORDIV, args)
-            opt.emit_operation(var)
+            assert 0   # XXX for now; should never be the case with handling
+                       # of INT_PY_DIV commented out in this file...
+            #args = [var, ConstInt(self.coefficient_div)]
+            #var = ResOperation(rop.INT_FLOORDIV, args)
+            #opt.emit_operation(var)
         if self.constant > 0:
             args = [var, ConstInt(self.constant)]
             var = ResOperation(rop.INT_ADD, args)
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
@@ -8,6 +8,7 @@
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop, AbstractResOp
 from rpython.jit.metainterp.optimizeopt import vstring
+from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.rlib.rarithmetic import intmask
 
 def get_integer_min(is_unsigned, byte_size):
@@ -172,39 +173,50 @@
         if b.bounded():
             r.intersect(b)
 
-    def optimize_INT_FLOORDIV(self, op):
-        b1 = self.getintbound(op.getarg(0))
-        b2 = self.getintbound(op.getarg(1))
+    def optimize_CALL_PURE_I(self, op):
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.
+        effectinfo = op.getdescr().get_extra_info()
+        oopspecindex = effectinfo.oopspecindex
+        if oopspecindex == EffectInfo.OS_INT_PY_DIV:
+            self.opt_call_INT_PY_DIV(op)
+            return
+        elif oopspecindex == EffectInfo.OS_INT_PY_MOD:
+            self.opt_call_INT_PY_MOD(op)
+            return
+        self.emit_operation(op)
+
+    def opt_call_INT_PY_DIV(self, op):
+        b1 = self.getintbound(op.getarg(1))
+        b2 = self.getintbound(op.getarg(2))
         self.emit_operation(op)
         r = self.getintbound(op)
-        r.intersect(b1.div_bound(b2))
+        r.intersect(b1.py_div_bound(b2))
 
-    def optimize_INT_MOD(self, op):
-        b1 = self.getintbound(op.getarg(0))
-        b2 = self.getintbound(op.getarg(1))
-        known_nonneg = (b1.known_ge(IntBound(0, 0)) and
-                        b2.known_ge(IntBound(0, 0)))
-        if known_nonneg and b2.is_constant():
+    def opt_call_INT_PY_MOD(self, op):
+        b1 = self.getintbound(op.getarg(1))
+        b2 = self.getintbound(op.getarg(2))
+        if b2.is_constant():
             val = b2.getint()
-            if (val & (val-1)) == 0:
-                # nonneg % power-of-two ==> nonneg & (power-of-two - 1)
-                arg1 = op.getarg(0)
+            if val > 0 and (val & (val-1)) == 0:
+                # x % power-of-two ==> x & (power-of-two - 1)
+                # with Python's modulo, this is valid even if 'x' is negative.
+                from rpython.jit.metainterp.history import DONT_CHANGE
+                arg1 = op.getarg(1)
                 arg2 = ConstInt(val-1)
                 op = self.replace_op_with(op, rop.INT_AND,
-                                          args=[arg1, arg2])
+                                          args=[arg1, arg2],
+                                          descr=DONT_CHANGE)  # <- xxx rename?
         self.emit_operation(op)
         if b2.is_constant():
             val = b2.getint()
             r = self.getintbound(op)
-            if val < 0:
-                if val == -sys.maxint-1:
-                    return     # give up
-                val = -val
-            if known_nonneg:
+            if val >= 0:        # with Python's modulo:  0 <= (x % pos) < pos
                 r.make_ge(IntBound(0, 0))
-            else:
-                r.make_gt(IntBound(-val, -val))
-            r.make_lt(IntBound(val, val))
+                r.make_lt(IntBound(val, val))
+            else:               # with Python's modulo:  neg < (x % neg) <= 0
+                r.make_gt(IntBound(val, val))
+                r.make_le(IntBound(0, 0))
 
     def optimize_INT_LSHIFT(self, op):
         arg0 = self.get_box_replacement(op.getarg(0))
@@ -613,10 +625,10 @@
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
         r = self.getintbound(op)
-        b = r.div_bound(b2)
+        b = r.py_div_bound(b2)
         if b1.intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
-        b = r.div_bound(b1)
+        b = r.py_div_bound(b1)
         if b2.intersect(b):
             self.propagate_bounds_backward(op.getarg(1))
 
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py 
b/rpython/jit/metainterp/optimizeopt/intutils.py
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -174,16 +174,21 @@
         else:
             return IntUnbounded()
 
-    def div_bound(self, other):
+    def py_div_bound(self, other):
         if self.has_upper and self.has_lower and \
            other.has_upper and other.has_lower and \
-           not other.contains(0) and self.lower > (-sys.maxint-1):
-            vals = (
-                llop.int_floordiv(lltype.Signed, self.upper, other.upper),
-                llop.int_floordiv(lltype.Signed, self.upper, other.lower),
-                llop.int_floordiv(lltype.Signed, self.lower, other.upper),
-                llop.int_floordiv(lltype.Signed, self.lower, other.lower))
-            return IntBound(min4(vals), max4(vals))
+           not other.contains(0):
+            try:
+                # this gives the bounds for 'int_py_div', so use the
+                # Python-style handling of negative numbers and not
+                # the C-style one
+                vals = (ovfcheck(self.upper / other.upper),
+                        ovfcheck(self.upper / other.lower),
+                        ovfcheck(self.lower / other.upper),
+                        ovfcheck(self.lower / other.lower))
+                return IntBound(min4(vals), max4(vals))
+            except OverflowError:
+                return IntUnbounded()
         else:
             return IntUnbounded()
 
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py 
b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -168,13 +168,13 @@
                         break
             self.emit_operation(op)
 
-    def optimize_UINT_FLOORDIV(self, op):
-        b2 = self.getintbound(op.getarg(1))
-
+    def _optimize_CALL_INT_UDIV(self, op):
+        b2 = self.getintbound(op.getarg(2))
         if b2.is_constant() and b2.getint() == 1:
-            self.make_equal_to(op, op.getarg(0))
-        else:
-            self.emit_operation(op)
+            self.make_equal_to(op, op.getarg(1))
+            self.last_emitted_operation = REMOVED
+            return True
+        return False
 
     def optimize_INT_LSHIFT(self, op):
         b1 = self.getintbound(op.getarg(0))
@@ -663,6 +663,16 @@
             self.make_constant(op, result)
             self.last_emitted_operation = REMOVED
             return
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.
+        effectinfo = op.getdescr().get_extra_info()
+        oopspecindex = effectinfo.oopspecindex
+        if oopspecindex == EffectInfo.OS_INT_UDIV:
+            if self._optimize_CALL_INT_UDIV(op):
+                return
+        elif oopspecindex == EffectInfo.OS_INT_PY_DIV:
+            if self._optimize_CALL_INT_PY_DIV(op):
+                return
         self.emit_operation(op)
     optimize_CALL_PURE_R = optimize_CALL_PURE_I
     optimize_CALL_PURE_F = optimize_CALL_PURE_I
@@ -678,24 +688,31 @@
     def optimize_GUARD_FUTURE_CONDITION(self, op):
         self.optimizer.notice_guard_future_condition(op)
 
-    def optimize_INT_FLOORDIV(self, op):
-        arg0 = op.getarg(0)
-        b1 = self.getintbound(arg0)
+    def _optimize_CALL_INT_PY_DIV(self, op):
         arg1 = op.getarg(1)
-        b2 = self.getintbound(arg1)
+        b1 = self.getintbound(arg1)
+        arg2 = op.getarg(2)
+        b2 = self.getintbound(arg2)
 
-        if b2.is_constant() and b2.getint() == 1:
-            self.make_equal_to(op, arg0)
-            return
-        elif b1.is_constant() and b1.getint() == 0:
+        if b1.is_constant() and b1.getint() == 0:
             self.make_constant_int(op, 0)
-            return
-        if b1.known_ge(IntBound(0, 0)) and b2.is_constant():
+            self.last_emitted_operation = REMOVED
+            return True
+        # This is Python's integer division: 'x // (2**shift)' can always
+        # be replaced with 'x >> shift', even for negative values of x
+        if b2.is_constant():
             val = b2.getint()
-            if val & (val - 1) == 0 and val > 0: # val == 2**shift
+            if val == 1:
+                self.make_equal_to(op, arg1)
+                self.last_emitted_operation = REMOVED
+                return True
+            elif val > 0 and val & (val - 1) == 0:   # val == 2**shift
+                from rpython.jit.metainterp.history import DONT_CHANGE
                 op = self.replace_op_with(op, rop.INT_RSHIFT,
-                            args = [op.getarg(0), ConstInt(highest_bit(val))])
+                            args=[arg1, ConstInt(highest_bit(val))],
+                            descr=DONT_CHANGE)  # <- xxx rename? means "kill"
         self.emit_operation(op)
+        return True
 
     def optimize_CAST_PTR_TO_INT(self, op):
         self.optimizer.pure_reverse(op)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py 
b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -244,19 +244,18 @@
     from rpython.rtyper.lltypesystem.lloperation import llop
     for _, _, b1 in some_bounds():
         for _, _, b2 in some_bounds():
-            b3 = b1.div_bound(b2)
+            b3 = b1.py_div_bound(b2)
             for n1 in nbr:
                 for n2 in nbr:
                     if b1.contains(n1) and b2.contains(n2):
                         if n2 != 0:
-                            assert b3.contains(
-                                llop.int_floordiv(lltype.Signed, n1, n2))
+                            assert b3.contains(n1 / n2)   # Python-style div
 
-    a=bound(2, 4).div_bound(bound(1, 2))
+    a=bound(2, 4).py_div_bound(bound(1, 2))
     assert not a.contains(0)
     assert not a.contains(5)
 
-    a=bound(-3, 2).div_bound(bound(1, 2))
+    a=bound(-3, 2).py_div_bound(bound(1, 2))
     assert not a.contains(-4)
     assert not a.contains(3)
     assert a.contains(-3)
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
@@ -1849,7 +1849,7 @@
 
         ops = """
         [i0]
-        i1 = int_floordiv(0, i0)
+        i1 = int_mul(0, i0)
         jump(i1)
         """
         expected = """
@@ -1858,6 +1858,17 @@
         """
         self.optimize_loop(ops, expected)
 
+        ops = """
+        [i0]
+        i1 = int_mul(1, i0)
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_fold_partially_constant_ops_ovf(self):
         ops = """
         [i0]
@@ -4111,21 +4122,6 @@
 
     # ----------
     def optimize_strunicode_loop_extradescrs(self, ops, optops):
-        class FakeCallInfoCollection:
-            def callinfo_for_oopspec(self, oopspecindex):
-                calldescrtype = type(LLtypeMixin.strequaldescr)
-                effectinfotype = 
type(LLtypeMixin.strequaldescr.get_extra_info())
-                for value in LLtypeMixin.__dict__.values():
-                    if isinstance(value, calldescrtype):
-                        extra = value.get_extra_info()
-                        if (extra and isinstance(extra, effectinfotype) and
-                            extra.oopspecindex == oopspecindex):
-                            # returns 0 for 'func' in this test
-                            return value, 0
-                raise AssertionError("not found: oopspecindex=%d" %
-                                     oopspecindex)
-        #
-        self.callinfocollection = FakeCallInfoCollection()
         self.optimize_strunicode_loop(ops, optops)
 
     def test_str_equal_noop1(self):
@@ -4642,102 +4638,89 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_intdiv_bounds(self):
+        ops = """
+        [i0]
+        i2 = call_pure_i(321, i0, 3, descr=int_py_div_descr)
+        i3 = int_add_ovf(i2, 50)
+        guard_no_overflow() []
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i2 = call_i(321, i0, 3, descr=int_py_div_descr)
+        i3 = int_add(i2, 50)
+        jump(i3)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_intmod_bounds(self):
         ops = """
         [i0, i1]
-        i2 = int_mod(i0, 12)
-        i3 = int_gt(i2, 12)
+        i2 = call_pure_i(321, i0, 12, descr=int_py_mod_descr)
+        i3 = int_ge(i2, 12)
         guard_false(i3) []
-        i4 = int_lt(i2, -12)
+        i4 = int_lt(i2, 0)
         guard_false(i4) []
-        i5 = int_mod(i1, -12)
-        i6 = int_lt(i5, -12)
+        i5 = call_pure_i(321, i1, -12, descr=int_py_mod_descr)
+        i6 = int_le(i5, -12)
         guard_false(i6) []
-        i7 = int_gt(i5, 12)
+        i7 = int_gt(i5, 0)
         guard_false(i7) []
         jump(i2, i5)
         """
         expected = """
         [i0, i1]
-        i2 = int_mod(i0, 12)
-        i5 = int_mod(i1, -12)
+        i2 = call_i(321, i0, 12, descr=int_py_mod_descr)
+        i5 = call_i(321, i1, -12, descr=int_py_mod_descr)
         jump(i2, i5)
         """
         self.optimize_loop(ops, expected)
 
-        # This the sequence of resoperations that is generated for a Python
-        # app-level int % int.  When the modulus is constant and when i0
-        # is known non-negative it should be optimized to a single int_mod.
+        # same as above, but all guards are shifted by one so that they
+        # must stay
+        ops = """
+        [i8, i9]
+        i0 = escape_i()
+        i2 = call_pure_i(321, i0, 12, descr=int_py_mod_descr)
+        i3 = int_ge(i2, 11)
+        guard_false(i3) []
+        i4 = int_lt(i2, 1)
+        guard_false(i4) []
+        i1 = escape_i()
+        i5 = call_pure_i(321, i1, -12, descr=int_py_mod_descr)
+        i6 = int_le(i5, -11)
+        guard_false(i6) []
+        i7 = int_gt(i5, -1)
+        guard_false(i7) []
+        jump(i2, i5)
+        """
+        self.optimize_loop(ops, ops.replace('call_pure_i', 'call_i'))
+
+        # 'n % power-of-two' can always be turned into int_and(), even
+        # if n is possibly negative.  That's by we handle 'int_py_mod'
+        # and not C-like mod.
         ops = """
         [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
-        i1 = int_mod(i0, 42)
-        i2 = int_rshift(i1, %d)
-        i3 = int_and(42, i2)
-        i4 = int_add(i1, i3)
-        finish(i4)
-        """ % (LONG_BIT-1)
+        i1 = call_pure_i(321, i0, 8, descr=int_py_mod_descr)
+        finish(i1)
+        """
         expected = """
         [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
-        i1 = int_mod(i0, 42)
-        finish(i1)
-        """
-        self.optimize_loop(ops, expected)
-
-        # '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)
 
-    def test_intmod_bounds_harder(self):
-        py.test.skip("harder")
-        # 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).
+    def test_intmod_bounds_bug1(self):
         ops = """
         [i0]
-        i1 = int_mod(i0, 16)
-        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)
-        finish(i4)
-        """
-        self.optimize_loop(ops, expected)
-
-    def test_intmod_bounds_bug1(self):
-        ops = """
-        [i0]
-        i1 = int_mod(i0, %d)
+        i1 = call_pure_i(321, i0, %d, descr=int_py_mod_descr)
         i2 = int_eq(i1, 0)
         guard_false(i2) []
         finish()
         """ % (-(1<<(LONG_BIT-1)),)
-        self.optimize_loop(ops, ops)
+        self.optimize_loop(ops, ops.replace('call_pure_i', 'call_i'))
 
     def test_bounded_lazy_setfield(self):
         ops = """
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -3493,7 +3493,7 @@
     def test_fold_partially_constant_uint_floordiv(self):
         ops = """
         [i0]
-        i1 = uint_floordiv(i0, 1)
+        i1 = call_pure_i(321, i0, 1, descr=int_udiv_descr)
         jump(i1)
         """
         expected = """
@@ -5247,13 +5247,13 @@
         guard_true(it1) []
         it2 = int_gt(i2, 0)
         guard_true(it2) []
-        ix2 = int_floordiv(i0, i1)
+        ix2 = call_pure_i(321, i0, i1, descr=int_py_div_descr)
         ix2t = int_ge(ix2, 0)
         guard_true(ix2t) []
-        ix3 = int_floordiv(i1, i0)
+        ix3 = call_pure_i(321, i1, i0, descr=int_py_div_descr)
         ix3t = int_ge(ix3, 0)
         guard_true(ix3t) []
-        ix4 = int_floordiv(i1, i2)
+        ix4 = call_pure_i(321, i1, i2, descr=int_py_div_descr)
         ix4t = int_ge(ix4, 0)
         guard_true(ix4t) []
         jump(i0, i1, i2)
@@ -5264,13 +5264,14 @@
         guard_true(it1) []
         it2 = int_gt(i2, 0)
         guard_true(it2) []
-        ix2 = int_floordiv(i0, i1)
+        ix2 = call_i(321, i0, i1, descr=int_py_div_descr)
         ix2t = int_ge(ix2, 0)
         guard_true(ix2t) []
-        ix3 = int_floordiv(i1, i0)
+        ix3 = call_i(321, i1, i0, descr=int_py_div_descr)
         ix3t = int_ge(ix3, 0)
         guard_true(ix3t) []
-        ix4 = int_floordiv(i1, i2)
+        ix4 = call_i(321, i1, i2, descr=int_py_div_descr)
+        # <== the check that ix4 is nonnegative was removed
         jump(i0, i1, i2)
         """
         expected = """
@@ -5314,92 +5315,38 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
-    def test_division(self):
-        ops = """
-        [i7, i6, i8]
-        it1 = int_gt(i7, 0)
-        guard_true(it1) []
-        it2 = int_gt(i6, 0)
-        guard_true(it2) []
-        i13 = int_is_zero(i6)
-        guard_false(i13) []
-        i15 = int_and(i8, i6)
-        i17 = int_eq(i15, -1)
-        guard_false(i17) []
-        i18 = int_floordiv(i7, i6)
-        i19 = int_xor(i7, i6)
-        i21 = int_lt(i19, 0)
-        i22 = int_mod(i7, i6)
-        i23 = int_is_true(i22)
-        i24 = int_and(i21, i23)
-        i25 = int_sub(i18, i24)
-        jump(i7, i25, i8)
-        """
-        preamble = """
-        [i7, i6, i8]
-        it1 = int_gt(i7, 0)
-        guard_true(it1) []
-        it2 = int_gt(i6, 0)
-        guard_true(it2) []
-        i15 = int_and(i8, i6)
-        i17 = int_eq(i15, -1)
-        guard_false(i17) []
-        i18 = int_floordiv(i7, i6)
-        i19 = int_xor(i7, i6)
-        i22 = int_mod(i7, i6)
-        i23 = int_is_true(i22)
-        jump(i7, i18, i8)
-        """
-        expected = """
-        [i7, i6, i8]
-        it2 = int_gt(i6, 0)
-        guard_true(it2) []
-        i15 = int_and(i8, i6)
-        i17 = int_eq(i15, -1)
-        guard_false(i17) []
-        i18 = int_floordiv(i7, i6)
-        i19 = int_xor(i7, i6)
-        i22 = int_mod(i7, i6)
-        i23 = int_is_true(i22)
-        jump(i7, i18, i8)
-        """
-        self.optimize_loop(ops, expected, preamble)
-
     def test_division_to_rshift(self):
         ops = """
         [i1, i2]
-        it = int_gt(i1, 0)
-        guard_true(it)[]
-        i3 = int_floordiv(i1, i2)
-        i4 = int_floordiv(2, i2)
-        i5 = int_floordiv(i1, 2)
-        i6 = int_floordiv(3, i2)
-        i7 = int_floordiv(i1, 3)
-        i8 = int_floordiv(4, i2)
-        i9 = int_floordiv(i1, 4)
-        i10 = int_floordiv(i1, 0)
-        i11 = int_floordiv(i1, 1)
-        i12 = int_floordiv(i2, 2)
-        i13 = int_floordiv(i2, 3)
-        i14 = int_floordiv(i2, 4)
-        jump(i5, i14)
+        i3 = call_pure_i(321, i1, i2, descr=int_py_div_descr)
+        i4 = call_pure_i(322, 2, i2, descr=int_py_div_descr)
+        i6 = call_pure_i(323, 3, i2, descr=int_py_div_descr)
+        i8 = call_pure_i(324, 4, i2, descr=int_py_div_descr)
+        i9b = call_pure_i(325, i1, -2, descr=int_py_div_descr)
+        i9c = call_pure_i(326, i1, -1, descr=int_py_div_descr)
+        i10 = call_pure_i(327, i1, 0, descr=int_py_div_descr)
+        i11 = call_pure_i(328, i1, 1, descr=int_py_div_descr)
+        i5 = call_pure_i(329, i1, 2, descr=int_py_div_descr)
+        i7 = call_pure_i(330, i1, 3, descr=int_py_div_descr)
+        i9 = call_pure_i(331, i1, 4, descr=int_py_div_descr)
+        i9d = call_pure_i(332, i1, 6, descr=int_py_div_descr)
+        jump(i5, i9)
         """
         expected = """
         [i1, i2]
-        it = int_gt(i1, 0)
-        guard_true(it)[]
-        i3 = int_floordiv(i1, i2)
-        i4 = int_floordiv(2, i2)
+        i3 = call_i(321, i1, i2, descr=int_py_div_descr)
+        i4 = call_i(322, 2, i2, descr=int_py_div_descr)
+        i6 = call_i(323, 3, i2, descr=int_py_div_descr)
+        i8 = call_i(324, 4, i2, descr=int_py_div_descr)
+        i9b = call_i(325, i1, -2, descr=int_py_div_descr)
+        i9c = call_i(326, i1, -1, descr=int_py_div_descr)
+        i10 = call_i(327, i1, 0, descr=int_py_div_descr)
+        # i11 = i1
         i5 = int_rshift(i1, 1)
-        i6 = int_floordiv(3, i2)
-        i7 = int_floordiv(i1, 3)
-        i8 = int_floordiv(4, i2)
+        i7 = call_i(330, i1, 3, descr=int_py_div_descr)
         i9 = int_rshift(i1, 2)
-        i10 = int_floordiv(i1, 0)
-        i12 = int_floordiv(i2, 2)
-        i13 = int_floordiv(i2, 3)
-        i14 = int_floordiv(i2, 4)
-        jump(i5, i14)
+        i9d = call_i(332, i1, 6, descr=int_py_div_descr)
+        jump(i5, i9)
         """
         self.optimize_loop(ops, expected)
 
@@ -5475,7 +5422,7 @@
     def test_int_div_1(self):
         ops = """
         [i0]
-        i1 = int_floordiv(i0, 1)
+        i1 = call_pure_i(321, i0, 1, descr=int_py_div_descr)
         jump(i1)
         """
         expected = """
@@ -5484,48 +5431,16 @@
         """
         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)
+        ops = """
+        [i0]
+        i1 = call_pure_i(321, 0, i0, descr=int_py_div_descr)
+        escape_n(i1)
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        escape_n(0)
+        jump(i0)
         """
         self.optimize_loop(ops, expected)
 
@@ -5538,15 +5453,15 @@
         guard_true(i2) []
         # here, -50 <= i4 <= -40
 
-        i5 = int_floordiv(i4, 30)
-        # here, we know that that i5 == -1  (C-style handling of negatives!)
+        i5 = call_pure_i(321, i4, 30, descr=int_py_div_descr)
+        # here, we know that that i5 == -2  (Python-style handling of 
negatives)
         escape_n(i5)
         jump(i4)
         """
         expected = """
         [i4, i5]
-        escape_n(-1)
-        jump(i4, -1)
+        escape_n(-2)
+        jump(i4, -2)
         """
         self.optimize_loop(ops, expected)
 
@@ -6782,21 +6697,6 @@
 
     # ----------
     def optimize_strunicode_loop_extradescrs(self, ops, optops, preamble):
-        class FakeCallInfoCollection:
-            def callinfo_for_oopspec(self, oopspecindex):
-                calldescrtype = type(LLtypeMixin.strequaldescr)
-                effectinfotype = 
type(LLtypeMixin.strequaldescr.get_extra_info())
-                for value in LLtypeMixin.__dict__.values():
-                    if isinstance(value, calldescrtype):
-                        extra = value.get_extra_info()
-                        if (extra and isinstance(extra, effectinfotype) and
-                                extra.oopspecindex == oopspecindex):
-                            # returns 0 for 'func' in this test
-                            return value, 0
-                raise AssertionError("not found: oopspecindex=%d" %
-                                     oopspecindex)
-        #
-        self.callinfocollection = FakeCallInfoCollection()
         self.optimize_strunicode_loop(ops, optops, preamble)
 
     def test_str_equal_noop1(self):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py 
b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
@@ -397,8 +397,8 @@
         loop1 = self.parse_trace("""
         i10 = int_and(255, i1)
         i11 = int_and(255, i2)
-        i12 = uint_floordiv(i10,1)
-        i13 = uint_floordiv(i11,1)
+        i12 = call_pure_i(321, i10)
+        i13 = call_pure_i(321, i11)
         i14 = int_and(i1, i12)
         i15 = int_and(i2, i13)
         """)
@@ -412,9 +412,9 @@
         v4[2xi64] = vec_pack_i(v3[2xi64], i2, 1, 1)
         v5[2xi64] = vec_int_and(v1[2xi64], v4[2xi64])
         i10 = vec_unpack_i(v5[2xi64], 0, 1)
-        i12 = uint_floordiv(i10,1)
+        i12 = call_pure_i(321, i10)
         i11 = vec_unpack_i(v5[2xi64], 1, 1)
-        i13 = uint_floordiv(i11,1)
+        i13 = call_pure_i(321, i11)
         v6[0xi64] = vec_i()
         v7[1xi64] = vec_pack_i(v6[2xi64], i12, 0, 1)
         v8[2xi64] = vec_pack_i(v7[2xi64], i13, 1, 1)
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
@@ -421,8 +421,43 @@
     jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable)
     vref_descr = cpu.sizeof(vrefinfo.JIT_VIRTUAL_REF, jit_virtual_ref_vtable)
 
+    FUNC = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
+    ei = EffectInfo([], [], [], [], [], [], 
EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
+                    can_invalidate=False,
+                    oopspecindex=EffectInfo.OS_INT_PY_DIV)
+    int_py_div_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)
+    ei = EffectInfo([], [], [], [], [], [], 
EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
+                    can_invalidate=False,
+                    oopspecindex=EffectInfo.OS_INT_UDIV)
+    int_udiv_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)
+    ei = EffectInfo([], [], [], [], [], [], 
EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
+                    can_invalidate=False,
+                    oopspecindex=EffectInfo.OS_INT_PY_MOD)
+    int_py_mod_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)
+
     namespace = locals()
 
+
+class FakeCallInfoCollection:
+    def callinfo_for_oopspec(self, oopspecindex):
+        calldescrtype = type(LLtypeMixin.strequaldescr)
+        effectinfotype = type(LLtypeMixin.strequaldescr.get_extra_info())
+        for value in LLtypeMixin.__dict__.values():
+            if isinstance(value, calldescrtype):
+                extra = value.get_extra_info()
+                if (extra and isinstance(extra, effectinfotype) and
+                    extra.oopspecindex == oopspecindex):
+                    # returns 0 for 'func' in this test
+                    return value, 0
+        raise AssertionError("not found: oopspecindex=%d" %
+                             oopspecindex)
+
+    calldescr_udiv = LLtypeMixin.int_udiv_descr
+    #calldescr_umod = LLtypeMixin.int_umod_descr
+
+LLtypeMixin.callinfocollection = FakeCallInfoCollection()
+
+
 # ____________________________________________________________
 
 
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
@@ -659,6 +659,7 @@
         assert mref1.is_adjacent_after(mref5)
 
     def test_array_memory_ref_div(self):
+        py.test.skip("XXX rewrite or kill this test for the new divisions")
         ops = """
         [p0,i0]
         i1 = int_floordiv(i0,2)
@@ -724,7 +725,7 @@
         ops = """
         [p0,i0]
         i1 = int_add(i0,4)
-        i2 = int_floordiv(i1,2)
+        i2 = int_sub(i1,3)   # XXX used to be "divide by 2", not sure about it
         i3 = raw_load_i(p0,i2,descr=chararraydescr)
         i4 = int_add(i0,2)
         i5 = int_mul(i4,2)
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -201,11 +201,10 @@
 
     # ------------------------------
 
-    for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
+    for _opimpl in ['int_add', 'int_sub', 'int_mul',
                     'int_and', 'int_or', 'int_xor', 'int_signext',
                     'int_rshift', 'int_lshift', 'uint_rshift',
                     'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
-                    'uint_floordiv',
                     'float_add', 'float_sub', 'float_mul', 'float_truediv',
                     'float_lt', 'float_le', 'float_eq',
                     'float_ne', 'float_gt', 'float_ge',
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -955,9 +955,6 @@
     'INT_ADD/2/i',
     'INT_SUB/2/i',
     'INT_MUL/2/i',
-    'INT_FLOORDIV/2/i',
-    'UINT_FLOORDIV/2/i',
-    'INT_MOD/2/i',
     'INT_AND/2/i',
     'INT_OR/2/i',
     'INT_XOR/2/i',
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
@@ -586,7 +586,7 @@
         def internfn(y):
             return y * 3
         def externfn(y):
-            return y % 4
+            return y ^ 4
         def f(y):
             while y >= 0:
                 myjitdriver.can_enter_jit(y=y)
@@ -601,7 +601,7 @@
         policy = StopAtXPolicy(externfn)
         res = self.meta_interp(f, [31], policy=policy)
         assert res == 42
-        self.check_resops(int_mul=2, int_mod=0)
+        self.check_resops(int_mul=2, int_xor=0)
 
     def test_we_are_jitted(self):
         myjitdriver = JitDriver(greens = [], reds = ['y'])
@@ -936,10 +936,11 @@
                 myjitdriver.can_enter_jit(x=x, y=y, n=n)
                 myjitdriver.jit_merge_point(x=x, y=y, n=n)
                 n -= ovfcheck(x % y)
+                x += 1
             return n
         res = self.meta_interp(f, [20, 1, 2])
         assert res == 0
-        self.check_resops(call_i=0, call_r=0)
+        self.check_resops(call_i=2, int_eq=3, int_and=2)
 
     def test_abs(self):
         myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
@@ -1133,7 +1134,7 @@
             while n > 0:
                 mydriver.can_enter_jit(n=n, x=x)
                 mydriver.jit_merge_point(n=n, x=x)
-                if n % 2 == 0:
+                if n & 1 == 0:
                     cls = A
                 else:
                     cls = B
@@ -1173,7 +1174,6 @@
 
     def test_div_overflow(self):
         import sys
-        from rpython.rtyper.lltypesystem.lloperation import llop
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
         def f(x, y):
             res = 0
@@ -1181,15 +1181,13 @@
                 myjitdriver.can_enter_jit(x=x, y=y, res=res)
                 myjitdriver.jit_merge_point(x=x, y=y, res=res)
                 try:
-                    res += llop.int_floordiv_ovf(lltype.Signed,
-                                                 -sys.maxint-1, x)
+                    res += ovfcheck((-sys.maxint-1) // x)
                     x += 5
                 except OverflowError:
                     res += 100
                 y -= 1
             return res
-        res = self.meta_interp(f, [-41, 16])
-        assert res == ((-sys.maxint-1) // (-41) +
+        expected =    ((-sys.maxint-1) // (-41) +
                        (-sys.maxint-1) // (-36) +
                        (-sys.maxint-1) // (-31) +
                        (-sys.maxint-1) // (-26) +
@@ -1198,10 +1196,12 @@
                        (-sys.maxint-1) // (-11) +
                        (-sys.maxint-1) // (-6) +
                        100 * 8)
+        assert f(-41, 16) == expected
+        res = self.meta_interp(f, [-41, 16])
+        assert res == expected
 
     def test_overflow_fold_if_divisor_constant(self):
         import sys
-        from rpython.rtyper.lltypesystem.lloperation import llop
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
         def f(x, y):
             res = 0
@@ -1209,10 +1209,8 @@
                 myjitdriver.can_enter_jit(x=x, y=y, res=res)
                 myjitdriver.jit_merge_point(x=x, y=y, res=res)
                 try:
-                    res += llop.int_floordiv_ovf(lltype.Signed,
-                                                 x, 2)
-                    res += llop.int_mod_ovf(lltype.Signed,
-                                                 x, 2)
+                    res += ovfcheck(x // 2)
+                    res += ovfcheck(x % 2)
                     x += 5
                 except OverflowError:
                     res += 100
@@ -1312,7 +1310,6 @@
 
     def test_free_object(self):
         import weakref
-        from rpython.rtyper.lltypesystem.lloperation import llop
         myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
         class X(object):
             pass
@@ -3824,7 +3821,6 @@
         self.check_operations_history(guard_class=0, record_exact_class=1)
 
     def test_give_class_knowledge_to_tracer_explicitly(self):
-        from rpython.rtyper.lltypesystem.lloperation import llop
         class Base(object):
             def f(self):
                 raise NotImplementedError
diff --git a/rpython/jit/metainterp/test/test_dict.py 
b/rpython/jit/metainterp/test/test_dict.py
--- a/rpython/jit/metainterp/test/test_dict.py
+++ b/rpython/jit/metainterp/test/test_dict.py
@@ -99,9 +99,9 @@
             py.test.skip("this is an r_dict test")
         myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
         def key(x):
-            return x % 2
+            return x & 1
         def eq(x, y):
-            return (x % 2) == (y % 2)
+            return (x & 1) == (y & 1)
 
         def f(n):
             dct = objectmodel.r_dict(eq, key)
@@ -117,7 +117,7 @@
         res1 = f(100)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to