[pypy-svn] pypy default: A peepoler optimization: a JUMP to RETURN becomes a RETURN.

amauryfa commits-noreply at bitbucket.org
Wed Jan 19 20:33:35 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r40953:8332e72b048f
Date: 2011-01-19 20:32 +0100
http://bitbucket.org/pypy/pypy/changeset/8332e72b048f/

Log:	A peepoler optimization: a JUMP to RETURN becomes a RETURN.

diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1,9 +1,10 @@
 import py
-from pypy.interpreter.astcompiler import codegen, astbuilder
+from pypy.interpreter.astcompiler import codegen, astbuilder, symtable
 from pypy.interpreter.pyparser import pyparse
 from pypy.interpreter.pyparser.test import expressions
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.pyparser.error import SyntaxError, IndentationError
+from pypy.tool import stdlib_opcode as ops
 
 def compile_with_astcompiler(expr, mode, space):
     p = pyparse.PythonParser(space)
@@ -12,6 +13,18 @@
     ast = astbuilder.ast_from_node(space, cst, info)
     return codegen.compile_ast(space, ast, info)
 
+def generate_function_code(expr, space):
+    p = pyparse.PythonParser(space)
+    info = pyparse.CompileInfo("<test>", 'exec')
+    cst = p.parse_source(expr, info)
+    ast = astbuilder.ast_from_node(space, cst, info)
+    function_ast = ast.body[0]
+    symbols = symtable.SymtableBuilder(space, ast, info)
+    generator = codegen.FunctionCodeGenerator(
+        space, 'function', function_ast, 1, symbols, info)
+    blocks = generator.first_block.post_order()
+    generator._resolve_block_targets(blocks)
+    return generator, blocks
 
 class TestCompiler:
     """These tests compile snippets of code and check them by
@@ -771,3 +784,21 @@
          print >> s, "hi", "lovely!",
          assert s.getvalue() == "hi lovely!"
          """ in {}
+
+class TestOptimizations:
+
+    def test_elim_jump_to_return(self):
+        source = """def f():
+        return true_value if cond else false_value
+        """
+        code, blocks = generate_function_code(source, self.space)
+        instrs = []
+        for block in blocks:
+            instrs.extend(block.instructions)
+        print instrs
+        counts = {}
+        for instr in instrs:
+            counts[instr.opcode] = counts.get(instr.opcode, 0) + 1
+        assert ops.JUMP_FORWARD not in counts
+        assert ops.JUMP_ABSOLUTE not in counts
+        assert counts[ops.RETURN_VALUE] == 2

diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -286,6 +286,12 @@
                                     target = target.instructions[0].jump[0]
                                     instr.opcode = ops.JUMP_ABSOLUTE
                                     absolute = True
+                                elif target_op == ops.RETURN_VALUE:
+                                    # Replace JUMP_* to a RETURN into just a RETURN
+                                    instr.opcode = ops.RETURN_VALUE
+                                    instr.arg = 0
+                                    instr.has_jump = False
+                                    continue
                         if absolute:
                             jump_arg = target.offset
                         else:


More information about the Pypy-commit mailing list