gh-106149: move unconditional jump direction resolution from optimizer to assembler (#106291)

This commit is contained in:
Irit Katriel 2023-07-01 11:28:07 +01:00 committed by GitHub
parent d3abc9b516
commit 200f255411
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 20 deletions

View file

@ -674,11 +674,45 @@ resolve_jump_offsets(instr_sequence *instrs)
return SUCCESS;
}
static int
resolve_unconditional_jumps(instr_sequence *instrs)
{
/* Resolve directions of unconditional jumps */
for (int i = 0; i < instrs->s_used; i++) {
instruction *instr = &instrs->s_instrs[i];
bool is_forward = (instr->i_oparg > i);
switch(instr->i_opcode) {
case JUMP:
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
break;
case JUMP_NO_INTERRUPT:
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
instr->i_opcode = is_forward ?
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
break;
default:
if (OPCODE_HAS_JUMP(instr->i_opcode) &&
IS_PSEUDO_INSTR(instr->i_opcode)) {
Py_UNREACHABLE();
}
}
}
return SUCCESS;
}
PyCodeObject *
_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
PyObject *consts, int maxdepth, instr_sequence *instrs,
int nlocalsplus, int code_flags, PyObject *filename)
{
if (resolve_unconditional_jumps(instrs) < 0) {
return NULL;
}
if (resolve_jump_offsets(instrs) < 0) {
return NULL;
}

View file

@ -393,24 +393,17 @@ no_redundant_jumps(cfg_builder *g) {
static int
normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
cfg_instr *last = _PyCfg_BasicblockLastInstr(b);
if (last == NULL || !is_jump(last)) {
if (last == NULL || !is_jump(last) ||
IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
return SUCCESS;
}
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
bool is_forward = last->i_target->b_visited == 0;
switch(last->i_opcode) {
case JUMP:
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
return SUCCESS;
case JUMP_NO_INTERRUPT:
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
last->i_opcode = is_forward ?
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
return SUCCESS;
if (is_forward) {
return SUCCESS;
}
int reversed_opcode = 0;
switch(last->i_opcode) {
case POP_JUMP_IF_NOT_NONE:
@ -426,9 +419,6 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
reversed_opcode = POP_JUMP_IF_FALSE;
break;
}
if (is_forward) {
return SUCCESS;
}
/* transform 'conditional jump T' to
* 'reversed_jump b_next' followed by 'jump_backwards T'
*/

View file

@ -4,7 +4,7 @@
// Do not edit!
#define IS_PSEUDO_INSTR(OP) \
#define IS_PSEUDO_INSTR(OP) ( \
((OP) == LOAD_CLOSURE) || \
((OP) == STORE_FAST_MAYBE_NULL) || \
((OP) == LOAD_SUPER_METHOD) || \
@ -17,7 +17,7 @@
((OP) == SETUP_CLEANUP) || \
((OP) == SETUP_WITH) || \
((OP) == POP_BLOCK) || \
0
0)
#define EXIT_TRACE 300
#define SET_IP 301