mirror of
https://github.com/python/cpython.git
synced 2025-07-12 05:45:15 +00:00
[3.10] bpo-45773: Stop "optimizing" certain jump patterns (GH-29526)
This commit is contained in:
parent
c5bfb88eb6
commit
a89bbde83f
6 changed files with 60 additions and 81 deletions
115
Python/compile.c
115
Python/compile.c
|
@ -21,6 +21,8 @@
|
|||
* objects.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_ast.h" // _PyAST_GetDocString()
|
||||
#include "pycore_compile.h" // _PyFuture_FromAST()
|
||||
|
@ -7264,25 +7266,24 @@ fold_rotations(struct instr *inst, int n)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
eliminate_jump_to_jump(basicblock *bb, int opcode) {
|
||||
assert (bb->b_iused > 0);
|
||||
struct instr *inst = &bb->b_instr[bb->b_iused-1];
|
||||
assert (is_jump(inst));
|
||||
assert (inst->i_target->b_iused > 0);
|
||||
struct instr *target = &inst->i_target->b_instr[0];
|
||||
if (inst->i_target == target->i_target) {
|
||||
/* Nothing to do */
|
||||
return 0;
|
||||
// Attempt to eliminate jumps to jumps by updating inst to jump to
|
||||
// target->i_target using the provided opcode. Return whether or not the
|
||||
// optimization was successful.
|
||||
static bool
|
||||
jump_thread(struct instr *inst, struct instr *target, int opcode)
|
||||
{
|
||||
assert(is_jump(inst));
|
||||
assert(is_jump(target));
|
||||
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
|
||||
// changes (and we fall into an infinite loop):
|
||||
if (inst->i_lineno == target->i_lineno &&
|
||||
inst->i_target != target->i_target)
|
||||
{
|
||||
inst->i_target = target->i_target;
|
||||
inst->i_opcode = opcode;
|
||||
return true;
|
||||
}
|
||||
int lineno = target->i_lineno;
|
||||
if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) {
|
||||
return -1;
|
||||
}
|
||||
assert (bb->b_iused >= 2);
|
||||
bb->b_instr[bb->b_iused-2].i_opcode = NOP;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Maximum size of basic block that should be copied in optimizer */
|
||||
|
@ -7399,25 +7400,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
|||
where y+1 is the instruction following the second test.
|
||||
*/
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
switch(target->i_opcode) {
|
||||
switch (target->i_opcode) {
|
||||
case POP_JUMP_IF_FALSE:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
*inst = *target;
|
||||
i--;
|
||||
}
|
||||
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
|
||||
break;
|
||||
case JUMP_ABSOLUTE:
|
||||
case JUMP_FORWARD:
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
if (inst->i_lineno == target->i_lineno &&
|
||||
inst->i_target != target->i_target) {
|
||||
inst->i_target = target->i_target;
|
||||
i--;
|
||||
}
|
||||
i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP);
|
||||
break;
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
assert (inst->i_target->b_iused == 1);
|
||||
case POP_JUMP_IF_TRUE:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
// We don't need to bother checking for loops here,
|
||||
// since a block's b_next cannot point to itself:
|
||||
assert(inst->i_target != inst->i_target->b_next);
|
||||
inst->i_opcode = POP_JUMP_IF_FALSE;
|
||||
inst->i_target = inst->i_target->b_next;
|
||||
--i;
|
||||
|
@ -7425,27 +7422,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
switch(target->i_opcode) {
|
||||
switch (target->i_opcode) {
|
||||
case POP_JUMP_IF_TRUE:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
*inst = *target;
|
||||
i--;
|
||||
}
|
||||
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
|
||||
break;
|
||||
case JUMP_ABSOLUTE:
|
||||
case JUMP_FORWARD:
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
if (inst->i_lineno == target->i_lineno &&
|
||||
inst->i_target != target->i_target) {
|
||||
inst->i_target = target->i_target;
|
||||
i--;
|
||||
}
|
||||
i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP);
|
||||
break;
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
assert (inst->i_target->b_iused == 1);
|
||||
case POP_JUMP_IF_FALSE:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
// We don't need to bother checking for loops here,
|
||||
// since a block's b_next cannot point to itself:
|
||||
assert(inst->i_target != inst->i_target->b_next);
|
||||
inst->i_opcode = POP_JUMP_IF_TRUE;
|
||||
inst->i_target = inst->i_target->b_next;
|
||||
--i;
|
||||
|
@ -7453,54 +7445,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case POP_JUMP_IF_FALSE:
|
||||
switch(target->i_opcode) {
|
||||
switch (target->i_opcode) {
|
||||
case JUMP_ABSOLUTE:
|
||||
case JUMP_FORWARD:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
inst->i_target = target->i_target;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case POP_JUMP_IF_TRUE:
|
||||
switch(target->i_opcode) {
|
||||
switch (target->i_opcode) {
|
||||
case JUMP_ABSOLUTE:
|
||||
case JUMP_FORWARD:
|
||||
if (inst->i_lineno == target->i_lineno) {
|
||||
inst->i_target = target->i_target;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case JUMP_ABSOLUTE:
|
||||
case JUMP_FORWARD:
|
||||
assert (i == bb->b_iused-1);
|
||||
switch(target->i_opcode) {
|
||||
case JUMP_FORWARD:
|
||||
if (eliminate_jump_to_jump(bb, inst->i_opcode)) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
switch (target->i_opcode) {
|
||||
case JUMP_ABSOLUTE:
|
||||
if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case JUMP_FORWARD:
|
||||
i -= jump_thread(inst, target, JUMP_ABSOLUTE);
|
||||
}
|
||||
break;
|
||||
case FOR_ITER:
|
||||
assert (i == bb->b_iused-1);
|
||||
if (target->i_opcode == JUMP_FORWARD) {
|
||||
if (eliminate_jump_to_jump(bb, inst->i_opcode)) {
|
||||
goto error;
|
||||
}
|
||||
i -= jump_thread(inst, target, FOR_ITER);
|
||||
}
|
||||
break;
|
||||
case ROT_N:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue