[pypy-commit] pypy remove-raisingops: Remove divisions and modulos from regular JIT operations, uses oopspec
arigo
pypy.commits at gmail.com
Tue May 10 12:31:37 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: remove-raisingops
Changeset: r84351:1ad01ba1173b
Date: 2016-05-10 18:31 +0200
http://bitbucket.org/pypy/pypy/changeset/1ad01ba1173b/
Log: Remove divisions and modulos from regular JIT operations, uses
oopspec calls
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
@@ -26,6 +26,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
@@ -1903,15 +1903,19 @@
self.callcontrol.callinfocollection.add(oopspecindex, calldescr, func)
def _handle_int_ovf(self, op, oopspec_name, args):
- assert oopspec_name in ('int.add_ovf', 'int.sub_ovf', 'int.mul_ovf',
- 'int.py_div', 'int.py_mod')
- op0 = SpaceOperation(oopspec_name.replace('.', '_'), args, op.result)
- if oopspec_name in ('int.add_ovf', 'int.mul_ovf'):
- op0 = self._rewrite_symmetric(op0)
- oplist = [op0]
- if oopspec_name.endswith('_ovf'):
- oplist.insert(0, SpaceOperation('-live-', [], None))
- return oplist
+ opname = oopspec_name.replace('.', '_')
+ if oopspec_name in ('int.add_ovf', 'int.sub_ovf', 'int.mul_ovf'):
+ op0 = SpaceOperation(opname, args, op.result)
+ if oopspec_name in ('int.add_ovf', 'int.mul_ovf'):
+ op0 = self._rewrite_symmetric(op0)
+ oplist = [op0]
+ if oopspec_name.endswith('_ovf'):
+ oplist.insert(0, SpaceOperation('-live-', [], None))
+ return oplist
+ else:
+ 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)
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:]]
@@ -273,7 +277,7 @@
v3 = varoftype(lltype.Signed)
for v1 in [varoftype(lltype.Signed), const(42)]:
for v2 in [varoftype(lltype.Signed), const(43)]:
- op = SpaceOperation('foobar', [v1, v2], v3)
+ op = SpaceOperation('direct_call', [Constant(opname), v1, v2], v3)
oplist = Transformer(FakeCPU())._handle_int_ovf(op, 'int.'+opname,
[v1, v2])
op1, op0 = oplist
@@ -293,7 +297,7 @@
v3 = varoftype(lltype.Signed)
for v1 in [varoftype(lltype.Signed), const(42)]:
for v2 in [varoftype(lltype.Signed), const(43)]:
- op = SpaceOperation('foobar', [v1, v2], v3)
+ op = SpaceOperation('direct_call', [Constant(opname), v1, v2], v3)
oplist = Transformer(FakeCPU())._handle_int_ovf(op, 'int.'+opname,
[v1, v2])
op1, op0 = oplist
@@ -304,18 +308,19 @@
assert op1.args == []
assert op1.result is None
- at py.test.mark.parametrize('opname', ['py_div', 'py_mod'])
-def test_asymmetric_op_nonovf(opname):
+ at py.test.mark.parametrize('opname', ['py_div', 'udiv', 'py_mod', 'umod'])
+def test_asymmetric_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('foobar', [v1, v2], v3)
- oplist = Transformer(FakeCPU())._handle_int_ovf(op, 'int.'+opname,
- [v1, v2])
- [op0] = oplist
- assert op0.opname == 'int_'+opname
- assert op0.args == [v1, v2]
- assert op0.result == v3
+ op = SpaceOperation('direct_call', [Constant(opname), v1, v2], v3)
+ op0 = tr._handle_int_ovf(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(
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,11 +955,6 @@
'INT_ADD/2/i',
'INT_SUB/2/i',
'INT_MUL/2/i',
- 'INT_C_DIV/2/i', # C-style handling of negatives (backend only)
- 'INT_PY_DIV/2/i', # Python-style handling of negatives (frontend)
- 'UINT_FLOORDIV/2/i',
- 'INT_C_MOD/2/i', # C-style handling of negatives (backend only)
- 'INT_PY_MOD/2/i', # Python-style handling of negatives (frontend)
'INT_AND/2/i',
'INT_OR/2/i',
'INT_XOR/2/i',
diff --git a/rpython/rtyper/rint.py b/rpython/rtyper/rint.py
--- a/rpython/rtyper/rint.py
+++ b/rpython/rtyper/rint.py
@@ -307,8 +307,7 @@
"""Write a simple operation implementing the given 'func'.
It must be an operation that cannot raise.
"""
- if '_ovf' in func or (func.startswith(('mod', 'floordiv'))
- and not hop.s_result.unsigned):
+ if '_ovf' in func or func.startswith(('mod', 'floordiv')):
raise TyperError("%r should not be used here any more" % (func,))
r_result = hop.r_result
@@ -351,8 +350,6 @@
if not any_implicit_exception:
if not func.startswith(('mod', 'floordiv')):
return _rtype_template(hop, func)
- if hop.s_result.unsigned:
- return _rtype_template(hop, func)
repr = hop.r_result
assert repr.lowleveltype != Bool
@@ -399,11 +396,6 @@
raise ZeroDivisionError("integer division")
return ll_int_floordiv(x, y)
-def ll_uint_floordiv_zer(x, y):
- if y == 0:
- raise ZeroDivisionError("unsigned integer division")
- return llop.uint_floordiv(Unsigned, x, y)
-
def ll_int_floordiv_ovf(x, y):
# JIT: intentionally not short-circuited to produce only one guard
# and to remove the check fully if one of the arguments is known
@@ -416,23 +408,44 @@
raise ZeroDivisionError("integer division")
return ll_int_floordiv_ovf(x, y)
-def ll_llong_floordiv(x, y):
- r = llop.llong_floordiv(SignedLongLong, x, y) # <= truncates like in C
- p = r * y
- if y < 0: u = p - x
- else: u = x - p
- return r + (u >> LLONG_BITS_1)
+ at jit.oopspec("int.udiv(x, y)")
+def ll_uint_floordiv(x, y):
+ return llop.uint_floordiv(Unsigned, x, y)
-def ll_llong_floordiv_zer(x, y):
+def ll_uint_floordiv_zer(x, y):
if y == 0:
- raise ZeroDivisionError("longlong division")
- return ll_llong_floordiv(x, y)
+ raise ZeroDivisionError("unsigned integer division")
+ return ll_uint_floordiv(x, y)
-def ll_ullong_floordiv_zer(x, y):
- if y == 0:
- raise ZeroDivisionError("unsigned longlong division")
- return llop.ullong_floordiv(UnsignedLongLong, x, y)
+if SignedLongLong == Signed:
+ ll_llong_floordiv = ll_int_floordiv
+ ll_llong_floordiv_zer = ll_int_floordiv_zer
+ ll_ullong_floordiv = ll_uint_floordiv
+ ll_ullong_floordiv_zer = ll_uint_floordiv_zer
+else:
+ @jit.dont_look_inside
+ def ll_llong_floordiv(x, y):
+ r = llop.llong_floordiv(SignedLongLong, x, y) # <= truncates like in C
+ p = r * y
+ if y < 0: u = p - x
+ else: u = x - p
+ return r + (u >> LLONG_BITS_1)
+ def ll_llong_floordiv_zer(x, y):
+ if y == 0:
+ raise ZeroDivisionError("longlong division")
+ return ll_llong_floordiv(x, y)
+
+ @jit.dont_look_inside
+ def ll_ullong_floordiv(x, y):
+ return llop.ullong_floordiv(UnsignedLongLong, x, y)
+
+ def ll_ullong_floordiv_zer(x, y):
+ if y == 0:
+ raise ZeroDivisionError("unsigned longlong division")
+ return ll_ullong_floordiv(x, y)
+
+ at jit.dont_look_inside
def ll_lllong_floordiv(x, y):
r = llop.lllong_floordiv(SignedLongLongLong, x, y) # <= truncates like in C
p = r * y
@@ -460,11 +473,6 @@
raise ZeroDivisionError
return ll_int_mod(x, y)
-def ll_uint_mod_zer(x, y):
- if y == 0:
- raise ZeroDivisionError
- return llop.uint_mod(Unsigned, x, y)
-
def ll_int_mod_ovf(x, y):
# see comment in ll_int_floordiv_ovf
if (x == -sys.maxint - 1) & (y == -1):
@@ -476,22 +484,43 @@
raise ZeroDivisionError
return ll_int_mod_ovf(x, y)
-def ll_llong_mod(x, y):
- r = llop.llong_mod(SignedLongLong, x, y) # <= truncates like in C
- if y < 0: u = -r
- else: u = r
- return r + (y & (u >> LLONG_BITS_1))
+ at jit.oopspec("int.umod(x, y)")
+def ll_uint_mod(x, y):
+ return llop.uint_mod(Unsigned, x, y)
-def ll_llong_mod_zer(x, y):
+def ll_uint_mod_zer(x, y):
if y == 0:
raise ZeroDivisionError
- return ll_llong_mod(x, y)
+ return ll_uint_mod(x, y)
-def ll_ullong_mod_zer(x, y):
- if y == 0:
- raise ZeroDivisionError
- return llop.ullong_mod(UnsignedLongLong, x, y)
+if SignedLongLong == Signed:
+ ll_llong_mod = ll_int_mod
+ ll_llong_mod_zer = ll_int_mod_zer
+ ll_ullong_mod = ll_uint_mod
+ ll_ullong_mod_zer = ll_uint_mod_zer
+else:
+ @jit.dont_look_inside
+ def ll_llong_mod(x, y):
+ r = llop.llong_mod(SignedLongLong, x, y) # <= truncates like in C
+ if y < 0: u = -r
+ else: u = r
+ return r + (y & (u >> LLONG_BITS_1))
+ def ll_llong_mod_zer(x, y):
+ if y == 0:
+ raise ZeroDivisionError
+ return ll_llong_mod(x, y)
+
+ @jit.dont_look_inside
+ def ll_ullong_mod(x, y):
+ return llop.ullong_mod(UnsignedLongLong, x, y)
+
+ def ll_ullong_mod_zer(x, y):
+ if y == 0:
+ raise ZeroDivisionError
+ return llop.ullong_mod(UnsignedLongLong, x, y)
+
+ at jit.dont_look_inside
def ll_lllong_mod(x, y):
r = llop.lllong_mod(SignedLongLongLong, x, y) # <= truncates like in C
if y < 0: u = -r
More information about the pypy-commit
mailing list