Repository navigation
gh-148817: Fold long lists/sets of constant elements into constant tuples/frozensets #149016
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
ddd3875
3510ec1
0c2f097
79d68e0
737095e
fa30806
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1515,20 +1515,18 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, | |
| ... | ||
| LOAD_CONST cN | ||
| LIST_APPEND/SET_ADD 1 | ||
| [CALL_INTRINSIC_1 INTRINSIC_LIST_TO_TUPLE] <-- when expected_append is true | ||
| [CALL_INTRINSIC_1 INTRINSIC_LIST_TO_TUPLE] <-- optional | ||
| with: | ||
| LOAD_CONST (c1, c2, ... cN) | ||
| When expected_append is true, the instruction at `i` is the LIST_TO_TUPLE | ||
| intrinsic (so the immediately preceding non-NOP instruction is expected | ||
| to be a LIST_APPEND), and only the BUILD_LIST/LIST_APPEND form is | ||
| considered. When expected_append is false, the instruction at `i` is the | ||
| trailing LIST_APPEND or SET_ADD itself, the matching BUILD_LIST/BUILD_SET | ||
| start is selected from its opcode, and for sets the result is wrapped in | ||
| a frozenset. | ||
| The instruction at `i` is either the LIST_TO_TUPLE intrinsic (so the | ||
| immediately preceding non-NOP instruction is expected to be a | ||
| LIST_APPEND, and only the BUILD_LIST/LIST_APPEND form is considered), | ||
| or the trailing LIST_APPEND or SET_ADD itself, in which case the | ||
| matching BUILD_LIST/BUILD_SET start is selected from its opcode, and | ||
| for sets the result is wrapped in a frozenset. | ||
| */ | ||
| static int | ||
| fold_constant_seq_into_load_const(basicblock *bb, int i, | ||
| bool expected_append, | ||
| PyObject *consts, PyObject *const_cache, | ||
| _Py_hashtable_t *consts_index) | ||
| { | ||
|
|
@@ -1538,6 +1536,10 @@ fold_constant_seq_into_load_const(basicblock *bb, int i, | |
| assert(i < bb->b_iused); | ||
|
|
||
| cfg_instr *target = &bb->b_instr[i]; | ||
| assert(target->i_opcode == LIST_APPEND || target->i_opcode == SET_ADD || | ||
| (target->i_opcode == CALL_INTRINSIC_1 && | ||
| target->i_oparg == INTRINSIC_LIST_TO_TUPLE)); | ||
| bool expected_append = target->i_opcode == CALL_INTRINSIC_1; | ||
| int append_op = expected_append ? LIST_APPEND : target->i_opcode; | ||
| assert(append_op == LIST_APPEND || append_op == SET_ADD); | ||
| int build_op = append_op == LIST_APPEND ? BUILD_LIST : BUILD_SET; | ||
|
|
@@ -1618,17 +1620,6 @@ fold_constant_seq_into_load_const(basicblock *bb, int i, | |
| return SUCCESS; | ||
| } | ||
|
|
||
| static int | ||
| fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i, | ||
| PyObject *consts, PyObject *const_cache, | ||
| _Py_hashtable_t *consts_index) | ||
| { | ||
| assert(bb->b_instr[i].i_opcode == CALL_INTRINSIC_1); | ||
| assert(bb->b_instr[i].i_oparg == INTRINSIC_LIST_TO_TUPLE); | ||
| return fold_constant_seq_into_load_const(bb, i, true, | ||
| consts, const_cache, consts_index); | ||
| } | ||
|
|
||
| #define MIN_CONST_SEQUENCE_SIZE 3 | ||
| /* | ||
| Optimize lists and sets for: | ||
|
|
@@ -2543,7 +2534,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts, | |
| INSTR_SET_OP0(inst, NOP); | ||
| } | ||
| else { | ||
| RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache, consts_index)); | ||
| RETURN_IF_ERROR(fold_constant_seq_into_load_const(bb, i, consts, const_cache, consts_index)); | ||
| } | ||
| } | ||
| else if (oparg == INTRINSIC_UNARY_POSITIVE) { | ||
|
|
@@ -2554,8 +2545,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts, | |
| case SET_ADD: | ||
| if (oparg == 1 && (nextop == GET_ITER || nextop == CONTAINS_OP)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there may be other cases where the optimisation can be applied:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll do that in follow-up, but from a quick look it seems to be true |
||
| RETURN_IF_ERROR(fold_constant_seq_into_load_const( | ||
| bb, i, false, | ||
| consts, const_cache, consts_index)); | ||
| bb, i, consts, const_cache, consts_index)); | ||
| } | ||
| break; | ||
| case BINARY_OP: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.