[pypy-svn] pypy jit-longlong: Change the point at which we replace Constants of type LongLong.
arigo
commits-noreply at bitbucket.org
Sun Jan 9 18:21:05 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: jit-longlong
Changeset: r40532:d026413dcaf5
Date: 2011-01-09 18:20 +0100
http://bitbucket.org/pypy/pypy/changeset/d026413dcaf5/
Log: Change the point at which we replace Constants of type LongLong. Now
it should be more general, and also handle Constants that appear in
link.args.
diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -2,6 +2,7 @@
from pypy.rlib.rarithmetic import r_longlong, intmask
from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
+from pypy.objspace.flow.model import Block, Link
from pypy.translator.unsimplify import varoftype
from pypy.rpython.lltypesystem import lltype
from pypy.jit.codewriter.jtransform import Transformer, NotSupported
@@ -57,6 +58,42 @@
if is_llf(v.concretetype)]
assert op1.result == v_result
+ def test_remove_longlong_constant(self):
+ c1 = Constant(r_longlong(-123), lltype.SignedLongLong)
+ c2 = Constant(r_longlong(-124), lltype.SignedLongLong)
+ c3 = Constant(r_longlong(0x987654321), lltype.SignedLongLong)
+ v1 = varoftype(lltype.SignedLongLong)
+ v2 = varoftype(lltype.Bool)
+ block = Block([v1])
+ block.operations = [SpaceOperation('foo', [c1, v1, c3], v2)]
+ block.exitswitch = v2
+ block.closeblock(Link([c2], block, exitcase=False),
+ Link([c1], block, exitcase=True))
+ tr = Transformer()
+ tr.remove_longlong_constants(block)
+ assert len(block.operations) == 4
+ assert block.operations[0].opname == 'cast_int_to_longlong'
+ assert block.operations[0].args[0].value == -123
+ assert block.operations[0].args[0].concretetype == lltype.Signed
+ v3 = block.operations[0].result
+ assert block.operations[1].opname == 'two_ints_to_longlong'
+ assert block.operations[1].args[0].value == intmask(0x87654321)
+ assert block.operations[1].args[0].concretetype == lltype.Signed
+ assert block.operations[1].args[1].value == 0x9
+ assert block.operations[1].args[1].concretetype == lltype.Signed
+ v4 = block.operations[1].result
+ assert block.operations[2].opname == 'foo'
+ assert block.operations[2].args[0] is v3
+ assert block.operations[2].args[1] is v1
+ assert block.operations[2].args[2] is v4
+ assert block.operations[2].result is v2
+ assert block.operations[3].opname == 'cast_int_to_longlong'
+ assert block.operations[3].args[0].value == -124
+ assert block.operations[3].args[0].concretetype == lltype.Signed
+ v5 = block.operations[3].result
+ assert block.exits[0].args[0] is v5
+ assert block.exits[1].args[0] is v3
+
def test_is_true(self):
for opname, T in [('llong_is_true', lltype.SignedLongLong),
('ullong_is_true', lltype.UnsignedLongLong)]:
@@ -181,54 +218,3 @@
[lltype.Float], lltype.SignedLongLong)
self.do_check('cast_longlong_to_float', EffectInfo.OS_LLONG_TO_FLOAT,
[lltype.SignedLongLong], lltype.Float)
-
- def test_prebuilt_constant_32(self):
- c_x = const(r_longlong(-171))
- v_y = varoftype(lltype.SignedLongLong)
- v_z = varoftype(lltype.SignedLongLong)
- op = SpaceOperation('llong_add', [c_x, v_y], v_z)
- tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
- oplist = tr.rewrite_operation(op)
- assert len(oplist) == 2
- assert oplist[0].opname == 'residual_call_irf_f'
- assert oplist[0].args[0].value == 'llong_from_int'
- assert oplist[0].args[1] == 'calldescr-84'
- assert list(oplist[0].args[2]) == [const(-171)]
- assert list(oplist[0].args[3]) == []
- assert list(oplist[0].args[4]) == []
- v_x = oplist[0].result
- assert isinstance(v_x, Variable)
- assert oplist[1].opname == 'residual_call_irf_f'
- assert oplist[1].args[0].value == 'llong_add'
- assert oplist[1].args[1] == 'calldescr-70'
- assert list(oplist[1].args[2]) == []
- assert list(oplist[1].args[3]) == []
- assert list(oplist[1].args[4]) == [v_x, v_y]
- assert oplist[1].result == v_z
-
- def test_prebuilt_constant_64(self):
- for value in [3000000000, -3000000000, 12345678987654321]:
- v_hi = intmask(value >> 32)
- v_lo = intmask(value)
- c_x = const(r_longlong(value))
- v_y = varoftype(lltype.SignedLongLong)
- v_z = varoftype(lltype.SignedLongLong)
- op = SpaceOperation('llong_add', [c_x, v_y], v_z)
- tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
- oplist = tr.rewrite_operation(op)
- assert len(oplist) == 2
- assert oplist[0].opname == 'residual_call_irf_f'
- assert oplist[0].args[0].value == 'llong_from_two_ints'
- assert oplist[0].args[1] == 'calldescr-93'
- assert list(oplist[0].args[2]) == [const(v_lo), const(v_hi)]
- assert list(oplist[0].args[3]) == []
- assert list(oplist[0].args[4]) == []
- v_x = oplist[0].result
- assert isinstance(v_x, Variable)
- assert oplist[1].opname == 'residual_call_irf_f'
- assert oplist[1].args[0].value == 'llong_add'
- assert oplist[1].args[1] == 'calldescr-70'
- assert list(oplist[1].args[2]) == []
- assert list(oplist[1].args[3]) == []
- assert list(oplist[1].args[4]) == [v_x, v_y]
- assert oplist[1].result == v_z
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -39,6 +39,7 @@
def optimize_block(self, block):
if block.operations == ():
return
+ self.remove_longlong_constants(block)
self.vable_array_vars = {}
self.vable_flags = {}
renamings = {}
@@ -134,6 +135,55 @@
block.exits = block.exits[:1]
block.exitswitch = None
+ def remove_longlong_constants(self, block):
+ # remove all Constant({Un}signedLongLong), and replace them with
+ # cast_int_to_longlong(Constant(Signed)) or
+ # two_ints_to_longlong(Constant(Signed), Constant(Signed)).
+ operations = []
+ all_constants = {}
+ #
+ def _get_const_as_var(c):
+ v = all_constants.get(c)
+ if v is None:
+ from pypy.rlib.rarithmetic import intmask
+ v = varoftype(c.concretetype)
+ value = int(c.value)
+ c_hi = Constant(intmask(value >> 32), lltype.Signed)
+ c_lo = Constant(intmask(value), lltype.Signed)
+ if c_lo.value == value:
+ # a long long constant, but it fits in 32 bits
+ op1 = SpaceOperation('cast_int_to_longlong', [c_lo], v)
+ else:
+ # a 64-bit long long constant, requires two ints
+ op1 = SpaceOperation('two_ints_to_longlong', [c_lo, c_hi],
+ v)
+ operations.append(op1)
+ all_constants[c] = v
+ return v
+ #
+ for op in block.operations:
+ for i, v in enumerate(op.args):
+ if (isinstance(v, Constant) and
+ self._is_longlong(v.concretetype)):
+ args = op.args[:]
+ args[i] = _get_const_as_var(v)
+ op = SpaceOperation(op.opname, args, op.result)
+ operations.append(op)
+ #
+ last_op = None
+ if block.exitswitch == c_last_exception:
+ last_op = operations.pop()
+ for link in block.exits:
+ for i, v in enumerate(link.args):
+ if (isinstance(v, Constant) and
+ self._is_longlong(v.concretetype)):
+ args = link.args[:]
+ args[i] = _get_const_as_var(v)
+ link.args = args
+ if last_op is not None:
+ operations.append(last_op)
+ block.operations = operations
+
# ----------
def follow_constant_exit(self, block):
@@ -268,26 +318,10 @@
# ----------
# Various kinds of calls
- def remove_longlong_constants(func):
- """Decorator. Detect and remove all Constants of type LongLong."""
- def remove_and_call(self, op):
- oplist = []
- op = self._remove_longlong_constants(op, oplist)
- ops = func(self, op)
- if oplist:
- if not isinstance(ops, list):
- assert isinstance(ops, SpaceOperation)
- ops = [ops]
- ops = oplist + ops
- return ops
- return remove_and_call
-
- @remove_longlong_constants
def rewrite_op_direct_call(self, op):
kind = self.callcontrol.guess_call_kind(op)
return getattr(self, 'handle_%s_call' % kind)(op)
- @remove_longlong_constants
def rewrite_op_indirect_call(self, op):
kind = self.callcontrol.guess_call_kind(op)
return getattr(self, 'handle_%s_indirect_call' % kind)(op)
@@ -511,7 +545,6 @@
[op.args[0], arraydescr, op.args[1]],
op.result)
- @remove_longlong_constants
def rewrite_op_setarrayitem(self, op):
ARRAY = op.args[0].concretetype.TO
if self._array_of_voids(ARRAY):
@@ -594,7 +627,6 @@
return SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
[v_inst, descr], op.result)
- @remove_longlong_constants
def rewrite_op_setfield(self, op):
if self.is_typeptr_getset(op):
# ignore the operation completely -- instead, it's done by 'new'
@@ -809,43 +841,16 @@
# and unsupported ones are turned into a call to a function from
# jit.codewriter.support.
- @staticmethod
- def _is_longlong(TYPE):
- return TYPE == lltype.SignedLongLong or TYPE == lltype.UnsignedLongLong
-
- def _remove_longlong_constants(self, op, oplist):
- args = op.args
- for i in range(len(args)):
- if (isinstance(args[i], Constant) and
- self._is_longlong(args[i].concretetype)):
- from pypy.rlib.rarithmetic import intmask
- v_x = varoftype(args[i].concretetype)
- value = int(args[i].value)
- if value == intmask(value):
- # a long long constant, but it fits in 32 bits
- c_x = Constant(value, lltype.Signed)
- op0 = SpaceOperation('llong_from_int', [c_x], v_x)
- op1 = self.prepare_builtin_call(op0, "llong_from_int",
- [c_x])
- op2 = self._handle_oopspec_call(op1, [c_x],
- EffectInfo.OS_LLONG_FROM_INT)
- else:
- # a long long constant, requires two ints
- c_hi = Constant(intmask(value >> 32), lltype.Signed)
- c_lo = Constant(intmask(value), lltype.Signed)
- op0 = SpaceOperation('llong_from_two_ints', [c_lo, c_hi],
- v_x)
- op1 = self.prepare_builtin_call(op0, "llong_from_two_ints",
- [c_lo, c_hi])
- op2 = self._handle_oopspec_call(op1, [c_lo, c_hi],
- EffectInfo.OS_LLONG_FROM_TWO_INTS)
- oplist.append(op2)
- args = args[:]
- args[i] = v_x
- if args is op.args:
- return op
- else:
- return SpaceOperation(op.opname, args, op.result)
+ if lltype.SignedLongLong != lltype.Signed:
+ @staticmethod
+ def _is_longlong(TYPE):
+ return (TYPE == lltype.SignedLongLong or
+ TYPE == lltype.UnsignedLongLong)
+ else:
+ # on 64-bit, _is_longlong() returns always False
+ @staticmethod
+ def _is_longlong(TYPE):
+ return False
for _op, _oopspec in [('llong_invert', 'INVERT'),
('ullong_invert', 'INVERT'),
@@ -885,7 +890,6 @@
('two_ints_to_longlong', 'FROM_TWO_INTS'),
]:
exec py.code.Source('''
- @remove_longlong_constants
def rewrite_op_%s(self, op):
args = op.args
op1 = self.prepare_builtin_call(op, "llong_%s", args)
@@ -894,15 +898,32 @@
return op2
''' % (_op, _oopspec.lower(), _oopspec)).compile()
+ def _normalize(self, oplist):
+ if isinstance(oplist, SpaceOperation):
+ return [oplist]
+ else:
+ assert type(oplist) is list
+ return oplist
+
def rewrite_op_llong_neg(self, op):
- args = [Constant(0, lltype.SignedLongLong), op.args[0]]
+ v = varoftype(lltype.SignedLongLong)
+ op0 = SpaceOperation('cast_int_to_longlong',
+ [Constant(0, lltype.Signed)],
+ v)
+ args = [v, op.args[0]]
op1 = SpaceOperation('llong_sub', args, op.result)
- return self.rewrite_operation(op1)
+ return (self._normalize(self.rewrite_operation(op0)) +
+ self._normalize(self.rewrite_operation(op1)))
def rewrite_op_llong_is_true(self, op):
- args = [op.args[0], Constant(0, lltype.SignedLongLong)]
+ v = varoftype(lltype.SignedLongLong)
+ op0 = SpaceOperation('cast_int_to_longlong',
+ [Constant(0, lltype.Signed)],
+ v)
+ args = [op.args[0], v]
op1 = SpaceOperation('llong_ne', args, op.result)
- return self.rewrite_operation(op1)
+ return (self._normalize(self.rewrite_operation(op0)) +
+ self._normalize(self.rewrite_operation(op1)))
rewrite_op_ullong_is_true = rewrite_op_llong_is_true
More information about the Pypy-commit
mailing list