[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