gh-119352 Add UOp Pair Compatibility to PyStats#119354
gh-119352 Add UOp Pair Compatibility to PyStats#119354JeffersGlass wants to merge 33 commits intopython:mainfrom
Conversation
gvanrossum
left a comment
There was a problem hiding this comment.
I started reviewing this but realized I don't know the summarize_stats.py script well enough to review that -- I think it's probably up to @mdboom to review that.
The cases_generator changes and the new generated output LGTM.
Co-authored-by: Guido van Rossum <gvanrossum@gmail.com>
…lass/cpython into supernodes-input-compat
mdboom
left a comment
There was a problem hiding this comment.
This looks great, and thanks for working on this. Just some stylistic changes mostly. The example table in the PR was helpful to understand how this looks -- it's going to be super helpful.
| line = line[len(start) :] | ||
| name, val = line.split() | ||
| defines[int(val.strip())].append(name.strip()) | ||
| defines[int(val.strip().strip("()"))].append(name.strip()) |
There was a problem hiding this comment.
| defines[int(val.strip().strip("()"))].append(name.strip()) | |
| defines[int(val.strip().removesuffix("()"))].append(name.strip()) |
This is probably safer, unless there is a need to remove things like (()) that I'm missing.
There was a problem hiding this comment.
The defines for the flags look like #define HAS_PASSTHROUGH_FLAG (4096) - this line is to strip the parens around the number. We could do resmovesuffix(")") and removeprefix("(")?
Could also do the whole thing with a regex if that's preferable, but it would be a little unweildy.
There was a problem hiding this comment.
I see. I misunderstood what this needed to do. I think this is fine.
| flag_names: tuple[str] = None, | ||
| filepath: str | Path = "Include/internal/pycore_uop_metadata.h", | ||
| ) -> dict[str, list[str]]: | ||
| flags = {} |
There was a problem hiding this comment.
Overall, I found this function a bit hard to follow (but then again, parsing C with regexes is always that way). It might be helpful to have a header comment with an example of the pattern it's looking for and what the output would look like for it.
There was a problem hiding this comment.
Agreed, I've added a comment to clarify. In general, I wonder if having something like opcode_metadata_generator.py for the UOp metadata, and spitting out that metadata as Python originally, would be more robust than parsing the C headers, but that might be a significant chunk of work.
There was a problem hiding this comment.
I like that idea, but can/should be a follow-on to this PR. I think parts of this predate having the generator -- it would be a lot cleaner to generate some JSON or something that would be easily parseable.
|
Thanks for all the comments @mdboom! I’m taking a few days of post-conference R&R with my wife, but I will return to this PR presently and get it into shape. |
|
@JeffersGlass: No worries. I fully support post-conference R&R! |
Co-authored-by: Michael Droettboom <mdboom@gmail.com>
Co-authored-by: Michael Droettboom <mdboom@gmail.com>
…lass/cpython into supernodes-input-compat
|
Does this want a NEWS.d entry? No worries either way, just wasn't sure whether Pystats updates in general (or this in particular) merits one. |
| line = line[len(start) :] | ||
| name, val = line.split() | ||
| defines[int(val.strip())].append(name.strip()) | ||
| defines[int(val.strip().strip("()"))].append(name.strip()) |
There was a problem hiding this comment.
I see. I misunderstood what this needed to do. I think this is fine.
|
One minor request. |
|
I think the ideal conflict calculation for The union {
uint32_t target;
struct {
union {
uint16_t exit_index;
uint16_t jump_target;
};
uint16_t error_target;
};
};
So I think it would be more like the following: targets = names.count("_DEOPT")
exit_indexes = names.count("_EXIT_TRACE")
jump_targets = combined_flags.count("HAS_DEOPT_FLAG") + combined_flags.count("HAS_EXIT_FLAG")
error_targets = combined_flags.count("HAS_ERROR_FLAG") + combined_flags.count("HAS_ERROR_NO_POP_FLAG")
valid = (
# UOP_FORMAT_TARGET:
(targets <= 1 and exit_indexes == 0 and jump_targets == 0 and error_targets == 0) or
# UOP_FORMAT_EXIT:
(targets == 0 and exit_indexes <= 1 and jump_targets == 0 and error_targets <= 1) or
# UOP_FORMAT_JUMP:
(targets == 0 and exit_indexes == 0 and jump_targets <= 1 and error_targets <= 1)
) |
|
Thanks @brandtbucher, I've updated the logic for detecting conflicting uses of of target. Additionally - I had been detecting the use of an oparg based on solely On a pyperformance pystats run, none of the top 5000 pairs show a conflict for Here's a sample from the middle of those results:
|
|
Update: I do think the lack of target conflicts is a bug... I am troubleshooting/adding tests. |
|
Indeed, I had an error in how I was combining the flags of two uops. Now corrected, the output looks something like this:
|
I believe |
Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
It does look like both of those things are true - I've adjusted the conflict-checking code to only account for |
|
Give that we're no longer pursuing superinstructions as a high-priority optimization, this is no longer going to be particularly helpful. I'll close this, though it could be revived if it turns out to be useful later. |
This PR adds functionality to
PyStats-enabled builds, specifically to the UOp pair-count section emitted when the interpreter is build with the Tier 2 Interpreter. It adds another column to the pair-count table, indicating whether the two instructions have overlapping uses ofoparg,operand, andtarget. This makes it easy to tell which pairs can be immediately adapted to become superinstructions, and which would require a modified instruction format.See below for an example of this output - the
Compatibilitycolumn in the far right is the added column.Closes #119352