[pypy-svn] r34376 - in pypy/dist/pypy: config translator/backendopt translator/backendopt/test

arigo at codespeak.net arigo at codespeak.net
Wed Nov 8 16:41:05 CET 2006


Author: arigo
Date: Wed Nov  8 16:41:04 2006
New Revision: 34376

Added:
   pypy/dist/pypy/translator/backendopt/removeassert.py   (contents, props changed)
   pypy/dist/pypy/translator/backendopt/test/test_removeassert.py   (contents, props changed)
Modified:
   pypy/dist/pypy/config/pypyoption.py
   pypy/dist/pypy/translator/backendopt/all.py
Log:
A backend optimization (disabled for now) which kills the checks that go
into 'raise AssertionError' branches in ll graphs.  This leaves some
useless computations behind (the expression in the 'assert' statement)
but the hope is that the C optimizer will remove them.


Modified: pypy/dist/pypy/config/pypyoption.py
==============================================================================
--- pypy/dist/pypy/config/pypyoption.py	(original)
+++ pypy/dist/pypy/config/pypyoption.py	Wed Nov  8 16:41:04 2006
@@ -191,6 +191,9 @@
                        requires=[("translation.stackless", False)]),
             BoolOption("clever_malloc_removal",
                        "Remove mallocs in a clever way", default=False),
+            BoolOption("remove_asserts",
+                       "Kill 'raise AssertionError', which lets the C "
+                       "optimizer remove the asserts", default=False),
             IntOption("inline_threshold", "Threshold when to inline functions",
                       default=1, cmdline=None),
         ]),

Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Wed Nov  8 16:41:04 2006
@@ -8,6 +8,7 @@
 from pypy.translator import simplify
 from pypy.translator.backendopt.escape import malloc_to_stack
 from pypy.translator.backendopt.mallocprediction import clever_inlining_and_malloc_removal
+from pypy.translator.backendopt.removeassert import remove_asserts
 from pypy.translator.backendopt.support import log
 from pypy.objspace.flow.model import checkgraph
 
@@ -15,7 +16,7 @@
     # sensible keywords are
     # raisingop2direct_call, inline_threshold, mallocs
     # merge_if_blocks, constfold, heap2stack
-    # clever_malloc_removal
+    # clever_malloc_removal, remove_asserts
 
     config = translator.config.translation.backendopt.copy()
     config.set(**kwds)
@@ -83,6 +84,9 @@
         for graph in graphs:
             constant_fold_graph(graph)
 
+    if config.remove_asserts:
+        remove_asserts(translator, graphs)
+
     if config.heap2stack:
         assert graphs is translator.graphs  # XXX for now
         malloc_to_stack(translator)

Added: pypy/dist/pypy/translator/backendopt/removeassert.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/removeassert.py	Wed Nov  8 16:41:04 2006
@@ -0,0 +1,38 @@
+from pypy.objspace.flow.model import Constant
+from pypy.translator.simplify import eliminate_empty_blocks, join_blocks
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import rclass
+
+
+def remove_asserts(translator, graphs):
+    rtyper = translator.rtyper
+    clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError)
+    r_AssertionError = rclass.getclassrepr(rtyper, clsdef)
+    ll_AssertionError = r_AssertionError.convert_const(AssertionError)
+
+    while graphs:
+        pending = []
+        for graph in graphs:
+            eliminate_empty_blocks(graph)
+            join_blocks(graph)
+            for link in graph.iterlinks():
+                if (link.target is graph.exceptblock
+                    and isinstance(link.args[0], Constant)
+                    and link.args[0].value == ll_AssertionError):
+                    kill_assertion_link(graph, link)
+                    pending.append(graph)
+                    break
+        graphs = pending
+
+
+def kill_assertion_link(graph, link):
+    block = link.prevblock
+    exits = list(block.exits)
+    if len(exits) > 1:
+        exits.remove(link)
+        if len(exits) == 1 and block.exitswitch.concretetype is lltype.Bool:
+            # condition no longer necessary
+            block.exitswitch = None
+            exits[0].exitcase = None
+            exits[0].llexitcase = None
+        block.recloseblock(*exits)

Added: pypy/dist/pypy/translator/backendopt/test/test_removeassert.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/test/test_removeassert.py	Wed Nov  8 16:41:04 2006
@@ -0,0 +1,62 @@
+from pypy.objspace.flow.model import summary
+from pypy.translator.backendopt.removeassert import remove_asserts
+from pypy.translator.backendopt.constfold import constant_fold_graph
+from pypy.translator.backendopt.test import test_constfold
+from pypy.translator.backendopt.test.test_constfold import check_graph
+
+
+def get_graph(fn, signature):
+    graph, t = test_constfold.get_graph(fn, signature)
+    constant_fold_graph(graph)
+    return graph, t
+
+def contains_raise(graph):
+    for link in graph.iterlinks():
+        if link.target is graph.exceptblock:
+            return True
+    else:
+        return False
+
+def check(fn, args, expected_result):
+    signature = [int] * len(args)   # for now
+    graph, t = get_graph(fn, signature)
+    remove_asserts(t, [graph])
+    assert not contains_raise(graph)
+    check_graph(graph, args, expected_result, t)
+
+
+def test_simple():
+    def fn(n):
+        assert n >= 1
+        return n-1
+    check(fn, [125], 124)
+
+def test_and():
+    def fn(n):
+        assert n >= 1 and n < 10
+        return n-1
+    check(fn, [1], 0)
+
+def test_or():
+    def fn(n):
+        assert n >= 1 or n % 2 == 0
+        return n-1
+    check(fn, [-120], -121)
+
+def test_isinstance():
+    class A:
+        pass
+    class B(A):
+        pass
+    def g(n):
+        if n > 10:
+            return A()
+        else:
+            b = B()
+            b.value = 321
+            return b
+    def fn(n):
+        x = g(n)
+        assert isinstance(x, B)
+        return x.value
+    check(fn, [5], 321)



More information about the Pypy-commit mailing list