[pypy-commit] pypy no-failargs: In-progress: reduce the various numbers assigned to ResOps, including
arigo
noreply at buildbot.pypy.org
Mon Oct 29 17:23:03 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: no-failargs
Changeset: r58586:e0e01c9c6532
Date: 2012-10-29 16:01 +0100
http://bitbucket.org/pypy/pypy/changeset/e0e01c9c6532/
Log: In-progress: reduce the various numbers assigned to ResOps,
including for __str__(). Now it adds a constraint to oparsed texts:
we cannot use e.g. both 'p0' and 'i0' (only one variable is allowed
at position 0), or 'f0' and 'f1' (float variables are assumed to
take two positions each). This should be nicely checked by oparser,
though.
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -635,6 +635,18 @@
self.last_exception = None
def setenv(self, box, arg):
+ if box.type == INT:
+ # typecheck the result
+ if isinstance(arg, bool):
+ arg = int(arg)
+ assert lltype.typeOf(arg) == lltype.Signed
+ elif box.type == REF:
+ assert lltype.typeOf(arg) == llmemory.GCREF
+ elif box.type == FLOAT:
+ assert lltype.typeOf(arg) == longlong.FLOATSTORAGE
+ else:
+ raise AssertionError(box)
+ #
assert box.getvarindex() >= 0
self.env[box] = arg
self.framecontent[box.getvarindex()] = arg
@@ -673,24 +685,15 @@
if hasattr(gf.descr, '_llgraph_bridge'):
i = 0
self.lltrace = gf.descr._llgraph_bridge
- newvals = [self.env[arg] for arg in self.lltrace.inputargs]
+ newvals = [self.framecontent[arg._varindex]
+ for arg in self.lltrace.inputargs]
self.do_renaming(self.lltrace.inputargs, newvals)
continue
raise
- if op.type == INT:
- # typecheck the result
- if isinstance(resval, bool):
- resval = int(resval)
- assert lltype.typeOf(resval) == lltype.Signed
- elif op.type == REF:
- assert lltype.typeOf(resval) == llmemory.GCREF
- elif op.type == FLOAT:
- assert lltype.typeOf(resval) == longlong.FLOATSTORAGE
- else:
- assert op.type == VOID
- assert resval is None
if op.type != VOID:
self.setenv(op, resval)
+ else:
+ assert resval is None
i += 1
def do_renaming(self, newargs, newvalues):
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -24,51 +24,13 @@
add_loop_instruction = ['overload for a specific cpu']
bridge_loop_instruction = ['overload for a specific cpu']
- _nextvarindex = 0
-
- def update_varindexes(self, newtext2op):
- # 'self.text2op' is a dict mapping variable names (as present in
- # the oparser source) to the corresponding ResOp. This function
- # updates it with 'newtext2op', then assigns '_varindex' to all
- # the new ResOps. The choice of '_varindex' is done automatically
- # to avoid conflicts, but existing '_varindex' are not changed.
- # If 'newtext2op' is not a dict but a list, comes up with names
- # as per str(op).
- if isinstance(newtext2op, list):
- newtext2op = dict([(str(op), op) for op in newtext2op])
- try:
- text2op = self.text2op
- except AttributeError:
- text2op = self.text2op = {}
- text2op.update(newtext2op)
- if newtext2op:
- # update 'self._nextvarindex' to a value higher than any seen
- # in newtext2op. Pick two more rather than one more just in
- # case the highest so far was a FLOAT.
- newops = newtext2op.values()
- random.shuffle(newops)
- maximum = max([getattr(op, '_varindex', -2) for op in newops])
- self._nextvarindex = max(self._nextvarindex, maximum + 2)
- for op in newops:
- self.assign_varindex(op)
-
- def assign_varindex(self, op):
- if (isinstance(op, AbstractResOp) and op.type != VOID and
- getattr(op, '_varindex', -1) == -1):
- op._varindex = self._nextvarindex
- if hasattr(op, '_str'):
- del op._str # recompute it
- # this op consumes either one or two numbers, depending on its
- # type as a non-FLOAT or FLOAT. We don't care too much about
- # being on 32-bit vs 64-bit here.
- self._nextvarindex += 1 + (op.type == FLOAT)
def execute_operation(self, opname, valueboxes, result_type, descr=None):
inputargs, operations = self._get_single_operation_list(opname,
result_type,
valueboxes,
descr)
- self.update_varindexes(inputargs + operations)
+ oparser.assign_all_varindices(inputargs + operations)
looptoken = JitCellToken()
self.cpu.compile_loop(inputargs, operations, looptoken)
args = []
@@ -151,14 +113,11 @@
namespace['faildescr3'] = BasicFailDescr(3)
if 'faildescr4' not in namespace:
namespace['faildescr4'] = BasicFailDescr(4)
- loop = oparser.parse(s, namespace=namespace, mutable=True,
- oldvars=getattr(self, 'text2op', {}))
- self.update_varindexes(loop.text2op)
+ loop = oparser.parse(s, namespace=namespace, mutable=True)
return loop.inputargs, loop.operations, JitCellToken()
def get_frame_value(self, frame, varname):
- op = self.text2op[varname]
- index = op.getvarindex()
+ index = int(varname[1:])
if varname.startswith('i'):
return self.cpu.get_frame_value_int(frame, index)
if varname.startswith('p'):
@@ -184,8 +143,8 @@
faildescr = BasicFailDescr(1)
inputargs, ops, token = self.parse("""
[f0]
- f1 = float_add(f0, 1.)
- finish(f1, descr=faildescr)
+ f2 = float_add(f0, 1.)
+ finish(f2, descr=faildescr)
""", namespace=locals())
self.cpu.compile_loop(inputargs, ops, token)
frame = self.cpu.execute_token(token, longlong.getfloatstorage(2.8))
@@ -1208,9 +1167,9 @@
label(%s, descr=targettoken)
i1 = int_sub(i0, 1)
i2 = int_ge(i1, 0)
- guard_true(i2, descr=faildescr) [%s]
+ guard_true(i2, descr=faildescr)
jump(%s, descr=targettoken)
- """ % (inp, inp, inp, ", ".join(jumpargs)), None)
+ """ % (inp, inp, ", ".join(jumpargs)), None)
#
self.cpu.compile_loop(inpargs, operations, looptoken)
#
@@ -1241,15 +1200,9 @@
#
assert dstvalues[index_counter] == 11
dstvalues[index_counter] = 0
- for i, (box, val) in enumerate(zip(inpargs, dstvalues)):
- if box.type == 'i':
- got = self.cpu.get_latest_value_int(frame, i)
- elif box.type == 'r':
- got = self.cpu.get_latest_value_ref(frame, i)
- elif box.type == 'f':
- got = self.cpu.get_latest_value_float(frame, i)
- else:
- assert 0
+ assert len(inputargs) == len(inpargs) == len(dstvalues)
+ for (name, val) in zip(inputargs, dstvalues):
+ got = self.get_frame_value(frame, name)
assert type(got) == type(val)
assert got == val
@@ -1264,8 +1217,8 @@
[%(fboxes)s]
label(%(fboxes)s, descr=targettoken)
i2 = float_le(f0, 9.2)
- guard_true(i2, descr=faildescr1) [%(fboxes)s]
- finish(descr=faildescr2) [%(fboxes)s]
+ guard_true(i2, descr=faildescr1)
+ finish(descr=faildescr2)
""" % {'fboxes': fboxes}, {'faildescr1': faildescr1,
'faildescr2': faildescr2,
'targettoken': targettoken})
@@ -1285,55 +1238,53 @@
args.append(longlong.getfloatstorage(x))
frame = self.cpu.execute_token(looptoken, *args)
assert self.cpu.get_latest_descr(frame).identifier == 2
- res = self.cpu.get_latest_value_float(frame, 0)
+ res = self.get_frame_value(frame, "f0")
assert longlong.getrealfloat(res) == 8.5
- for i in range(1, len(fboxes.split(","))):
- got = longlong.getrealfloat(self.cpu.get_latest_value_float(frame, i))
+ fboxeslist = map(str.strip, fboxes.split(","))
+ for i in range(1, len(fboxeslist)):
+ res = self.get_frame_value(frame, fboxeslist[i])
+ got = longlong.getrealfloat(res)
assert got == 13.5 + 6.73 * i
def test_compile_bridge_spilled_float(self):
if not self.cpu.supports_floats:
py.test.skip("requires floats")
fboxes = [boxfloat() for i in range(3)]
- faildescr1 = BasicFailDescr(100)
loopops = """
- [i0,f1, f2]
+ [i0, f1, f2]
f3 = float_add(f1, f2)
force_spill(f3)
force_spill(f1)
force_spill(f2)
- guard_false(i0, descr=faildescr0) [f1, f2, f3]
- finish() []"""
+ guard_false(i0, descr=faildescr0)
+ finish()"""
inputargs, operations, looptoken = self.parse(
loopops, namespace={'faildescr0': BasicFailDescr(1)})
self.cpu.compile_loop(inputargs, operations, looptoken)
args = [1]
args.append(longlong.getfloatstorage(132.25))
args.append(longlong.getfloatstorage(0.75))
- frame = self.cpu.execute_token(looptoken, *args) #xxx check
+ frame = self.cpu.execute_token(looptoken, *args)
assert operations[-2].getdescr()== self.cpu.get_latest_descr(frame)
- f1 = self.cpu.get_latest_value_float(frame, 0)
- f2 = self.cpu.get_latest_value_float(frame, 1)
- f3 = self.cpu.get_latest_value_float(frame, 2)
+ f1 = self.get_frame_value(frame, "f1")
+ f2 = self.get_frame_value(frame, "f2")
+ f3 = self.get_frame_value(frame, "f3")
assert longlong.getrealfloat(f1) == 132.25
assert longlong.getrealfloat(f2) == 0.75
assert longlong.getrealfloat(f3) == 133.0
+ faildescr1 = BasicFailDescr(100)
bridgeops = [
create_resop(rop.FINISH, None, [], descr=faildescr1,
mutable=True),
]
- bridgeops[-1].setfailargs(fboxes)
self.cpu.compile_bridge(operations[-2].getdescr(), fboxes,
bridgeops, looptoken)
- args = [1,
- longlong.getfloatstorage(132.25),
- longlong.getfloatstorage(0.75)]
frame = self.cpu.execute_token(looptoken, *args)
assert self.cpu.get_latest_descr(frame).identifier == 100
- f1 = self.cpu.get_latest_value_float(frame, 0)
- f2 = self.cpu.get_latest_value_float(frame, 1)
- f3 = self.cpu.get_latest_value_float(frame, 2)
+ f1 = self.get_frame_value(frame, "f1")
+ f2 = self.get_frame_value(frame, "f2")
+ f3 = self.get_frame_value(frame, "f3")
assert longlong.getrealfloat(f1) == 132.25
assert longlong.getrealfloat(f2) == 0.75
assert longlong.getrealfloat(f3) == 133.0
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -557,21 +557,21 @@
return object.__repr__(self)
def __str__(self):
- if not hasattr(self, '_str'):
- if self.type == INT:
- t = 'i'
- elif self.type == FLOAT:
- t = 'f'
- elif self.type == REF:
- t = 'p'
- else:
- t = '?'
- if getattr(self, '_varindex', -1) < 0:
- self._str = '%s%d' % (t, AbstractResOp._counter)
+ if self.type == INT:
+ t = 'i'
+ elif self.type == FLOAT:
+ t = 'f'
+ elif self.type == REF:
+ t = 'p'
+ else:
+ t = '?'
+ if getattr(self, '_varindex', -1) < 0:
+ if not hasattr(self, '_str'):
AbstractResOp._counter += 1
- else:
- self._str = '%s%s' % (t.upper(), self._varindex)
- return self._str
+ self._str = '%s-%d' % (t, AbstractResOp._counter)
+ return self._str
+ else:
+ return '%s%d' % (t, self._varindex)
def repr(self, graytext=False):
# RPython-friendly version
diff --git a/pypy/jit/tool/oparser.py b/pypy/jit/tool/oparser.py
--- a/pypy/jit/tool/oparser.py
+++ b/pypy/jit/tool/oparser.py
@@ -7,7 +7,7 @@
from pypy.jit.metainterp.resoperation import rop, opclasses, rop_lowercase,\
ResOpWithDescr, N_aryOp, UnaryOp, PlainResOp, create_resop_dispatch,\
- ResOpNone, create_resop_0, example_for_opnum
+ ResOpNone, create_resop_0, example_for_opnum, FLOAT
from pypy.jit.metainterp import optmodel
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import Symbolic
@@ -20,10 +20,8 @@
use_mock_model = False
def __init__(self, input, cpu, namespace, type_system,
- invent_fail_descr=True, results=None, mutable=False,
- oldvars={}):
+ invent_fail_descr=True, results=None, mutable=False):
self.input = input
- self.oldvars = oldvars
self.vars = {}
self.cpu = cpu
self._consts = namespace
@@ -33,6 +31,7 @@
self.original_jitcell_token = self.model.JitCellToken()
self.results = results
self.mutable = mutable
+ self.allops = []
def get_const(self, name, typ):
if self._consts is None:
@@ -77,20 +76,17 @@
def newvar(self, elem):
if elem not in self.vars:
- if elem not in self.oldvars:
- if elem[0] in 'ifp':
- if elem[0] == 'p':
- p = 'r'
- else:
- p = elem[0]
- opnum = getattr(rop, 'INPUT_' + p)
- box = create_resop_0(opnum, example_for_opnum(opnum),
- mutable=self.mutable)
+ if elem[0] in 'ifp':
+ if elem[0] == 'p':
+ p = 'r'
else:
- raise ParseError("Unknown variable type: %s" % elem)
- box._str = elem
+ p = elem[0]
+ opnum = getattr(rop, 'INPUT_' + p)
+ box = create_resop_0(opnum, example_for_opnum(opnum),
+ mutable=self.mutable)
else:
- box = self.oldvars[elem]
+ raise ParseError("Unknown variable type: %s" % elem)
+ self.setstr(box, elem)
self.vars[elem] = box
return self.vars[elem]
@@ -203,10 +199,20 @@
else:
result = self.results[num]
opres = self.create_op(opnum, result, args, descr)
- opres._str = res
+ self.setstr(opres, res)
self.vars[res] = opres
return opres
+ def setstr(self, op, text):
+ op._str = text
+ try:
+ num = int(text[1:])
+ except ValueError:
+ num = -1
+ if num >= 0:
+ op._varindex = num
+ self.allops.append(op)
+
def parse_op_no_result(self, line):
opnum, args, descr = self.parse_op(line)
res = self.create_op(opnum, None, args, descr)
@@ -242,13 +248,13 @@
num, ops, last_offset = self.parse_ops(base_indent, newlines, 0)
if num < len(newlines):
raise ParseError("unexpected dedent at line: %s" % newlines[num])
+ assign_all_varindices(self.allops)
loop = self.model.ExtendedTreeLoop("loop")
loop.comment = first_comment
loop.original_jitcell_token = self.original_jitcell_token
loop.operations = ops
loop.inputargs = inpargs
loop.last_offset = last_offset
- loop.text2op = self.vars
return loop
def parse_ops(self, indent, lines, start):
@@ -306,12 +312,42 @@
def parse(input, cpu=None, namespace=DEFAULT, type_system='lltype',
invent_fail_descr=True, OpParser=OpParser,
- results=None, mutable=False, oldvars={}):
+ results=None, mutable=False):
if namespace is DEFAULT:
namespace = {}
return OpParser(input, cpu, namespace, type_system,
- invent_fail_descr, results, mutable, oldvars).parse()
+ invent_fail_descr, results, mutable).parse()
def pure_parse(*args, **kwds):
kwds['invent_fail_descr'] = False
return parse(*args, **kwds)
+
+
+def assign_all_varindices(allops):
+ assigned_varindices = {}
+ unassigned_varindices = []
+ #
+ for op in allops:
+ if getattr(op, '_varindex', -1) >= 0:
+ num = op._varindex
+ assert num not in assigned_varindices, (
+ "duplicate or overlapping var: %s and %s" % (
+ op, assigned_varindices[num]))
+ assigned_varindices[num] = op
+ if op.type == FLOAT:
+ assert (num + 1) not in assigned_varindices, (
+ "duplicate or overlapping var: %s and %s" % (
+ op, assigned_varindices[num + 1]))
+ assigned_varindices[num + 1] = op
+ else:
+ unassigned_varindices.append(op)
+ #
+ nextindex = 0
+ for op in unassigned_varindices:
+ while (nextindex in assigned_varindices or
+ (op.type == FLOAT and (nextindex + 1) in assigned_varindices)):
+ nextindex += 1
+ op._varindex = nextindex
+ nextindex += 1
+ if op.type == FLOAT:
+ nextindex += 1
diff --git a/pypy/jit/tool/test/test_oparser.py b/pypy/jit/tool/test/test_oparser.py
--- a/pypy/jit/tool/test/test_oparser.py
+++ b/pypy/jit/tool/test/test_oparser.py
@@ -2,8 +2,8 @@
import sys
from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.jit.tool.oparser import parse, OpParser
-from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.tool.oparser import parse, OpParser, assign_all_varindices
+from pypy.jit.metainterp.resoperation import rop, INT, FLOAT
from pypy.jit.metainterp.history import AbstractDescr, JitCellToken,\
TargetToken
@@ -250,3 +250,45 @@
for modname, mod in sys.modules.iteritems():
if isinstance(mod, ForbiddenModule):
sys.modules[modname] = mod.old_mod
+
+
+def test_assign_all_varindices():
+ class FakeOp:
+ def __init__(self, varindex=-1, type=INT):
+ self._varindex = varindex
+ self.type = type
+ def indices(lst):
+ return [op._varindex for op in lst]
+
+ ops = [FakeOp(5), FakeOp(6)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [5, 6]
+
+ ops = [FakeOp(5), FakeOp(6, FLOAT)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [5, 6]
+
+ ops = [FakeOp(5), FakeOp(5)]
+ py.test.raises(AssertionError, assign_all_varindices, ops)
+ ops = [FakeOp(5), FakeOp(5, FLOAT)]
+ py.test.raises(AssertionError, assign_all_varindices, ops)
+ ops = [FakeOp(5), FakeOp(4, FLOAT)]
+ py.test.raises(AssertionError, assign_all_varindices, ops)
+ ops = [FakeOp(4, FLOAT), FakeOp(5)]
+ py.test.raises(AssertionError, assign_all_varindices, ops)
+
+ ops = [FakeOp(), FakeOp(type=FLOAT), FakeOp(1)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [0, 2, 1]
+
+ ops = [FakeOp(), FakeOp(type=FLOAT), FakeOp(2)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [0, 3, 2]
+
+ ops = [FakeOp(), FakeOp(type=FLOAT), FakeOp(3)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [0, 1, 3]
+
+ ops = [FakeOp(), FakeOp(type=FLOAT), FakeOp(2, FLOAT)]
+ assign_all_varindices(ops)
+ assert indices(ops) == [0, 4, 2]
More information about the pypy-commit
mailing list