Skip to content

Commit 200f255

Browse files
authored
gh-106149: move unconditional jump direction resolution from optimizer to assembler (#106291)
1 parent d3abc9b commit 200f255

File tree

4 files changed

+44
-20
lines changed

4 files changed

+44
-20
lines changed

Python/assemble.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,11 +674,45 @@ resolve_jump_offsets(instr_sequence *instrs)
674674
return SUCCESS;
675675
}
676676

677+
static int
678+
resolve_unconditional_jumps(instr_sequence *instrs)
679+
{
680+
/* Resolve directions of unconditional jumps */
681+
682+
for (int i = 0; i < instrs->s_used; i++) {
683+
instruction *instr = &instrs->s_instrs[i];
684+
bool is_forward = (instr->i_oparg > i);
685+
switch(instr->i_opcode) {
686+
case JUMP:
687+
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
688+
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
689+
instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
690+
break;
691+
case JUMP_NO_INTERRUPT:
692+
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
693+
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
694+
instr->i_opcode = is_forward ?
695+
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
696+
break;
697+
default:
698+
if (OPCODE_HAS_JUMP(instr->i_opcode) &&
699+
IS_PSEUDO_INSTR(instr->i_opcode)) {
700+
Py_UNREACHABLE();
701+
}
702+
}
703+
}
704+
return SUCCESS;
705+
}
706+
677707
PyCodeObject *
678708
_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
679709
PyObject *consts, int maxdepth, instr_sequence *instrs,
680710
int nlocalsplus, int code_flags, PyObject *filename)
681711
{
712+
713+
if (resolve_unconditional_jumps(instrs) < 0) {
714+
return NULL;
715+
}
682716
if (resolve_jump_offsets(instrs) < 0) {
683717
return NULL;
684718
}

Python/flowgraph.c

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -393,24 +393,17 @@ no_redundant_jumps(cfg_builder *g) {
393393
static int
394394
normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
395395
cfg_instr *last = _PyCfg_BasicblockLastInstr(b);
396-
if (last == NULL || !is_jump(last)) {
396+
if (last == NULL || !is_jump(last) ||
397+
IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
397398
return SUCCESS;
398399
}
399400
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
401+
400402
bool is_forward = last->i_target->b_visited == 0;
401-
switch(last->i_opcode) {
402-
case JUMP:
403-
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
404-
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
405-
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
406-
return SUCCESS;
407-
case JUMP_NO_INTERRUPT:
408-
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
409-
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
410-
last->i_opcode = is_forward ?
411-
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
412-
return SUCCESS;
403+
if (is_forward) {
404+
return SUCCESS;
413405
}
406+
414407
int reversed_opcode = 0;
415408
switch(last->i_opcode) {
416409
case POP_JUMP_IF_NOT_NONE:
@@ -426,9 +419,6 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
426419
reversed_opcode = POP_JUMP_IF_FALSE;
427420
break;
428421
}
429-
if (is_forward) {
430-
return SUCCESS;
431-
}
432422
/* transform 'conditional jump T' to
433423
* 'reversed_jump b_next' followed by 'jump_backwards T'
434424
*/

Python/opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/generate_cases.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,10 +1310,10 @@ def write_metadata(self) -> None:
13101310

13111311
def write_pseudo_instrs(self) -> None:
13121312
"""Write the IS_PSEUDO_INSTR macro"""
1313-
self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP) \\")
1313+
self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP) ( \\")
13141314
for op in self.pseudos:
13151315
self.out.emit(f" ((OP) == {op}) || \\")
1316-
self.out.emit(f" 0")
1316+
self.out.emit(f" 0)")
13171317

13181318
def write_uop_items(self, make_text: typing.Callable[[str, int], str]) -> None:
13191319
"""Write '#define XXX NNN' for each uop"""

0 commit comments

Comments
 (0)