gh-130480: Move duplicate LOAD_SMALL_INT optimization from codegen to CFG (#130481)

This commit is contained in:
Yan Yanchii 2025-03-14 22:23:27 +01:00 committed by GitHub
parent 26511993e6
commit 55815a6474
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 146 additions and 116 deletions

View file

@ -1297,6 +1297,7 @@ loads_const(int opcode)
return OPCODE_HAS_CONST(opcode) || opcode == LOAD_SMALL_INT;
}
/* Returns new reference */
static PyObject*
get_const_value(int opcode, int oparg, PyObject *co_consts)
{
@ -1390,19 +1391,43 @@ nop_out(cfg_instr **instrs, int size)
}
}
/* Does not steal reference to "newconst".
Return 1 if changed instruction to LOAD_SMALL_INT.
Return 0 if could not change instruction to LOAD_SMALL_INT.
Return -1 on error.
*/
static int
maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst,
PyObject *consts, PyObject *const_cache)
{
if (PyLong_CheckExact(newconst)) {
int overflow;
long val = PyLong_AsLongAndOverflow(newconst, &overflow);
if (val == -1 && PyErr_Occurred()) {
return -1;
}
if (!overflow && _PY_IS_SMALL_INT(val)) {
assert(_Py_IsImmortal(newconst));
INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val);
return 1;
}
}
return 0;
}
/* Steals reference to "newconst" */
static int
instr_make_load_const(cfg_instr *instr, PyObject *newconst,
PyObject *consts, PyObject *const_cache)
{
if (PyLong_CheckExact(newconst)) {
int overflow;
long val = PyLong_AsLongAndOverflow(newconst, &overflow);
if (!overflow && _PY_IS_SMALL_INT(val)) {
assert(_Py_IsImmortal(newconst));
INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val);
return SUCCESS;
}
int res = maybe_instr_make_load_smallint(instr, newconst, consts, const_cache);
if (res < 0) {
Py_DECREF(newconst);
return ERROR;
}
if (res > 0) {
return SUCCESS;
}
int oparg = add_const(newconst, consts, const_cache);
RETURN_IF_ERROR(oparg);
@ -2042,6 +2067,14 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *
int oparg = 0;
for (int i = 0; i < bb->b_iused; i++) {
cfg_instr *inst = &bb->b_instr[i];
if (inst->i_opcode == LOAD_CONST) {
PyObject *constant = get_const_value(inst->i_opcode, inst->i_oparg, consts);
int res = maybe_instr_make_load_smallint(inst, constant, consts, const_cache);
Py_DECREF(constant);
if (res < 0) {
return ERROR;
}
}
bool is_copy_of_load_const = (opcode == LOAD_CONST &&
inst->i_opcode == COPY &&
inst->i_oparg == 1);