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

Intrinsically recognize Unsafe APIs in the scanner #82589

Closed
wants to merge 1 commit into from

Conversation

MichalStrehovsky
Copy link
Member

Size optimization. If we're in shared code, call to an Unsafe intrinsic would bring generic lookup for the generic dictionary of the generic method. We would not be able to get rid of it later because it would be referenced from the other generic dictionary (the purpose of the scanning phase is to figure out how generic dictionaries will look like when we start code generation - this would be an unused slot).

To add insult to injury, the dictionary would be empty most of the time because these generic methods don't actually do anything with their T.

RyuJIT recognizes these intrinsically and it's not going to ask for the generic dictionary.

Loose generic dictionaries actually add quite a bit of costs because we need to keep track of them in hash tables in the generated executable (type loader might need it, reflection might need them, etc.)

Saves almost 1.1% on BasicMinimalApi (!!!).

Cc @dotnet/ilc-contrib

Size optimization. If we're in shared code, call to an Unsafe intrinsic would bring generic lookup for the generic dictionary of the generic method. We would not be able to get rid of it later because it would be referenced from the other generic dictionary (the purpose of the scanning phase is to figure out how generic dictionaries will look like when we start code generation - this would be an unused slot).

To add insult to injury, the dictionary would be empty most of the time because these generic methods don't actually do anything with their T.

RyuJIT recognizes these intrinsically and it's not going to ask for the generic dictionary.

Loose generic dictionaries actually add quite a bit of costs because we need to keep track of them in hash tables in the generated executable (type loader might need it, reflection might need them, etc.)

Saves almost 1.1% on BasicMinimalApi (!!!).
@ghost
Copy link

ghost commented Feb 24, 2023

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Issue Details

Size optimization. If we're in shared code, call to an Unsafe intrinsic would bring generic lookup for the generic dictionary of the generic method. We would not be able to get rid of it later because it would be referenced from the other generic dictionary (the purpose of the scanning phase is to figure out how generic dictionaries will look like when we start code generation - this would be an unused slot).

To add insult to injury, the dictionary would be empty most of the time because these generic methods don't actually do anything with their T.

RyuJIT recognizes these intrinsically and it's not going to ask for the generic dictionary.

Loose generic dictionaries actually add quite a bit of costs because we need to keep track of them in hash tables in the generated executable (type loader might need it, reflection might need them, etc.)

Saves almost 1.1% on BasicMinimalApi (!!!).

Cc @dotnet/ilc-contrib

Author: MichalStrehovsky
Assignees: -
Labels:

area-NativeAOT-coreclr

Milestone: -

@MichalStrehovsky
Copy link
Member Author

@EgorBo are there any conditions where RyuJIT would not end up expand these in the importer? Do I need to mark them mustExpand in RyuJIT?

@MichalStrehovsky MichalStrehovsky added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Feb 24, 2023
@MichalStrehovsky
Copy link
Member Author

I'll put NO MERGE. If #82591 comes through, this is not needed. With #82591 in place, the saving from this go down to like 0.05% and likely are not worth the extra code.

@EgorBo
Copy link
Member

EgorBo commented Feb 24, 2023

@EgorBo are there any conditions where RyuJIT would not end up expand these in the importer? Do I need to mark them mustExpand in RyuJIT?

Currently, they're marked as "better to expand" meaning - in case of debug or minopts they won't be expanded. I think they can be marked as mustExpand anyway

@EgorBo
Copy link
Member

EgorBo commented Feb 24, 2023

betterToExpand = ni >= NI_SRCS_UNSAFE_START && ni <= NI_SRCS_UNSAFE_END;

@tannergooding
Copy link
Member

There’s an issue (or might’ve been comment on one of the related PRs) that Jan put up asking us to make these recursive which will in turn make them mustExpand and treated the same as hardware intrinsics (on mobile, so cannot find easily atm)

Many hardware intrinsic APIs are notably in the same boat of not using their T, so it’s possible this applies to them as well

Notably mustExpand really just exists to handle the recursion and needing a managed fallback impl. It doesn’t guarantee that all main usages are expanded in import as it may not handle all failure cases and there is the general case where we cannot expand intrinsics for a particular IT pattern today

@MichalStrehovsky
Copy link
Member Author

Going to go with #82589.

@MichalStrehovsky MichalStrehovsky deleted the unsafeapis branch February 27, 2023 04:28
@ghost ghost locked as resolved and limited conversation to collaborators Mar 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-NativeAOT-coreclr NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants