mirror of
https://github.com/python/cpython.git
synced 2025-09-19 23:20:25 +00:00
gh-126835: Move constant tuple folding from ast_opt to CFG (#130769)
This commit is contained in:
parent
54efe296bc
commit
75103d975c
9 changed files with 264 additions and 172 deletions
|
@ -1482,6 +1482,95 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const
|
|||
return instr_make_load_const(instr, const_tuple, consts, const_cache);
|
||||
}
|
||||
|
||||
/* Replace:
|
||||
BUILD_LIST 0
|
||||
LOAD_CONST c1
|
||||
LIST_APPEND 1
|
||||
LOAD_CONST c2
|
||||
LIST_APPEND 1
|
||||
...
|
||||
LOAD_CONST cN
|
||||
LIST_APPEND 1
|
||||
CALL_INTRINSIC_1 INTRINSIC_LIST_TO_TUPLE
|
||||
with:
|
||||
LOAD_CONST (c1, c2, ... cN)
|
||||
*/
|
||||
static int
|
||||
fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i,
|
||||
PyObject *consts, PyObject *const_cache)
|
||||
{
|
||||
assert(PyDict_CheckExact(const_cache));
|
||||
assert(PyList_CheckExact(consts));
|
||||
assert(i >= 0);
|
||||
assert(i < bb->b_iused);
|
||||
|
||||
cfg_instr *intrinsic = &bb->b_instr[i];
|
||||
assert(intrinsic->i_opcode == CALL_INTRINSIC_1);
|
||||
assert(intrinsic->i_oparg == INTRINSIC_LIST_TO_TUPLE);
|
||||
|
||||
int consts_found = 0;
|
||||
bool expect_append = true;
|
||||
|
||||
for (int pos = i - 1; pos >= 0; pos--) {
|
||||
cfg_instr *instr = &bb->b_instr[pos];
|
||||
int opcode = instr->i_opcode;
|
||||
int oparg = instr->i_oparg;
|
||||
|
||||
if (opcode == NOP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (opcode == BUILD_LIST && oparg == 0) {
|
||||
if (!expect_append) {
|
||||
/* Not a sequence start. */
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Sequence start, we are done. */
|
||||
PyObject *newconst = PyTuple_New((Py_ssize_t)consts_found);
|
||||
if (newconst == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for (int newpos = i - 1; newpos >= pos; newpos--) {
|
||||
instr = &bb->b_instr[newpos];
|
||||
if (instr->i_opcode == NOP) {
|
||||
continue;
|
||||
}
|
||||
if (loads_const(instr->i_opcode)) {
|
||||
PyObject *constant = get_const_value(instr->i_opcode, instr->i_oparg, consts);
|
||||
if (constant == NULL) {
|
||||
Py_DECREF(newconst);
|
||||
return ERROR;
|
||||
}
|
||||
assert(consts_found > 0);
|
||||
PyTuple_SET_ITEM(newconst, --consts_found, constant);
|
||||
}
|
||||
nop_out(&instr, 1);
|
||||
}
|
||||
assert(consts_found == 0);
|
||||
return instr_make_load_const(intrinsic, newconst, consts, const_cache);
|
||||
}
|
||||
|
||||
if (expect_append) {
|
||||
if (opcode != LIST_APPEND || oparg != 1) {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!loads_const(opcode)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
consts_found++;
|
||||
}
|
||||
|
||||
expect_append = !expect_append;
|
||||
}
|
||||
|
||||
/* Did not find sequence start. */
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
#define MIN_CONST_SEQUENCE_SIZE 3
|
||||
/*
|
||||
Optimize lists and sets for:
|
||||
|
@ -2378,9 +2467,13 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
|
|||
RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache));
|
||||
break;
|
||||
case CALL_INTRINSIC_1:
|
||||
// for _ in (*foo, *bar) -> for _ in [*foo, *bar]
|
||||
if (oparg == INTRINSIC_LIST_TO_TUPLE && nextop == GET_ITER) {
|
||||
INSTR_SET_OP0(inst, NOP);
|
||||
if (oparg == INTRINSIC_LIST_TO_TUPLE) {
|
||||
if (nextop == GET_ITER) {
|
||||
INSTR_SET_OP0(inst, NOP);
|
||||
}
|
||||
else {
|
||||
RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache));
|
||||
}
|
||||
}
|
||||
else if (oparg == INTRINSIC_UNARY_POSITIVE) {
|
||||
RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue