-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[RyuJIT] static readonly fields can be Invariant #44562
[RyuJIT] static readonly fields can be Invariant #44562
Conversation
I am good with this change. @AndyAyersMS did you have any concerns here? |
Nice! |
// Auto-generated message 69e114c which was merged 12/7 removed the intermediate src/coreclr/src/ folder. This PR needs to be updated as it touches files in that directory which causes conflicts. To update your commits you can use this bash script: https://gist.github.com/ViktorHofer/6d24f62abdcddb518b4966ead5ef3783. Feel free to use the comment section of the gist to improve the script for others. |
@EgorBo waiting on you to resolve conflicts. |
3ccb654
to
b56e447
Compare
Also just want to point out this doesn't work for shared generic statics, even if we happen to know which exact instantiation we're accessing (because of inlining, say). |
…adonly-field-invariant
@AndyAyersMS could you please re-review? |
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.
This should apply more broadly instead of just to the case where the static address can't be RIP-relative.
Also, is
if (IMAGE_REL_BASED_REL32 != eeGetRelocTypeHint(fldAddr))
the right check for Arm64?
Can you fix up the "then" case to update tree instead of returning, and then move the new logic you are adding down below the joint point?
…adonly-field-invariant
…adonly-field-invariant
Co-authored-by: Andy Ayers <[email protected]>
…Bo/runtime-1 into jit-static-readonly-field-invariant
2772a5d
to
43360d3
Compare
@AndyAyersMS sorry but I don't think I follow, the structure of this method is:
where do you want me to move the "is initialized" logic to? |
As you show in your later commits, there's a divergence in how known-address statics are represented, depending on whether they can be directly addressed via an IP-relative offset or require materialization of the full address constant. We either need to be able to mark a I don't know why the IR was done this way -- might be something worth revisiting. |
I guess in some cases it might lead to a slightly less efficient codegen (where we don't benefit from being GTF_IND_INVARIANT) but neither jit-diff --cctors nor some of the heave apps I have locally found anything so I decided to not adding more complexity for CLS_VAR. e.g. |
Seems reasonable. Can you describe what the impact of using GT_IND for invariant statics is for cases where we can't CSE/Hoist? You should also look at diffs on x86. |
I only got this delta with that commit:
@AndyAyersMS X86 always uses the |
That may be a spurious diff, given that one case has 8 instances and the other 9. We sometimes see this with PMI.
Ideally things that are conceptually arch independent would work the same on all architectures. This ends up only being arch specific because of weirdness in the jit IR. Given that our main perf targets are x64 and arm64 I think it is ok to defer trying to get this working for x86 and arm32. I would open a follow-up issue noting that the split between GT_IND and GT_CLS_VAR is responsible for some missed optimization. And speaking of Arm64, what happens there? Are we always on the GT_IND path because the type hint always fails? |
Yep, as far as I see so the GT_IND path is always taken there (on all 64bit platforms except Windows) |
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.
Thanks for all your work on this.
Closes #38201
It allows to do CSE/Hoist-from-loops optimizations for such indirections and also fixes bounds checks on top of
static readonly
arrays, e.g.:Codegen diff: https://www.diffchecker.com/KSiNytCN
JIT-diff (
-f --cctors --pmi
):As far as I can see, the failures are CSE-related, e.g.:
Codegen diff: https://www.diffchecker.com/INxlsOR7
static readonly
fields are marked as invariant only when the host type is already statically inited (we can't change such fields with Reflection viafield.SetValue
after that). We even convert such fields into constants for primitive types today.Tiered JIT helps us here because when we re-compile a method to tier1 the host type is always already inited. The only problem are methods with loops which are always compiled straight to tier1 and it means the compilation most likely happens before the static initialization. As far as I understand, we're going to enable
COMPlus_TC_QuickJitForLoops=1
eventually with OSR so this problem will go away.Optional:
Mark such fields as
GTF_NONFAULTING_IND
if we check the content is not null (doesn't really affect the jit-diff report).Also, the current fix doesn't help with
static readonly NonPrimitiveValueType =
at the moment./cc @briansull @sandreenko