Skip to content
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

gh-118423: Add INSTRUCTION_SIZE macro to code generator #125467

Merged
merged 34 commits into from
Oct 29, 2024

Conversation

tomasr8
Copy link
Member

@tomasr8 tomasr8 commented Oct 14, 2024

I am not that familiar with the tier 1 interpreter (yet 😄 ) so I'd appreciate if someone could double check that for all
the places that use the new INSTRUCTION_SIZE macro, it is actually safe to do so.

I replaced all examples of next_instr - this_instr. There are still a few examples of 1 + INLINE_CACHE_ENTRIES_... but I wasn't sure whether those were safe to change as well.

I named the new macro INSTRUCTION_SIZE, but I'm happy to change it to INSTRUCTION_LENGTH if you prefer.

Feedback welcome :)

@tomasr8
Copy link
Member Author

tomasr8 commented Oct 14, 2024

cc @iritkatriel since you asked for this in #118380 (comment) :)

Copy link
Member

@Fidget-Spinner Fidget-Spinner 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 really close to what I was thinking of. Great work!

inst: Instruction | None
) -> bool:
"""Replace the INSTRUCTION_SIZE macro with the size of the current instruction."""
size = inst.size if inst else 1 + uop.size
Copy link
Member Author

Choose a reason for hiding this comment

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

tier2 does not have access to the instruction here so I calculate the size as 1 + uop.size. Does that make sense?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry this seems wrong, you need to emit the 1 + inline cache size not uop size

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed, I see when comparing the output of generated_cases.c.h with executor_cases.c.h that the latter has the wrong instruction size. I fixed it (I think) by looking up the instructions for each uop in tier2 and passing it to the emitter.
Let me know if it's correct like that :)

Copy link
Member

Choose a reason for hiding this comment

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

INSTRUCTION_SIZE is the size of the tier 1 instruction. This must be true even in tier 2.

I fixed it (I think) by looking up the instructions for each uop in tier2 and passing it to the emitter.

That is correct, but it would be nice if we also checked that all matching tier 1 instructions are the same size.

@tomasr8
Copy link
Member Author

tomasr8 commented Oct 16, 2024

It looks like there are not tests for tier2 yet so I only added tests for tier1

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

Thanks for doing this.

The general approach looks good, but I think we need to check that all the instructions containing the uop with INSTRUCTION_LENGTH are the same length.

}
"""
self.run_cases_test(input, output)

Copy link
Member

Choose a reason for hiding this comment

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

Add a test for another instruction that is a different length, but uses OP:

macro(OP2) = unused/1 + OP;

Copy link
Member Author

Choose a reason for hiding this comment

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

Added!

Copy link
Member

Choose a reason for hiding this comment

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

That test should fail, as the INSTRUCTION_SIZE is inconsistent.
The tier 2 INSTRUCTION_SIZE cannot be both 1 and 2.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, sorry I mistakenly thought it should only fail for tier 2 hence I was only checking the instruction in the tier 2 generator. I extended the check to tier 1 as well and the test now fails as expected.

Tools/cases_generator/generators_common.py Outdated Show resolved Hide resolved
@@ -167,7 +167,7 @@ def oparg(
return True


def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack:
def write_uop(uop: Uop, emitter: Emitter, stack: Stack, inst: Instruction | None) -> Stack:
Copy link
Member

Choose a reason for hiding this comment

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

Maybe pass the size, not the instruction. A uop can occur in many instructions, so picking one is arbitrary.
However, if it uses INSTRUCTION_SIZE, than all instructions must be the same size.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added the check for the instruction size, which actually pointed out one place where we cannot use INSTRUCTION_SIZE instead of next_instr - this_instr:

frame->return_offset = (uint16_t)(next_instr - this_instr);

@bedevere-app
Copy link

bedevere-app bot commented Oct 17, 2024

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@tomasr8
Copy link
Member Author

tomasr8 commented Oct 21, 2024

Passing the instruction size or None to every replacement function seems a bit clunky though.
Maybe would could add an instruction_size attribute to the Uop class and do the instruction size checking in analyzer.py?

I also thought it was less than ideal the way I did it, but I was a bit wary about adding more attributes to the classes. Though, your suggestion simplifies the code quite a bit!

I added a new attribute Uop.instruction_size which is only set for uops which contain the macro, otherwise it is None. This attribute is then used by the emitter.

@tomasr8
Copy link
Member Author

tomasr8 commented Oct 26, 2024

Friendly ping @markshannon 🙂 I think I addressed all of your points.

@markshannon markshannon self-requested a review October 28, 2024 09:40
Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

The assertion needs to be changed to explicitly raise. Otherwise it won't work with -O enabled.

Lib/test/test_generated_cases.py Outdated Show resolved Hide resolved
Lib/test/test_generated_cases.py Outdated Show resolved Hide resolved
Tools/cases_generator/analyzer.py Outdated Show resolved Hide resolved
Tools/cases_generator/analyzer.py Outdated Show resolved Hide resolved
Tools/cases_generator/analyzer.py Outdated Show resolved Hide resolved
@bedevere-app
Copy link

bedevere-app bot commented Oct 28, 2024

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@tomasr8
Copy link
Member Author

tomasr8 commented Oct 28, 2024

Thanks again for the review!

I have made the requested changes; please review again 🙂

@bedevere-app
Copy link

bedevere-app bot commented Oct 28, 2024

Thanks for making the requested changes!

@markshannon: please review the changes made to this pull request.

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

This looks good and correct now. Thanks.

I have a few suggestions, but they are mostly cosmetic.

Tools/cases_generator/analyzer.py Outdated Show resolved Hide resolved
Tools/cases_generator/analyzer.py Outdated Show resolved Hide resolved
if uop in inst.parts:
if size is None:
size = inst.size
if size != inst.size:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if size != inst.size:
elif size != inst.size:

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed this to an if because otherwise mypy complains that the elif is unreachable:

Tools/cases_generator/analyzer.py:1103: error: Statement is unreachable  [unreachable]

Copy link
Member

Choose a reason for hiding this comment

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

OK, leave it then.

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

Looks good.
Thanks for doing this.

@markshannon markshannon enabled auto-merge (squash) October 29, 2024 17:17
@markshannon markshannon merged commit aab58a9 into python:main Oct 29, 2024
70 of 71 checks passed
@tomasr8 tomasr8 deleted the instr-size branch October 29, 2024 21:19
@tomasr8
Copy link
Member Author

tomasr8 commented Oct 29, 2024

Thanks for all the reviews! :)

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

Successfully merging this pull request may close these issues.

3 participants