Skip to content

Commit 7b3e480

Browse files
committed
address review
1 parent b3a2aeb commit 7b3e480

File tree

1 file changed

+32
-56
lines changed

1 file changed

+32
-56
lines changed

Python/flowgraph.c

+32-56
Original file line numberDiff line numberDiff line change
@@ -1428,31 +1428,42 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const
14281428
}
14291429

14301430
#define MIN_CONST_SEQUENCE_SIZE 3
1431-
/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N
1432-
with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1,
1433-
or BUILD_SET & SET_UPDATE respectively.
1431+
/*
1432+
Optimize literal list/set for:
1433+
1. "for" loop, comprehension or "in"/"not in" tests:
1434+
Change literal list or set of constants into constant
1435+
tuple or frozenset respectively. Change literal list of
1436+
non-constants into tuple.
1437+
2. Constant literal lists/set with length >= MIN_CONST_SEQUENCE_SIZE:
1438+
Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N
1439+
with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1,
1440+
or BUILD_SET & SET_UPDATE respectively.
14341441
*/
14351442
static int
1436-
optimize_if_const_list_or_set(basicblock *bb, int n, PyObject *consts, PyObject *const_cache)
1443+
optimize_list_or_set_literal(basicblock *bb, int i, int nextop,
1444+
PyObject *consts, PyObject *const_cache)
14371445
{
14381446
assert(PyDict_CheckExact(const_cache));
14391447
assert(PyList_CheckExact(consts));
1440-
cfg_instr *instr = &bb->b_instr[n];
1448+
cfg_instr *instr = &bb->b_instr[i];
14411449
assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET);
1450+
bool contains_or_iter_literal = nextop == GET_ITER || nextop == CONTAINS_OP;
14421451
int seq_size = instr->i_oparg;
1443-
if (seq_size < MIN_CONST_SEQUENCE_SIZE) {
1452+
if (seq_size < MIN_CONST_SEQUENCE_SIZE && !contains_or_iter_literal) {
14441453
return SUCCESS;
14451454
}
14461455
PyObject *newconst;
1447-
RETURN_IF_ERROR(get_constant_sequence(bb, n-1, seq_size, consts, &newconst));
1456+
RETURN_IF_ERROR(get_constant_sequence(bb, i-1, seq_size, consts, &newconst));
14481457
if (newconst == NULL) {
14491458
/* not a const sequence */
1459+
if (contains_or_iter_literal && instr->i_opcode == BUILD_LIST) {
1460+
/* convert list iterable to tuple */
1461+
INSTR_SET_OP1(instr, BUILD_TUPLE, instr->i_oparg);
1462+
}
14501463
return SUCCESS;
14511464
}
14521465
assert(PyTuple_CheckExact(newconst) && PyTuple_GET_SIZE(newconst) == seq_size);
1453-
int build = instr->i_opcode;
1454-
int extend = build == BUILD_LIST ? LIST_EXTEND : SET_UPDATE;
1455-
if (build == BUILD_SET) {
1466+
if (instr->i_opcode == BUILD_SET) {
14561467
PyObject *frozenset = PyFrozenSet_New(newconst);
14571468
if (frozenset == NULL) {
14581469
Py_DECREF(newconst);
@@ -1462,11 +1473,16 @@ optimize_if_const_list_or_set(basicblock *bb, int n, PyObject *consts, PyObject
14621473
}
14631474
int index = add_const(newconst, consts, const_cache);
14641475
RETURN_IF_ERROR(index);
1465-
nop_out(bb, n-1, seq_size);
1466-
assert(n >= 2);
1467-
INSTR_SET_OP1(&bb->b_instr[n-2], build, 0);
1468-
INSTR_SET_OP1(&bb->b_instr[n-1], LOAD_CONST, index);
1469-
INSTR_SET_OP1(&bb->b_instr[n], extend, 1);
1476+
nop_out(bb, i-1, seq_size);
1477+
if (contains_or_iter_literal) {
1478+
INSTR_SET_OP1(instr, LOAD_CONST, index);
1479+
}
1480+
else {
1481+
assert(i >= 2);
1482+
INSTR_SET_OP1(&bb->b_instr[i-2], instr->i_opcode, 0);
1483+
INSTR_SET_OP1(&bb->b_instr[i-1], LOAD_CONST, index);
1484+
INSTR_SET_OP1(&bb->b_instr[i], instr->i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE, 1);
1485+
}
14701486
return SUCCESS;
14711487
}
14721488

@@ -1558,41 +1574,6 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca
15581574
return ERROR;
15591575
}
15601576

1561-
static int
1562-
optimize_if_const_list_or_set_iter(basicblock *bb, int n,
1563-
PyObject *consts, PyObject *const_cache)
1564-
{
1565-
cfg_instr *instr = &bb->b_instr[n];
1566-
assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET);
1567-
assert(n + 1 < bb->b_iused);
1568-
cfg_instr *next = &bb->b_instr[n + 1];
1569-
assert(next->i_opcode == GET_ITER || next->i_opcode == CONTAINS_OP);
1570-
int seq_size = instr->i_oparg;
1571-
PyObject *newconst;
1572-
RETURN_IF_ERROR(get_constant_sequence(bb, n-1, seq_size, consts, &newconst));
1573-
if (newconst == NULL) {
1574-
/* not a const sequence */
1575-
if (instr->i_opcode == BUILD_LIST) {
1576-
/* even if not const list, it is still changed to build tuple */
1577-
INSTR_SET_OP1(instr, BUILD_TUPLE, instr->i_oparg);
1578-
}
1579-
return SUCCESS;
1580-
}
1581-
if (instr->i_opcode == BUILD_SET) {
1582-
PyObject *frozenset = PyFrozenSet_New(newconst);
1583-
if (frozenset == NULL) {
1584-
Py_DECREF(newconst);
1585-
return ERROR;
1586-
}
1587-
Py_SETREF(newconst, frozenset);
1588-
}
1589-
int index = add_const(newconst, consts, const_cache);
1590-
RETURN_IF_ERROR(index);
1591-
nop_out(bb, n-1, seq_size);
1592-
INSTR_SET_OP1(instr, LOAD_CONST, index);
1593-
return SUCCESS;
1594-
}
1595-
15961577
#define VISITED (-1)
15971578

15981579
// Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the
@@ -1958,12 +1939,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
19581939
break;
19591940
case BUILD_LIST:
19601941
case BUILD_SET:
1961-
if (nextop == GET_ITER || nextop == CONTAINS_OP) {
1962-
RETURN_IF_ERROR(optimize_if_const_list_or_set_iter(bb, i, consts, const_cache));
1963-
}
1964-
else {
1965-
RETURN_IF_ERROR(optimize_if_const_list_or_set(bb, i, consts, const_cache));
1966-
}
1942+
RETURN_IF_ERROR(optimize_list_or_set_literal(bb, i, nextop, consts, const_cache));
19671943
break;
19681944
case POP_JUMP_IF_NOT_NONE:
19691945
case POP_JUMP_IF_NONE:

0 commit comments

Comments
 (0)