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

Assist JIT in eliminating bounds checks #81036

Merged
merged 3 commits into from
May 15, 2023
Merged

Conversation

xtqqczze
Copy link
Contributor

Follow-up: #81001.

Change condition in loops from index != T.Length to index < T.Length where T:

  • U[]
  • string
  • Span<U>
  • ReadOnlySpan<U>

cc: @stephentoub

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Jan 23, 2023
@@ -61,7 +61,7 @@ private static bool TryParseNumber(ReadOnlySpan<byte> source, ref Number.NumberB
int maxDigitCount = digits.Length - 1;

// Throw away any leading zeroes
while (srcIndex != source.Length)
while (srcIndex < source.Length)
Copy link
Member

Choose a reason for hiding this comment

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

Do these need uint-casts to eliminate the bound checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case casts appear to regress bounds check elimination.

Perhaps this is unnecessary because srcIndex is a local variable that is zero-initialized?

Copy link
Member

Choose a reason for hiding this comment

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

In this case casts appear to regress bounds check elimination.

Can you elaborate? I wouldn't expect this to remove the bounds check on source[srcIndex] without casting srcIndex to uint here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We already do checks on source.Length before the loop. Adding uint casts seems to cause JIT to "forget" about these.

Copy link
Member

Choose a reason for hiding this comment

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

I still don't understand what you mean. Can you share a sharplab.io example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's worth noting that SharpLab is .NET 7

@tannergooding For future reference, does the codegen from Compiler Explorer have the same optimizations as a local disassembly using .NET 8 nightly build.

Currently, .e.g. https://csharp.godbolt.org/z/cKhTfjvqd, seems to be using:
// crossgen2 8.0.0-preview.3.23152.99+8d2ddc45e8f6f2a726c2b91c1ba2b9f7208b1f3b

Copy link
Member

Choose a reason for hiding this comment

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

@xtqqczze for godbolt you need to pass -O or better --Ot argument to compiler to enable optimizations. godbolt uses crossgen (R2R) which is, on average, worse than what JIT emits (sharplab). Although, even sharplab's codegen is a bit synthetic since in the real world our JIT is tiered and Tier1 codegen might be different from what you see in sharplab.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for godbolt you need to pass -O or better --Ot

@EgorBo Not seeing any differeences in codegen for this example: https://csharp.godbolt.org/z/cKhTfjvqd, is this expected?

Copy link
Member

@tannergooding tannergooding Mar 3, 2023

Choose a reason for hiding this comment

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

Yes. However, its showing the crossgen code and so isn't strictly the same as what sharplab shows or what a user will see for Tier 1 codegen.

You can customize the instruction set targeted and I'd recommend using --instruction-set x86-x64-v3 as that targets AVX2, BMI1, BMI2, LZCNT, MOVBE, and FMA

You can customize the OS: --targetos windows (defaults to linux)
and the architecture: --targetarch arm64 (defaults to x64)

and in general pass in other options supported by crossgen (such as --Ot to optimize for speed)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tannergooding Great help with your tips, I knew about the parameters but couldn't find a useful reference with a search engine.

@xtqqczze xtqqczze marked this pull request as ready for review January 23, 2023 19:48
@xtqqczze xtqqczze changed the title Help eliminate more bounds checks Assist JIT in eliminating bounds checks Jan 23, 2023
@ghost
Copy link

ghost commented Feb 20, 2023

Tagging subscribers to this area: @dotnet/area-meta
See info in area-owners.md if you want to be subscribed.

Issue Details

Follow-up: #81001.

Change condition in loops from index != T.Length to index < T.Length where T:

  • U[]
  • string
  • Span<U>
  • ReadOnlySpan<U>

cc: @stephentoub

Author: xtqqczze
Assignees: -
Labels:

area-Meta, community-contribution

Milestone: -

@hughbe
Copy link
Contributor

hughbe commented Apr 12, 2023

Should we create an issue to add support to JIT to eliminate range checks for these?

@xtqqczze
Copy link
Contributor Author

Should we create an issue to add support to JIT to eliminate range checks for these?

Issue opened: #84697.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

LGTM. Most of these won't actually help eliminate bounds checks like the title suggests, but they're fine for clarity.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

LGTM. Most of these won't actually help eliminate bounds checks like the title suggests, but they're fine for clarity.

@stephentoub stephentoub merged commit 6730c71 into dotnet:main May 15, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jun 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Meta community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants