Skip to content

GH-135904: Add tests for the JIT build process #136766

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Jul 18, 2025

This is overdue, but it's especially valuable now that we're doing more subtle transformations on the machine code at JIT build time. This has a number of benefits:

  • When we add a new optimization at this level, we can directly see the impact on example code in the PR diff. And if it doesn't show up, we can add a test for it.
  • It gives us visibility into the quality of the generated code (without having the full stencils checked in yet). For example, making this PR helped me realize that there are three obvious quality issues on platforms I don't look at much:
    • On some platforms, system headers were putting unused writable data in our read-only data stencils. This is both wrong and wasteful. I fixed this issue as part of this PR (we just optimistically remove this data, and raise if it's actually used).
    • The JIT still inserts frame pointer pushes/pops on Intel-based Macs. I'll fix this in a follow-up PR.
    • LLVM has a bug that inserts unnecessary spills and reloads of C local variables on 32-bit Windows at the beginning and end of every stencil. I've filed an issue upstream: musttail doesn't optimize sibling calls llvm/llvm-project#147813

The new test is in Lib/test/test_jit_stencils.py. This test uses Tools/jit/test/test_executor_cases.c.h to generate a few small test stencils, and compares them to the expected output in the corresponding Tools/jit/test/test_jit_stencils-*.h file.

Most of the changes in Tools/jit/_targets.py are just cleanup to make the generated stencils simpler and more consistent, or to fix the writable-data bug I mentioned above.

@brandtbucher brandtbucher self-assigned this Jul 18, 2025
@brandtbucher brandtbucher added the tests Tests in the Lib/test dir label Jul 18, 2025
@brandtbucher brandtbucher requested a review from diegorusso as a code owner July 18, 2025 19:51
@brandtbucher brandtbucher added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jul 18, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @brandtbucher for commit 867a686 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F136766%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jul 18, 2025
@brandtbucher
Copy link
Member Author

!buildbot aarch64 RHEL8 LTO

@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @brandtbucher for commit 7c9c3ff 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F136766%2Fmerge

The command will test the builders whose names match following regular expression: aarch64 RHEL8 LTO

The builders matched are:

  • aarch64 RHEL8 LTO PR
  • aarch64 RHEL8 LTO + PGO PR

@tomasr8 tomasr8 self-requested a review July 21, 2025 19:56
class TestJITStencils(unittest.TestCase):

def _build_jit_stencils(self, target: str) -> str:
with tempfile.TemporaryDirectory() as work:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think os_helper.temp_dir is a bit more common in tests but either is fine :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'll take a look!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it, like, better? Haha.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't tell you 😅 but it seems quite common. Though both are used so it probably doesn't matter :)

parser.add_argument(
"-i",
"--input-file",
help="where to find the generated executor cases",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's worth calling out that this is used to pass in the dummy file in our tests and/or that this could be useful for custom builds/debugging? Maybe not in help text but in a comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I left a similar comment at the top of the PR. Is this the case of regenerating the file while in development so then be able to pass it?

Copy link
Contributor

@diegorusso diegorusso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not fully related to this PR but sometime I change this line https://github.com/python/cpython/pull/136766/files#diff-700c6057d24addce74e8787edb5f5556f718299f6ef1742cbb1d79580cdb535cR199 and add delete=False because I want to inspect the temporary files that have been generated.
Do you think that we should expose this to the user (it would be useful for me)?

pyconfig_h = pathlib.Path(sysconfig.get_config_h_filename()).resolve()
result, args = test.support.script_helper.run_python_until_end(
_TOOLS_JIT_BUILD_PY,
"--input-file", _TOOLS_JIT_TEST_TEST_EXECUTOR_CASES_C_H,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just for my understanding. is this needed in case we need to regenerate this during development and we need to test it, right?

HoleValue.JUMP_TARGET: "state->instruction_starts[instruction->jump_target]",
HoleValue.ERROR_TARGET: "state->instruction_starts[instruction->error_target]",
# These should all have raised an error if they were actually used:
# HoleValue.WRITABLE: "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I fully understand this. Can you expland please?

parser.add_argument(
"-i",
"--input-file",
help="where to find the generated executor cases",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I left a similar comment at the top of the PR. Is this the case of regenerating the file while in development so then be able to pass it?

@diegorusso
Copy link
Contributor

Most of the changes in Tools/jit/_targets.py are just cleanup to make the generated stencils simpler and more consistent, or to fix the writable-data bug I mentioned above.

It's not a hard push back, but shouldn't be these changes go to a separate PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants