Skip to content

Commit 17dffaa

Browse files
committed
for target optimization (set/list -> frozenset/tuple)
1 parent 2b39a13 commit 17dffaa

File tree

3 files changed

+17
-126
lines changed

3 files changed

+17
-126
lines changed

Lib/test/test_ast/test_ast.py

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3223,44 +3223,6 @@ def test_folding_format(self):
32233223

32243224
self.assert_ast(code, non_optimized_target, optimized_target)
32253225

3226-
def test_folding_comparator(self):
3227-
code = "1 %s %s1%s"
3228-
operators = [("in", ast.In()), ("not in", ast.NotIn())]
3229-
braces = [
3230-
("[", "]", ast.List, (1,)),
3231-
]
3232-
for left, right, non_optimized_comparator, optimized_comparator in braces:
3233-
for op, node in operators:
3234-
non_optimized_target = self.wrap_expr(ast.Compare(
3235-
left=ast.Constant(1), ops=[node],
3236-
comparators=[non_optimized_comparator(elts=[ast.Constant(1)])]
3237-
))
3238-
optimized_target = self.wrap_expr(ast.Compare(
3239-
left=ast.Constant(1), ops=[node],
3240-
comparators=[ast.Constant(value=optimized_comparator)]
3241-
))
3242-
self.assert_ast(code % (op, left, right), non_optimized_target, optimized_target)
3243-
3244-
def test_folding_iter(self):
3245-
code = "for _ in %s1%s: pass"
3246-
braces = [
3247-
("[", "]", ast.List, (1,)),
3248-
]
3249-
3250-
for left, right, ast_cls, optimized_iter in braces:
3251-
non_optimized_target = self.wrap_statement(ast.For(
3252-
target=ast.Name(id="_", ctx=ast.Store()),
3253-
iter=ast_cls(elts=[ast.Constant(1)]),
3254-
body=[ast.Pass()]
3255-
))
3256-
optimized_target = self.wrap_statement(ast.For(
3257-
target=ast.Name(id="_", ctx=ast.Store()),
3258-
iter=ast.Constant(value=optimized_iter),
3259-
body=[ast.Pass()]
3260-
))
3261-
3262-
self.assert_ast(code % (left, right), non_optimized_target, optimized_target)
3263-
32643226
def test_folding_subscript(self):
32653227
code = "'abcd'[0]"
32663228

Python/ast_opt.c

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -532,29 +532,6 @@ fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
532532
return make_const(node, newval, arena);
533533
}
534534

535-
static PyObject*
536-
make_const_tuple(asdl_expr_seq *elts)
537-
{
538-
for (Py_ssize_t i = 0; i < asdl_seq_LEN(elts); i++) {
539-
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
540-
if (e->kind != Constant_kind) {
541-
return NULL;
542-
}
543-
}
544-
545-
PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
546-
if (newval == NULL) {
547-
return NULL;
548-
}
549-
550-
for (Py_ssize_t i = 0; i < asdl_seq_LEN(elts); i++) {
551-
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
552-
PyObject *v = e->v.Constant.value;
553-
PyTuple_SET_ITEM(newval, i, Py_NewRef(v));
554-
}
555-
return newval;
556-
}
557-
558535
static int
559536
fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
560537
{
@@ -574,54 +551,6 @@ fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
574551
return make_const(node, newval, arena);
575552
}
576553

