GH-125837: Split LOAD_CONST into three. (GH-125972)

* Add LOAD_CONST_IMMORTAL opcode

* Add LOAD_SMALL_INT opcode

* Remove RETURN_CONST opcode
This commit is contained in:
Mark Shannon 2024-10-29 11:15:42 +00:00 committed by GitHub
parent 67f5c5bd6f
commit faa3272fb8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 706 additions and 538 deletions

View file

@ -283,7 +283,7 @@ dump_instr(cfg_instr *i)
static inline int
basicblock_returns(const basicblock *b) {
cfg_instr *last = basicblock_last_instr(b);
return last && (last->i_opcode == RETURN_VALUE || last->i_opcode == RETURN_CONST);
return last && last->i_opcode == RETURN_VALUE;
}
static void
@ -515,22 +515,6 @@ no_redundant_jumps(cfg_builder *g) {
}
return true;
}
static bool
all_exits_have_lineno(basicblock *entryblock) {
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
cfg_instr *instr = &b->b_instr[i];
if (instr->i_opcode == RETURN_VALUE) {
if (instr->i_loc.lineno < 0) {
assert(0);
return false;
}
}
}
}
return true;
}
#endif
/***** CFG preprocessing (jump targets and exceptions) *****/
@ -1131,7 +1115,7 @@ remove_redundant_nops_and_pairs(basicblock *entryblock)
int opcode = instr->i_opcode;
bool is_redundant_pair = false;
if (opcode == POP_TOP) {
if (prev_opcode == LOAD_CONST) {
if (prev_opcode == LOAD_CONST || prev_opcode == LOAD_SMALL_INT) {
is_redundant_pair = true;
}
else if (prev_opcode == COPY && prev_oparg == 1) {
@ -1280,14 +1264,23 @@ jump_thread(basicblock *bb, cfg_instr *inst, cfg_instr *target, int opcode)
return false;
}
static int
loads_const(int opcode)
{
return OPCODE_HAS_CONST(opcode) || opcode == LOAD_SMALL_INT;
}
static PyObject*
get_const_value(int opcode, int oparg, PyObject *co_consts)
{
PyObject *constant = NULL;
assert(OPCODE_HAS_CONST(opcode));
assert(loads_const(opcode));
if (opcode == LOAD_CONST) {
constant = PyList_GET_ITEM(co_consts, oparg);
}
if (opcode == LOAD_SMALL_INT) {
return PyLong_FromLong(oparg);
}
if (constant == NULL) {
PyErr_SetString(PyExc_SystemError,
@ -1345,7 +1338,7 @@ fold_tuple_on_constants(PyObject *const_cache,
assert(inst[n].i_oparg == n);
for (int i = 0; i < n; i++) {
if (!OPCODE_HAS_CONST(inst[i].i_opcode)) {
if (!loads_const(inst[i].i_opcode)) {
return SUCCESS;
}
}
@ -1583,7 +1576,7 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *
oparg = inst->i_oparg;
}
assert(!IS_ASSEMBLER_OPCODE(opcode));
if (opcode != LOAD_CONST) {
if (opcode != LOAD_CONST && opcode != LOAD_SMALL_INT) {
continue;
}
int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
@ -1662,12 +1655,6 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *
: POP_JUMP_IF_NONE;
break;
}
case RETURN_VALUE:
{
INSTR_SET_OP0(inst, NOP);
INSTR_SET_OP1(&bb->b_instr[++i], RETURN_CONST, oparg);
break;
}
case TO_BOOL:
{
PyObject *cnt = get_const_value(opcode, oparg, consts);
@ -2120,7 +2107,8 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
/* mark used consts */
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int opcode = b->b_instr[i].i_opcode;
if (OPCODE_HAS_CONST(opcode)) {
int index = b->b_instr[i].i_oparg;
index_map[index] = index;
}
@ -2173,7 +2161,8 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int opcode = b->b_instr[i].i_opcode;
if (OPCODE_HAS_CONST(opcode)) {
int index = b->b_instr[i].i_oparg;
assert(reverse_index_map[index] >= 0);
assert(reverse_index_map[index] < n_used_consts);
@ -2594,8 +2583,9 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache,
RETURN_IF_ERROR(insert_superinstructions(g));
RETURN_IF_ERROR(push_cold_blocks_to_end(g));
assert(all_exits_have_lineno(g->g_entryblock));
RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));
// temporarily remove assert. See https://github.com/python/cpython/issues/125845
// assert(all_exits_have_lineno(g->g_entryblock));
return SUCCESS;
}