diff options
author | Om G <34579088+OmG-117@users.noreply.github.com> | 2020-12-16 12:18:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-16 12:18:05 (GMT) |
commit | c71581c7a4192e6ba9a79eccc583aaadab300efa (patch) | |
tree | 9d42fd9c2bbf583cd7259672abe62c98c28cedc0 /Python/compile.c | |
parent | 8203c73f3bb1f51614279b6e23af2ec587d1fa22 (diff) | |
download | cpython-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.c | 42 |
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; } |