summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal Norwitz <nnorwitz@gmail.com>2006-10-14 21:33:38 (GMT)
committerNeal Norwitz <nnorwitz@gmail.com>2006-10-14 21:33:38 (GMT)
commitcbeb687c687e6edebd3afdb63be0a623294e744c (patch)
tree273d96ffef6560a4991173538ec512cdabf2cd79
parent5a72372329e0c6a47d226cdc33f7a22e424bb0d0 (diff)
downloadcpython-cbeb687c687e6edebd3afdb63be0a623294e744c.zip
cpython-cbeb687c687e6edebd3afdb63be0a623294e744c.tar.gz
cpython-cbeb687c687e6edebd3afdb63be0a623294e744c.tar.bz2
Update the peephole optimizer to remove more dead code (jumps after returns)
and inline jumps to returns.
-rw-r--r--Lib/test/test_peepholer.py35
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/import.c3
-rw-r--r--Python/peephole.c19
4 files changed, 55 insertions, 5 deletions
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index 4385a84..02b04e0 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -161,6 +161,41 @@ class TestTranforms(unittest.TestCase):
self.assert_('(None)' not in asm)
self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
+ def test_elim_jump_to_return(self):
+ # JUMP_FORWARD to RETURN --> RETURN
+ def f(cond, true_value, false_value):
+ return true_value if cond else false_value
+ asm = disassemble(f)
+ self.assert_('JUMP_FORWARD' not in asm)
+ self.assert_('JUMP_ABSOLUTE' not in asm)
+ self.assertEqual(asm.split().count('RETURN_VALUE'), 2)
+
+ def test_elim_jump_after_return1(self):
+ # Eliminate dead code: jumps immediately after returns can't be reached
+ def f(cond1, cond2):
+ if cond1: return 1
+ if cond2: return 2
+ while 1:
+ return 3
+ while 1:
+ if cond1: return 4
+ return 5
+ return 6
+ asm = disassemble(f)
+ self.assert_('JUMP_FORWARD' not in asm)
+ self.assert_('JUMP_ABSOLUTE' not in asm)
+ self.assertEqual(asm.split().count('RETURN_VALUE'), 6)
+
+ def test_elim_jump_after_return2(self):
+ # Eliminate dead code: jumps immediately after returns can't be reached
+ def f(cond1, cond2):
+ while 1:
+ if cond1: return 4
+ asm = disassemble(f)
+ self.assert_('JUMP_FORWARD' not in asm)
+ # There should be one jump for the while loop.
+ self.assertEqual(asm.split().count('JUMP_ABSOLUTE'), 1)
+ self.assertEqual(asm.split().count('RETURN_VALUE'), 2)
def test_main(verbose=None):
diff --git a/Misc/NEWS b/Misc/NEWS
index cd21eea..9800a9b 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1?
Core and builtins
-----------------
+- Update the peephole optimizer to remove more dead code (jumps after returns)
+ and inline unconditional jumps to returns.
+
- Bug #1545497: when given an explicit base, int() did ignore NULs
embedded in the string to convert.
diff --git a/Python/import.c b/Python/import.c
index a90729a..45c5507 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -65,9 +65,10 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
Python 2.5c1: 62121 (fix wrong lnotab with for loops and
storing constants that should have been removed)
Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp)
+ Python 2.6a0: 62141 (peephole optimizations)
.
*/
-#define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24))
+#define MAGIC (62141 | ((long)'\r'<<16) | ((long)'\n'<<24))
/* Magic word as global; note that _PyImport_Init() can change the
value of this global to accommodate for alterations of how the
diff --git a/Python/peephole.c b/Python/peephole.c
index 1d94319..f2fe6ce 100644
--- a/Python/peephole.c
+++ b/Python/peephole.c
@@ -523,6 +523,13 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
case SETUP_EXCEPT:
case SETUP_FINALLY:
tgt = GETJUMPTGT(codestr, i);
+ /* Replace JUMP_* to a RETURN into just a RETURN */
+ if (UNCONDITIONAL_JUMP(opcode) &&
+ codestr[tgt] == RETURN_VALUE) {
+ codestr[i] = RETURN_VALUE;
+ memset(codestr+i+1, NOP, 2);
+ continue;
+ }
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
continue;
tgttgt = GETJUMPTGT(codestr, tgt);
@@ -540,12 +547,16 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
goto exitUnchanged;
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
+ /* Remove unreachable JUMPs after RETURN */
case RETURN_VALUE:
- if (i+4 >= codelen ||
- codestr[i+4] != RETURN_VALUE ||
- !ISBASICBLOCK(blocks,i,5))
+ if (i+4 >= codelen)
continue;
- memset(codestr+i+1, NOP, 4);
+ if (codestr[i+4] == RETURN_VALUE &&
+ ISBASICBLOCK(blocks,i,5))
+ memset(codestr+i+1, NOP, 4);
+ else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
+ ISBASICBLOCK(blocks,i,4))
+ memset(codestr+i+1, NOP, 3);
break;
}
}