[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