summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorOm G <34579088+OmG-117@users.noreply.github.com>2020-12-16 12:18:05 (GMT)
committerGitHub <noreply@github.com>2020-12-16 12:18:05 (GMT)
commitc71581c7a4192e6ba9a79eccc583aaadab300efa (patch)
tree9d42fd9c2bbf583cd7259672abe62c98c28cedc0 /Python/compile.c
parent8203c73f3bb1f51614279b6e23af2ec587d1fa22 (diff)
downloadcpython-c71581c7a4192e6ba9a79eccc583aaadab300efa.zip
cpython-c71581c7a4192e6ba9a79eccc583aaadab300efa.tar.gz
cpython-c71581c7a4192e6ba9a79eccc583aaadab300efa.tar.bz2
bpo-42615: Delete redundant jump instructions that only bypass empty blocks (GH-23733)
* Delete jump instructions that bypass empty blocks * Add news entry * Explicitly check for unconditional jump opcodes Using the is_jump function results in the inclusion of instructions like returns for which this optimization is not really valid. So, instead explicitly check that the instruction is an unconditional jump. * Handle conditional jumps, delete jumps gracefully * Ensure b_nofallthrough and b_reachable are valid * Add test for redundant jumps * Regenerate importlib.h and edit Misc/ACKS * Fix bad whitespace
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/Python/compile.c b/Python/compile.c
index ae92869..4792733 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -6437,8 +6437,50 @@ optimize_cfg(struct assembler *a, PyObject *consts)
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
if (b->b_reachable == 0) {
b->b_iused = 0;
+ b->b_nofallthrough = 0;
}
}
+ /* Delete jump instructions made redundant by previous step. If a non-empty
+ block ends with a jump instruction, check if the next non-empty block
+ reached through normal flow control is the target of that jump. If it
+ is, then the jump instruction is redundant and can be deleted.
+ */
+ for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
+ if (b->b_iused > 0) {
+ struct instr *b_last_instr = &b->b_instr[b->b_iused - 1];
+ if (b_last_instr->i_opcode == POP_JUMP_IF_FALSE ||
+ b_last_instr->i_opcode == POP_JUMP_IF_TRUE ||
+ b_last_instr->i_opcode == JUMP_ABSOLUTE ||
+ b_last_instr->i_opcode == JUMP_FORWARD) {
+ basicblock *b_next_act = b->b_next;
+ while (b_next_act != NULL && b_next_act->b_iused == 0) {
+ b_next_act = b_next_act->b_next;
+ }
+ if (b_last_instr->i_target == b_next_act) {
+ b->b_nofallthrough = 0;
+ switch(b_last_instr->i_opcode) {
+ case POP_JUMP_IF_FALSE:
+ case POP_JUMP_IF_TRUE:
+ b_last_instr->i_opcode = POP_TOP;
+ b_last_instr->i_target = NULL;
+ b_last_instr->i_oparg = 0;
+ break;
+ case JUMP_ABSOLUTE:
+ case JUMP_FORWARD:
+ b_last_instr->i_opcode = NOP;
+ clean_basic_block(b);
+ break;
+ }
+ /* The blocks after this one are now reachable through it */
+ b_next_act = b->b_next;
+ while (b_next_act != NULL && b_next_act->b_iused == 0) {
+ b_next_act->b_reachable = 1;
+ b_next_act = b_next_act->b_next;
+ }
+ }
+ }
+ }
+ }
minimize_lineno_table(a);
return 0;
}