Update the peephole optimizer to remove more dead code (jumps after returns)
and inline jumps to returns.
This commit is contained in:
parent
5a72372329
commit
cbeb687c68
|
@ -161,6 +161,41 @@ class TestTranforms(unittest.TestCase):
|
||||||
self.assert_('(None)' not in asm)
|
self.assert_('(None)' not in asm)
|
||||||
self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
|
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):
|
def test_main(verbose=None):
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1?
|
||||||
Core and builtins
|
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
|
- Bug #1545497: when given an explicit base, int() did ignore NULs
|
||||||
embedded in the string to convert.
|
embedded in the string to convert.
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,10 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
|
||||||
Python 2.5c1: 62121 (fix wrong lnotab with for loops and
|
Python 2.5c1: 62121 (fix wrong lnotab with for loops and
|
||||||
storing constants that should have been removed)
|
storing constants that should have been removed)
|
||||||
Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp)
|
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
|
/* Magic word as global; note that _PyImport_Init() can change the
|
||||||
value of this global to accommodate for alterations of how the
|
value of this global to accommodate for alterations of how the
|
||||||
|
|
|
@ -523,6 +523,13 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
||||||
case SETUP_EXCEPT:
|
case SETUP_EXCEPT:
|
||||||
case SETUP_FINALLY:
|
case SETUP_FINALLY:
|
||||||
tgt = GETJUMPTGT(codestr, i);
|
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]))
|
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
|
||||||
continue;
|
continue;
|
||||||
tgttgt = GETJUMPTGT(codestr, tgt);
|
tgttgt = GETJUMPTGT(codestr, tgt);
|
||||||
|
@ -540,12 +547,16 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
||||||
goto exitUnchanged;
|
goto exitUnchanged;
|
||||||
|
|
||||||
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
|
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
|
||||||
|
/* Remove unreachable JUMPs after RETURN */
|
||||||
case RETURN_VALUE:
|
case RETURN_VALUE:
|
||||||
if (i+4 >= codelen ||
|
if (i+4 >= codelen)
|
||||||
codestr[i+4] != RETURN_VALUE ||
|
|
||||||
!ISBASICBLOCK(blocks,i,5))
|
|
||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue