GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-126835: Avoid creating unnecessary tuple when looking for constant sequence during constant folding by WolframAlph · Pull Request #131054 · python/cpython

Conversation

@WolframAlph

@WolframAlph WolframAlph commented Mar 10, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor
  • Issue: Move const folding to the peephole optimizer #126835

Context: #126835 (comment)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
WolframAlph added 2 commits March 10, 2025 21:02
@WolframAlph
move STACK_USE_GUIDELINNE to pycore_compile.h
5186de3
@WolframAlph
avoid creating unnecessary tuple when looking for constant sequence
f42824e
@WolframAlph
WolframAlph requested review from iritkatriel and markshannon as code owners March 10, 2025 20:05
@bedevere-app bedevere-app Bot added the awaiting review label Mar 10, 2025
@bedevere-app bedevere-app Bot mentioned this pull request Mar 10, 2025
Move const folding to the peephole optimizer #126835
Open
@WolframAlph

WolframAlph commented Mar 10, 2025

Copy link
Copy Markdown
Contributor Author

@iritkatriel what would be the good way to test this?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@WolframAlph
rename get_const_sequence_instructions
64eb38d
iritkatriel
iritkatriel reviewed Mar 11, 2025
View reviewed changes

@iritkatriel iritkatriel left a comment

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Include/internal/pycore_compile.h Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c
return SUCCESS;

nop_out(bb, seq, BINOP_OPERAND_COUNT);
return instr_make_load_const(binop, newconst, consts, const_cache);

@iritkatriel iritkatriel Mar 11, 2025

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@WolframAlph WolframAlph Mar 11, 2025

Copy link
Copy Markdown
Contributor Author

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?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Mar 11, 2025

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@WolframAlph WolframAlph Mar 11, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@WolframAlph WolframAlph Mar 11, 2025

Copy link
Copy Markdown
Contributor Author

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Mar 11, 2025

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
WolframAlph added 2 commits March 11, 2025 15:28
@WolframAlph
address review
212dacc
@WolframAlph
some adjustments
bfa67f5
iritkatriel
iritkatriel reviewed Mar 11, 2025
View reviewed changes
Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

iritkatriel
iritkatriel reviewed Mar 11, 2025
View reviewed changes
Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@iritkatriel iritkatriel added the skip news label Mar 11, 2025
@WolframAlph
address review
9d3297e
iritkatriel
iritkatriel reviewed Mar 11, 2025
View reviewed changes
Comment thread Python/flowgraph.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@iritkatriel

iritkatriel commented Mar 11, 2025

Copy link
Copy Markdown
Member

@iritkatriel what would be the good way to test this?

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 (_PY_STACK_USE_GUIDELINE and MIN_CONST_SEQUENCE_SIZE, so each of these and +-1).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@WolframAlph

WolframAlph commented Mar 12, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

MIN_CONST_SEQUENCE_SIZE is covered by test_optimize_if_const_set & test_optimize_if_const_list in test_peepholer.py.

_PY_STACK_USE_GUIDELINE is not covered anywhere AFAIK. I will add test in test_compiler_codegen.py for _PY_STACK_USE_GUIDELINE boundary.

Additionally, I would like to assert that we are not missing optimization by returning early if seq_size > _PY_STACK_USE_GUIDELINE. Basically small function counting how many consecutive constants there are and return count > _PY_STACK_USE_GUIDELINE. It would be stripped out on non debug builds however, so we would need to #ifdef it (or some other way (macro?)). WDYT?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@WolframAlph

WolframAlph commented Mar 12, 2025

Copy link
Copy Markdown
Contributor Author

It would be stripped out on non debug builds however, so we would need to #ifdef it

Actually, we already have such section in flowgraph.c:

cpython/Python/flowgraph.c

Lines 386 to 405 in 98fa4a4

#ifndef NDEBUG
static bool
cfg_builder_check(cfg_builder *g)
{
assert(g->g_entryblock->b_iused > 0);
for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) {
assert(!_PyMem_IsPtrFreed(block));
if (block->b_instr != NULL) {
assert(block->b_ialloc > 0);
assert(block->b_iused >= 0);
assert(block->b_ialloc >= block->b_iused);
}
else {
assert (block->b_iused == 0);
assert (block->b_ialloc == 0);
}
}
return true;
}
#endif

So maybe just put it there?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@iritkatriel

iritkatriel commented Mar 12, 2025

Copy link
Copy Markdown
Member

Basically small function counting how many consecutive constants there are and return count > _PY_STACK_USE_GUIDELINE.

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.

>>> def f():
...     g(1,2,3,4,5,6,7,8,9,10)
...     
>>> dis.dis(f)
  1           RESUME                   0

  2           LOAD_GLOBAL              1 (g + NULL)
              LOAD_SMALL_INT           1
              LOAD_SMALL_INT           2
              LOAD_SMALL_INT           3
              LOAD_SMALL_INT           4
              LOAD_SMALL_INT           5
              LOAD_SMALL_INT           6
              LOAD_SMALL_INT           7
              LOAD_SMALL_INT           8
              LOAD_SMALL_INT           9
              LOAD_SMALL_INT          10
              CALL                    10
              POP_TOP
              LOAD_CONST               0 (None)
              RETURN_VALUE

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@WolframAlph

WolframAlph commented Mar 12, 2025

Copy link
Copy Markdown
Contributor Author

Then maybe assert constant sequence is within _PY_STACK_USE_GUIDELINE upon entering fold_tuple_of_constants & optimize_lists_and_sets?

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));
    ...
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@iritkatriel

iritkatriel commented Mar 12, 2025

Copy link
Copy Markdown
Member

I don't see what you're testing here that we're not covering with the normal tests.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@iritkatriel
Merge branch 'main' into redesign-const-seq
302cf3e
iritkatriel
iritkatriel approved these changes Mar 12, 2025
View reviewed changes
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting review labels Mar 12, 2025
@iritkatriel
iritkatriel merged commit 3618240 into python:main Mar 12, 2025
@bedevere-app bedevere-app Bot removed the awaiting merge label Mar 12, 2025
@iritkatriel

iritkatriel commented Mar 12, 2025

Copy link
Copy Markdown
Member

I merged, so we won't get more conflicts. We can always add more tests later.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@WolframAlph

WolframAlph commented Mar 13, 2025

Copy link
Copy Markdown
Contributor Author

Alright. My point being that since we return early with if (seq_size > _PY_STACK_USE_GUIDELINE), maybe it's worth adding assertion to check that we are not missing optimization due to this. In case for some reason in future, codegen emits more consecutive constant stack loads then _PY_STACK_USE_GUIDELINE. But maybe I'm wrong and we don't need it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

plashchynski pushed a commit to plashchynski/cpython that referenced this pull request Mar 17, 2025
@WolframAlph @plashchynski
pythongh-126835: Avoid creating unnecessary tuple when looking for co…
f88766c
…nstant sequence during constant folding (python#131054)
@gouzil gouzil mentioned this pull request Nov 18, 2025
[SOT][3.14] fix func_closure lose、fix CALL_FUNCTION_EX kwargs_variable is NullVariable、add MF.MF_HAS_ANNOTATE、add LOAD_COMMON_CONSTANT opcode PaddlePaddle/Paddle#76451
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@iritkatriel iritkatriel iritkatriel approved these changes
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

skip news

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@WolframAlph @iritkatriel
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.