-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Remove redundant ulong casts in Span.Slice for x64 targets #123635
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
base: main
Are you sure you want to change the base?
Conversation
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.
Pull request overview
This PR removes platform-specific bounds checking workarounds for 64-bit targets in Span, Memory, and related types. The change simplifies the code by using a uniform bounds check pattern across all platforms, enabling better JIT optimization and eliminating unnecessary bounds checks in common slicing patterns.
Changes:
- Replaced complex 64-bit-specific bounds checks with simpler, JIT-friendly two-condition checks that work uniformly across all platforms
- Updated comment in ValueListBuilder.cs to reflect that the guard condition is now universal rather than 64-bit specific
- Removed all TARGET_64BIT conditional compilation directives related to bounds checking from Span, Memory, String, and related types
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Private.CoreLib/src/System/Span.cs | Removed TARGET_64BIT conditional for Slice bounds checking in both constructor and Slice method |
| src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs | Removed TARGET_64BIT conditional for Slice bounds checking in both constructor and Slice method |
| src/libraries/System.Private.CoreLib/src/System/Memory.cs | Removed TARGET_64BIT conditional for Slice bounds checking in constructor, Slice method, and Span property getter |
| src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs | Removed TARGET_64BIT conditional for Slice bounds checking in constructor, Slice method, and Span property getter |
| src/libraries/System.Private.CoreLib/src/System/String.cs | Removed TARGET_64BIT conditional from TryGetSpan method |
| src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs | Removed TARGET_64BIT conditional from Substring method |
| src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs | Removed TARGET_64BIT conditionals from AsSpan and AsMemory extension methods |
| src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ValueListBuilder.cs | Updated comment to reflect universal application of guard condition and simplified the bounds check |
| int pos = _pos; | ||
| Span<T> span = _span; | ||
| if ((ulong)(uint)pos + (ulong)(uint)length <= (ulong)(uint)span.Length) // same guard condition as in Span<T>.Slice on 64-bit | ||
| if ((uint)pos <= (uint)span.Length - (uint)length) // same guard condition as in Span<T>.Slice |
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.
you need the !TARGET_64BIT path from Slice here, this is not the same as before
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, this has been reverted.
@EgorBo is it possible we're seeing multiple regressions because of this change ? Would you mind re-running MihuBot once more for the fresh changes ? It seems I don't have access, and I'm not sure how I can run the same suite locally.
|
Some of my recent JIT changes were preparing for this actually, but I am not yet sure it won't regress today. the 64bit path messes with JIT's range check analysis which is built mostly around 32-bit integers (because of Array/Span Length being so), but at the same time it's just one condition+branch. The latter produces two jumps and JIT is not smart enough to merge it into one when it can (after opts). |
|
I think it's not ready for merge yet, needs more work in JIT |
Fixes #120607.
Related: #67044 , #119689
Remove 64-bit workarounds (ulong casts for 64-bit arithmetic) to produce JIT-friendly code that eliminates unnecessary bounds checks for Span slices. Presumably, this has become possible thanks to earlier work done in #62864,
Code from the issue:
Before changes:
After changes