[pypy-svn] pypy default: Remove code that the compiler attempt to put in a basic block

arigo commits-noreply at bitbucket.org
Sat Feb 12 23:00:33 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41863:09525c62ac04
Date: 2011-02-12 22:59 +0100
http://bitbucket.org/pypy/pypy/changeset/09525c62ac04/

Log:	Remove code that the compiler attempt to put in a basic block after
	a RETURN_VALUE statement. Such code would be dead. It should be
	enough to pass test_peepholer, hopefully.

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
@@ -818,4 +818,43 @@
         return (0, 1)[:2]
         """
         # Just checking this doesn't crash out
-        self.count_instructions(source)
\ No newline at end of file
+        self.count_instructions(source)
+
+    def test_remove_dead_code(self):
+        source = """def f(x):
+            return 5
+            x += 1
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_CONST:1, ops.RETURN_VALUE: 1}
+
+    def test_remove_dead_jump_after_return(self):
+        source = """def f(x, y, z):
+            if x:
+                return y
+            else:
+                return z
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_FAST: 3,
+                          ops.POP_JUMP_IF_FALSE: 1,
+                          ops.RETURN_VALUE: 2}
+
+    def test_remove_dead_yield(self):
+        source = """def f(x):
+            return
+            yield 6
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_CONST:1, ops.RETURN_VALUE: 1}
+        #
+        space = self.space
+        w_generator = space.appexec([], """():
+            d = {}
+            exec '''def f(x):
+                return
+                yield 6
+            ''' in d
+            return d['f'](5)
+        """)
+        assert 'generator' in space.str_w(space.repr(w_generator))

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
@@ -167,15 +167,22 @@
         self.use_block(block)
         return block
 
+    def is_dead_code(self):
+        """Return False if any code can be meaningfully added to the
+        current block, or True if it would be dead code."""
+        # currently only True after a RETURN_VALUE.
+        return self.current_block.have_return
+
     def emit_op(self, op):
         """Emit an opcode without an argument."""
         instr = Instruction(op)
         if not self.lineno_set:
             instr.lineno = self.lineno
             self.lineno_set = True
-        self.instrs.append(instr)
-        if op == ops.RETURN_VALUE:
-            self.current_block.have_return = True
+        if not self.is_dead_code():
+            self.instrs.append(instr)
+            if op == ops.RETURN_VALUE:
+                self.current_block.have_return = True
         return instr
 
     def emit_op_arg(self, op, arg):
@@ -184,7 +191,8 @@
         if not self.lineno_set:
             instr.lineno = self.lineno
             self.lineno_set = True
-        self.instrs.append(instr)
+        if not self.is_dead_code():
+            self.instrs.append(instr)
 
     def emit_op_name(self, op, container, name):
         """Emit an opcode referencing a name."""


More information about the Pypy-commit mailing list