577-
/* Change literal list or set of constants into constant
578-
tuple. Change literal list of non-constants into tuple.
579-
Used for right operand of "in" and "not in" tests and for iterable
580-
in "for" loop and comprehensions.
581-
*/
582-
static int
583-
fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
584-
{
585-
PyObject *newval;
586-
if (arg->kind == List_kind) {
587-
/* First change a list into tuple. */
588-
asdl_expr_seq *elts = arg->v.List.elts;
589-
if (has_starred(elts)) {
590-
return 1;
591-
}
592-
expr_context_ty ctx = arg->v.List.ctx;
593-
arg->kind = Tuple_kind;
594-
arg->v.Tuple.elts = elts;
595-
arg->v.Tuple.ctx = ctx;
596-
/* Try to create a constant tuple. */
597-
newval = make_const_tuple(elts);
598-
}
599-
else {
600-
return 1;
601-
}
602-
return make_const(arg, newval, arena);
603-
}
604-
605-
static int
606-
fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
607-
{
608-
asdl_int_seq *ops;
609-
asdl_expr_seq *args;
610-
Py_ssize_t i;
611-
612-
ops = node->v.Compare.ops;
613-
args = node->v.Compare.comparators;
614-
/* Change literal list or set in 'in' or 'not in' into tuple. */
615-
i = asdl_seq_LEN(ops) - 1;
616-
int op = asdl_seq_GET(ops, i);
617-
if (op == In || op == NotIn) {
618-
if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
619-
return 0;
620-
}
621-
}
622-
return 1;
623-
}
624-
625554
static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
626555
static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
627556
static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
@@ -782,7 +711,6 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
782711
case Compare_kind:
783712
CALL(astfold_expr, expr_ty, node_->v.Compare.left);
784713
CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
785-
CALL(fold_compare, expr_ty, node_);
786714
break;
787715
case Call_kind:
788716
CALL(astfold_expr, expr_ty, node_->v.Call.func);
@@ -852,7 +780,6 @@ astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState
852780
CALL(astfold_expr, expr_ty, node_->iter);
853781
CALL_SEQ(astfold_expr, expr, node_->ifs);
854782

855-
CALL(fold_iter, expr_ty, node_->iter);
856783
return 1;
857784
}
858785

@@ -939,8 +866,6 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
939866
CALL(astfold_expr, expr_ty, node_->v.For.iter);
940867
CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
941868
CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
942-
943-
CALL(fold_iter, expr_ty, node_->v.For.iter);
944869
break;
945870
case AsyncFor_kind:
946871
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);

Python/flowgraph.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,21 +1395,24 @@ fold_tuple_on_constants(PyObject *const_cache,
13951395
}
13961396

13971397

1398-
// Replaces const set with a frozenset.
1399-
// This should be used only in situations where we 100% sure that
1400-
// this set cannot be changed: where's constant set is a rhs in `for` loop
1401-
// or it's a rhs in `in` operation.
1398+
/* Replaces const set/list with a frozenset/tuple.
1399+
This should be used only in situations where we 100% sure that
1400+
this set cannot be changed: where's constant set/list is a rhs in `for` loop
1401+
or it's a rhs in `in` operation.
1402+
*/
14021403
static int
1403-
fold_set_on_constants(PyObject *const_cache,
1404+
fold_if_const_list_or_set(PyObject *const_cache,
14041405
cfg_instr *inst,
14051406
int n, PyObject *consts)
14061407
{
14071408
/* Pre-conditions */
14081409
assert(PyDict_CheckExact(const_cache));
14091410
assert(PyList_CheckExact(consts));
1410-
assert(inst[n].i_opcode == BUILD_SET);
14111411
assert(inst[n].i_oparg == n);
14121412

1413+
int build = inst[n].i_opcode;
1414+
assert(build == BUILD_LIST || build == BUILD_SET);
1415+
14131416
if (!is_constant_sequence(inst, n)) {
14141417
return SUCCESS;
14151418
}
@@ -1428,13 +1431,13 @@ fold_set_on_constants(PyObject *const_cache,
14281431
}
14291432
PyTuple_SET_ITEM(newconst, i, constant);
14301433
}
1431-
1432-
PyObject *frozenset = PyFrozenSet_New(newconst);
1433-
if (frozenset == NULL) {
1434-
return ERROR;
1434+
if (build == BUILD_SET) {
1435+
PyObject *frozenset = PyFrozenSet_New(newconst);
1436+
if (frozenset == NULL) {
1437+
return ERROR;
1438+
}
1439+
Py_SETREF(newconst, frozenset);
14351440
}
1436-
Py_SETREF(newconst, frozenset);
1437-
14381441
int index = add_const(newconst, consts, const_cache);
14391442
if (index < 0) {
14401443
return ERROR;
@@ -1866,9 +1869,10 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
18661869
case BUILD_LIST:
18671870
case BUILD_SET:
18681871
if (nextop == CONTAINS_OP || nextop == GET_ITER) {
1869-
if (fold_set_on_constants(const_cache, inst-oparg, oparg, consts) < 0) {
1872+
if (fold_if_const_list_or_set(const_cache, inst-oparg, oparg, consts) < 0) {
18701873
goto error;
18711874
}
1875+
break;
18721876
}
18731877
if (i >= oparg) {
18741878
if (optimize_if_const_list_or_set(const_cache, inst-oparg, oparg, consts) < 0) {

0 commit comments

Comments
 (0)