[pypy-svn] r74120 - in pypy/branch/blackhole-improvement/pypy/jit/codewriter: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Apr 27 19:25:46 CEST 2010
Author: arigo
Date: Tue Apr 27 19:25:45 2010
New Revision: 74120
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
Log:
Lots of messy but local code to transform graphs containing
the operation int_floordiv_ovf_zer.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py Tue Apr 27 19:25:45 2010
@@ -1,7 +1,8 @@
+import sys
from pypy.rpython.lltypesystem import lltype, rstr
from pypy.jit.metainterp.history import getkind
from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.objspace.flow.model import c_last_exception
+from pypy.objspace.flow.model import Block, Link, c_last_exception
from pypy.jit.codewriter.flatten import ListOfKind
@@ -24,7 +25,7 @@
def transform(self, graph):
self.graph = graph
- for block in graph.iterblocks():
+ for block in list(graph.iterblocks()):
self.optimize_block(block)
def optimize_block(self, block):
@@ -34,6 +35,7 @@
newoperations = []
if block.exitswitch == c_last_exception:
op_raising_exception = block.operations[-1]
+ self.rewrite_exception_operation(op_raising_exception, block)
else:
op_raising_exception = Ellipsis
for op in block.operations:
@@ -86,7 +88,7 @@
if len(block.exits) != 2:
return False
v = block.exitswitch
- if v.concretetype != lltype.Bool:
+ if isinstance(v, tuple) or v.concretetype != lltype.Bool:
return False
for link in block.exits:
if v in link.args:
@@ -120,6 +122,78 @@
# ----------
+ def rewrite_exception_operation(self, op, block):
+ # mangling of the graph for exception-raising operations that are
+ # not simple calls
+ try:
+ rewrite = _rewrite_exc_ops[op.opname]
+ except KeyError:
+ pass
+ else:
+ rewrite(self, op, block)
+
+ def rewrite_exc_op_int_floordiv_ovf_zer(self, op, block):
+ # See test_flatten.test_int_floordiv_ovf_zer for the mangling done here
+ usedvars = self.list_vars_in_use_at_end(block, op.args, op.result)
+ block.operations.pop()
+ [ovf_link, zer_link] = self.extract_exc_links(block, [
+ OverflowError, ZeroDivisionError])
+ block = self.write_new_condition(block, usedvars, zer_link,
+ ('int_is_true', op.args[1]))
+ v1 = Variable(); v1.concretetype = lltype.Signed
+ v2 = Variable(); v2.concretetype = lltype.Signed
+ block.operations += [
+ SpaceOperation('int_add', [op.args[0],
+ Constant(sys.maxint, lltype.Signed)],
+ v1),
+ SpaceOperation('int_and', [v1, op.args[1]], v2),
+ ]
+ block = self.write_new_condition(block, usedvars, ovf_link,
+ ('int_ne', v2, Constant(-1, lltype.Signed)))
+ block.operations += [
+ SpaceOperation('int_floordiv', op.args, op.result),
+ ]
+
+ def list_vars_in_use_at_end(self, block, extravars=[], exclude=None):
+ lists = [extravars]
+ for link in block.exits:
+ lists.append(link.args)
+ in_use = set()
+ for lst in lists:
+ for v in lst:
+ if isinstance(v, Variable):
+ in_use.add(v)
+ if exclude in in_use:
+ in_use.remove(exclude)
+ return list(in_use)
+
+ def extract_exc_links(self, block, exceptions):
+ # Remove the exception links from the block. The exception links must
+ # be catching exactly the listed 'exceptions'. We return them to the
+ # caller.
+ assert block.exits[0].exitcase is None
+ real_exc_links = dict([(link.exitcase, link)
+ for link in block.exits[1:]])
+ assert dict.fromkeys(real_exc_links) == dict.fromkeys(exceptions)
+ block.recloseblock(block.exits[0])
+ return [real_exc_links[exc] for exc in exceptions]
+
+ def write_new_condition(self, block, usedvars, exc_link, exitswitch):
+ # Write an exit at the end of the block, going either to a new
+ # block that is the continuation of the current block, or (in case
+ # 'exitswitch' is False) following the given 'exc_link'.
+ newblock = Block(usedvars)
+ normal_link = Link(usedvars, newblock)
+ normal_link.exitcase = normal_link.llexitcase = True
+ exc_link.exitcase = exc_link.llexitcase = False
+ block.exitswitch = exitswitch
+ [exit] = block.exits
+ block.recloseblock(normal_link, exc_link)
+ newblock.closeblock(exit)
+ return newblock
+
+ # ----------
+
def rewrite_operation(self, op):
try:
rewrite = _rewrite_ops[op.opname]
@@ -265,10 +339,15 @@
# ____________________________________________________________
-_rewrite_ops = {}
-for _name in dir(Transformer):
- if _name.startswith('rewrite_op_'):
- _rewrite_ops[_name[len('rewrite_op_'):]] = getattr(Transformer, _name)
+def _with_prefix(prefix):
+ result = {}
+ for name in dir(Transformer):
+ if name.startswith(prefix):
+ result[name[len(prefix):]] = getattr(Transformer, name)
+ return result
+
+_rewrite_ops = _with_prefix('rewrite_op_')
+_rewrite_exc_ops = _with_prefix('rewrite_exc_op_')
primitive_type_size = {
lltype.Signed: 'i',
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py Tue Apr 27 19:25:45 2010
@@ -329,8 +329,9 @@
""", transform=True)
def test_int_floordiv_ovf_zer(self):
- py.test.skip("in-progress")
def f(i, j):
+ assert i >= 0
+ assert j >= 0
try:
return ovfcheck(i // j)
except OverflowError:
@@ -346,8 +347,8 @@
goto_if_not_int_ne L2, %i3, $-1
int_floordiv %i0, %i1, %i4
int_return %i4
- L1:
- int_return $-42
L2:
int_return $42
+ L1:
+ int_return $-42
""".replace('MAXINT', str(sys.maxint)), transform=True)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py Tue Apr 27 19:25:45 2010
@@ -1,12 +1,14 @@
-import py
+import py, sys
from pypy.jit.codewriter import support
from pypy.jit.codewriter.regalloc import perform_register_allocation
from pypy.jit.codewriter.flatten import flatten_graph, ListOfKind
from pypy.jit.codewriter.format import format_assembler
+from pypy.jit.codewriter.jitter import transform_graph
from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
from pypy.objspace.flow.model import FunctionGraph, Block, Link
from pypy.objspace.flow.model import c_last_exception
from pypy.rpython.lltypesystem import lltype, rclass
+from pypy.rlib.rarithmetic import ovfcheck
class TestRegAlloc:
@@ -15,10 +17,12 @@
self.rtyper = support.annotate(func, values, type_system=type_system)
return self.rtyper.annotator.translator.graphs
- def check_assembler(self, graph, expected):
- """Only for simple graphs. More complex graphs must first be
- transformed by jitter.py before they can be subjected to
- register allocation and flattening."""
+ def check_assembler(self, graph, expected, transform=False):
+ # 'transform' can be False only for simple graphs. More complex
+ # graphs must first be transformed by jitter.py before they can be
+ # subjected to register allocation and flattening.
+ if transform:
+ transform_graph(graph)
regalloc = perform_register_allocation(graph, 'int')
ssarepr = flatten_graph(graph, {'int': regalloc})
asm = format_assembler(ssarepr)
@@ -176,3 +180,27 @@
L2:
reraise
""")
+
+ def test_int_floordiv_ovf_zer(self):
+ def f(i, j):
+ assert i >= 0
+ assert j >= 0
+ try:
+ return ovfcheck(i // j)
+ except OverflowError:
+ return 42
+ except ZeroDivisionError:
+ return -42
+ graph = self.make_graphs(f, [5, 6])[0]
+ self.check_assembler(graph, """
+ goto_if_not_int_is_true L1, %i1
+ int_add %i0, $MAXINT, %i2
+ int_and %i2, %i1, %i2
+ goto_if_not_int_ne L2, %i2, $-1
+ int_floordiv %i0, %i1, %i0
+ int_return %i0
+ L2:
+ int_return $42
+ L1:
+ int_return $-42
+ """.replace('MAXINT', str(sys.maxint)), transform=True)
More information about the Pypy-commit
mailing list