Author: Armin Rigo <[email protected]>
Branch:
Changeset: r74738:68c97410a30e
Date: 2014-11-26 18:16 +0100
http://bitbucket.org/pypy/pypy/changeset/68c97410a30e/
Log: Add 'int_signext' to replace the three instructions which have all
very large constants when used to sign-extend a 32-bit integer into
a full 64-bit word.
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
@@ -318,6 +318,18 @@
| (rd & 0xF) << 12
| imm16 & 0xFFF)
+ def SXTB_rr(self, rd, rm, c=cond.AL):
+ self.write32(c << 28
+ | 0x06AF0070
+ | (rd & 0xF) << 12
+ | (rm & 0xF))
+
+ def SXTB16_rr(self, rd, rm, c=cond.AL):
+ self.write32(c << 28
+ | 0x068F0070
+ | (rd & 0xF) << 12
+ | (rm & 0xF))
+
def LDREX(self, rt, rn, c=cond.AL):
self.write32(c << 28
| 0x01900f9f
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
@@ -102,6 +102,17 @@
self.mc.MOV_rr(res.value, arg.value, cond=c.GE)
return fcond
+ def emit_op_int_signext(self, op, arglocs, regalloc, fcond):
+ arg, numbytes, res = arglocs
+ assert numbytes.is_imm()
+ if numbytes.value == 1:
+ self.mc.SXTB_rr(res.value, arg.value)
+ elif numbytes.value == 2:
+ self.mc.SXTB16_rr(res.value, arg.value)
+ else:
+ raise AssertionError("bad number of bytes")
+ return fcond
+
#ref: http://blogs.arm.com/software-enablement/detecting-overflow-from-mul/
def emit_guard_int_mul_ovf(self, op, guard, arglocs, regalloc, fcond):
reg1 = arglocs[0]
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
@@ -458,6 +458,12 @@
resloc = self.force_allocate_reg(op.result, [op.getarg(0)])
return [argloc, resloc]
+ def prepare_op_int_signext(self, op, fcond):
+ argloc = self.make_sure_var_in_reg(op.getarg(0))
+ numbytes = op.getarg(1).getint()
+ resloc = self.force_allocate_reg(op.result)
+ return [argloc, imm(numbytes), resloc]
+
def prepare_guard_int_mul_ovf(self, op, guard, fcond):
boxes = op.getarglist()
reg1 = self.make_sure_var_in_reg(boxes[0], forbidden_vars=boxes)
diff --git a/rpython/jit/backend/test/runner_test.py
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -3890,6 +3890,26 @@
deadframe = self.cpu.execute_token(looptoken, inp)
assert outp == self.cpu.get_int_value(deadframe, 0)
+ def test_int_signext(self):
+ numbytes_cases = [1, 2] if IS_32_BIT else [1, 2, 4]
+ for numbytes in numbytes_cases:
+ ops = """
+ [i0]
+ i1 = int_signext(i0, %d)
+ finish(i1, descr=descr)
+ """ % numbytes
+ descr = BasicFinalDescr()
+ loop = parse(ops, self.cpu, namespace=locals())
+ looptoken = JitCellToken()
+ self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+ test_cases = [random.randrange(-sys.maxint-1, sys.maxint+1)
+ for _ in range(100)]
+ for test_case in test_cases:
+ deadframe = self.cpu.execute_token(looptoken, test_case)
+ got = self.cpu.get_int_value(deadframe, 0)
+ expected = heaptracker.int_signext(test_case, numbytes)
+ assert got == expected
+
def test_compile_asmlen(self):
from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
if not isinstance(self.cpu, AbstractLLCPU):
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
@@ -1143,6 +1143,18 @@
def genop_math_sqrt(self, op, arglocs, resloc):
self.mc.SQRTSD(arglocs[0], resloc)
+ def genop_int_signext(self, op, arglocs, resloc):
+ argloc, numbytesloc = arglocs
+ assert isinstance(numbytesloc, ImmedLoc)
+ if numbytesloc.value == 1:
+ self.mc.MOVSX8(resloc, argloc)
+ elif numbytesloc.value == 2:
+ self.mc.MOVSX16(resloc, argloc)
+ elif IS_X86_64 and numbytesloc.value == 4:
+ self.mc.MOVSX32(resloc, argloc)
+ else:
+ raise AssertionError("bad number of bytes")
+
def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs,
result_loc):
guard_opnum = guard_op.getopnum()
if isinstance(arglocs[0], RegLoc):
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
@@ -474,6 +474,12 @@
consider_int_invert = consider_int_neg
+ def consider_int_signext(self, op):
+ argloc = self.loc(op.getarg(0))
+ numbytesloc = self.loc(op.getarg(1))
+ resloc = self.force_allocate_reg(op.result)
+ self.perform(op, [argloc, numbytesloc], resloc)
+
def consider_int_lshift(self, op):
if isinstance(op.getarg(1), Const):
loc2 = self.rm.convert_to_imm(op.getarg(1))
diff --git a/rpython/jit/codewriter/heaptracker.py
b/rpython/jit/codewriter/heaptracker.py
--- a/rpython/jit/codewriter/heaptracker.py
+++ b/rpython/jit/codewriter/heaptracker.py
@@ -1,6 +1,7 @@
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.rtyper import rclass
from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.rarithmetic import r_uint, intmask
def adr2int(addr):
@@ -11,6 +12,14 @@
def int2adr(int):
return llmemory.cast_int_to_adr(int)
+def int_signext(value, numbytes):
+ b8 = numbytes * 8
+ a = r_uint(value)
+ a += r_uint(1 << (b8 - 1)) # a += 128
+ a &= r_uint((1 << b8) - 1) # a &= 255
+ a -= r_uint(1 << (b8 - 1)) # a -= 128
+ return intmask(a)
+
def count_fields_if_immutable(STRUCT):
assert isinstance(STRUCT, lltype.GcStruct)
if STRUCT._hints.get('immutable', False):
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
@@ -1267,19 +1267,12 @@
result = []
if min2:
- c_min2 = Constant(min2, lltype.Signed)
- v2 = varoftype(lltype.Signed)
- result.append(SpaceOperation('int_sub', [v_arg, c_min2], v2))
+ c_bytes = Constant(size2, lltype.Signed)
+ result.append(SpaceOperation('int_signext', [v_arg, c_bytes],
+ v_result))
else:
- v2 = v_arg
- c_mask = Constant(int((1 << (8 * size2)) - 1), lltype.Signed)
- if min2:
- v3 = varoftype(lltype.Signed)
- else:
- v3 = v_result
- result.append(SpaceOperation('int_and', [v2, c_mask], v3))
- if min2:
- result.append(SpaceOperation('int_add', [v3, c_min2], v_result))
+ c_mask = Constant(int((1 << (8 * size2)) - 1), lltype.Signed)
+ result.append(SpaceOperation('int_and', [v_arg, c_mask], v_result))
return result
def _float_to_float_cast(self, v_arg, v_result):
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
@@ -1,5 +1,6 @@
import py, sys
from rpython.jit.codewriter import support
+from rpython.jit.codewriter.heaptracker import int_signext
from rpython.jit.codewriter.flatten import flatten_graph, reorder_renaming_list
from rpython.jit.codewriter.flatten import GraphFlattener, ListOfKind, Register
from rpython.jit.codewriter.format import assert_format
@@ -780,53 +781,37 @@
(rffi.SIGNEDCHAR, rffi.LONG, ""),
(rffi.SIGNEDCHAR, rffi.ULONG, ""),
- (rffi.UCHAR, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3"""),
+ (rffi.UCHAR, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
(rffi.UCHAR, rffi.UCHAR, ""),
(rffi.UCHAR, rffi.SHORT, ""),
(rffi.UCHAR, rffi.USHORT, ""),
(rffi.UCHAR, rffi.LONG, ""),
(rffi.UCHAR, rffi.ULONG, ""),
- (rffi.SHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3"""),
+ (rffi.SHORT, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
(rffi.SHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
(rffi.SHORT, rffi.SHORT, ""),
(rffi.SHORT, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
(rffi.SHORT, rffi.LONG, ""),
(rffi.SHORT, rffi.ULONG, ""),
- (rffi.USHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3"""),
+ (rffi.USHORT, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
(rffi.USHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
- (rffi.USHORT, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
- int_and %i1, $65535 -> %i2
- int_add %i2, $-32768 -> %i3"""),
+ (rffi.USHORT, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
(rffi.USHORT, rffi.USHORT, ""),
(rffi.USHORT, rffi.LONG, ""),
(rffi.USHORT, rffi.ULONG, ""),
- (rffi.LONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3"""),
+ (rffi.LONG, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
(rffi.LONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
- (rffi.LONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
- int_and %i1, $65535 -> %i2
- int_add %i2, $-32768 -> %i3"""),
+ (rffi.LONG, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
(rffi.LONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
(rffi.LONG, rffi.LONG, ""),
(rffi.LONG, rffi.ULONG, ""),
- (rffi.ULONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3"""),
+ (rffi.ULONG, rffi.SIGNEDCHAR, "int_signext %i0, $1 -> %i1"),
(rffi.ULONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
- (rffi.ULONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
- int_and %i1, $65535 -> %i2
- int_add %i2, $-32768 -> %i3"""),
+ (rffi.ULONG, rffi.SHORT, "int_signext %i0, $2 -> %i1"),
(rffi.ULONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
(rffi.ULONG, rffi.LONG, ""),
(rffi.ULONG, rffi.ULONG, ""),
@@ -910,18 +895,14 @@
return rffi.cast(rffi.SIGNEDCHAR, n)
self.encoding_test(f, [12.456], """
cast_float_to_int %f0 -> %i0
- int_sub %i0, $-128 -> %i1
- int_and %i1, $255 -> %i2
- int_add %i2, $-128 -> %i3
- int_return %i3
+ int_signext %i0, $1 -> %i1
+ int_return %i1
""", transform=True)
self.encoding_test(f, [rffi.cast(lltype.SingleFloat, 12.456)], """
cast_singlefloat_to_float %i0 -> %f0
cast_float_to_int %f0 -> %i1
- int_sub %i1, $-128 -> %i2
- int_and %i2, $255 -> %i3
- int_add %i3, $-128 -> %i4
- int_return %i4
+ int_signext %i1, $1 -> %i2
+ int_return %i2
""", transform=True)
def f(dbl):
@@ -1068,9 +1049,12 @@
match = r.match(op)
assert match, "line %r does not match regexp" % (op,)
opname = match.group(1)
- if opname == 'int_add': value += int(match.group(2))
- elif opname == 'int_sub': value -= int(match.group(2))
- elif opname == 'int_and': value &= int(match.group(2))
- else: assert 0, opname
+ if opname == 'int_and':
+ value &= int(match.group(2))
+ elif opname == 'int_signext':
+ numbytes = int(match.group(2))
+ value = int_signext(value, numbytes)
+ else:
+ assert 0, opname
#
assert rffi.cast(lltype.Signed, value) == expected_value
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
@@ -489,6 +489,9 @@
if i < 0:
return 0
return i
+ @arguments("i", "i", returns="i")
+ def bhimpl_int_signext(a, b):
+ return heaptracker.int_signext(a, b)
@arguments("i", "i", returns="i")
def bhimpl_uint_lt(a, b):
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
@@ -197,7 +197,7 @@
# ------------------------------
for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
- 'int_and', 'int_or', 'int_xor',
+ 'int_and', 'int_or', 'int_xor', 'int_signext',
'int_rshift', 'int_lshift', 'uint_rshift',
'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
'uint_floordiv',
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
@@ -419,6 +419,7 @@
'INT_RSHIFT/2',
'INT_LSHIFT/2',
'UINT_RSHIFT/2',
+ 'INT_SIGNEXT/2',
'FLOAT_ADD/2',
'FLOAT_SUB/2',
'FLOAT_MUL/2',
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
@@ -3048,6 +3048,16 @@
res = self.meta_interp(f, [32])
assert res == f(32)
+ def test_int_signext(self):
+ def f(n):
+ return rffi.cast(rffi.SIGNEDCHAR, n)
+ res = self.interp_operations(f, [128])
+ assert res == -128
+ res = self.interp_operations(f, [-35 + 256 * 29])
+ assert res == -35
+ res = self.interp_operations(f, [127 - 256 * 29])
+ assert res == 127
+
class BaseLLtypeTests(BasicTests):
def test_identityhash(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit