-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-126835: Avoid creating unnecessary tuple when looking for constant sequence during constant folding #131054
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
Conversation
@iritkatriel what would be the good way to test this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good change. Some naming issues.
return SUCCESS; | ||
|
||
nop_out(bb, seq, BINOP_OPERAND_COUNT); | ||
return instr_make_load_const(binop, newconst, consts, const_cache); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might make sense for instr_make_load_const
to do the nop_out. It already changes the bytecode with INSTR_SET_OP1, so it makes sense for it to do the whole transformation.
It would need an arg for BINOP_OPERAND_COUNT
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't do it. Functions do precisely what their names suggest. What if we would need to use instr_make_load_const
in future without noping out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we can pass 0 for the "how many to NOP out" arg. We can also, if we want, add assertions in this function that the net change to stack effect of what we're doing is 0.
If you replace BUILD_TUPLE 5
by a LOAD_CONST
without the NOPing, then you end up with invalid code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. My only concern is that function would be doing too much, and it's kind of hard to find a proper name for it to reflect everything it is doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is usage of nop_out
without instr_make_load_const
so I would probably leave this for another PR as it would require a bit of adjusting some unrelated (to this PR) code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only concern is that function would be doing too much, and it's kind of hard to find a proper name for it to reflect everything it is doing.
The current name of the function doesn't reflect what it does (and that it can leave the bytecode in bad state).
There is usage of nop_out without instr_make_load_const so I would probably leave this for another PR as it would require a bit of adjusting some unrelated (to this PR) code.
You can just leave that usage as is. It won't be impacted by moving the nop_out
in other places into instr_make_load_const
.
Could also be in another PR.
The existing functional tests should cover this because this PR changes only implementation details and not behaviour. Might be worth making sure that we have tests for this on the boundaries of the relevant constants ( |
Additionally, I would like to assert that we are not missing optimization by returning early if |
Actually, we already have such section in Lines 386 to 405 in 98fa4a4
So maybe just put it there? |
I think it's possible to have a long sequence of LOAD_CONSTS which are not later turned into a tuple, so this check is too harsh.
|
Then maybe assert constant sequence is within static bool
const_folding_within_stack_use_guideline(basicblock *bb, int i)
{
assert(i < bb->b_iused);
int count = 0;
for (; i >= 0; i--) {
int opcode = bb->b_instr[i].i_opcode;
if (opcode == NOP) {
continue;
}
if (!loads_const(opcode)) {
break;
}
count++;
}
return count <= _PY_STACK_USE_GUIDELINE;
} static int
fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const_cache)
{
/* Pre-conditions */
assert(PyDict_CheckExact(const_cache));
assert(PyList_CheckExact(consts));
assert(const_folding_within_stack_use_guideline(bb, i-1));
... |
I don't see what you're testing here that we're not covering with the normal tests. |
I merged, so we won't get more conflicts. We can always add more tests later. |
Alright. My point being that since we return early with |
…nstant sequence during constant folding (python#131054)
…nstant sequence during constant folding (python#131054)
Context: #126835 (comment)