-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Upper bound effect on unsafe indexing #61498
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsUsing .Net6 on Windows 10, VS Code. Not sure if this is an issue or not, but I don't understand what's going on. Consider the following code :
The only difference between Test1 and Test2 is the upper bound, either Count or Values.Length. Given that the enumerator is using an unsafe indexer, I would assume that this would have no effect on performance whatsoever. But this is not the case. Running this code through Benchmark.Net gives me the following result :
Looking at sharplab.io, the asm is indeed different between the two functions, but I'm not fluent enough in it to understand what's going on.
|
@jakobbotsch PTAL. |
Looks like we manage to eliminate the null-check of public long Test1()
{
long result = 0;
foreach (long lg in new ValueEnumerator<long>(Values, Count + Values.Length * 0))
result ^= lg;
return result;
} Seems related to loop opts, cc @BruceForstall. |
We do need the null check, since Test1 doesn't get it "for free" with the It's interesting that loop hoisting does hoist the address calculation that the null check protects:
(that is,
|
Thanks for the answers. The
I understand Also, since |
The compiler optimizes G_M43963_IG03: ;; offset=0028H
4C8BC9 mov r9, rcx
4C63D2 movsxd r10, edx
4F8B0CD1 mov r9, qword ptr [r9+8*r10]
4933C1 xor rax, r9
FFC2 inc edx
- 413BD0 cmp edx, r8d
+ 81FA40420F00 cmp edx, 0xF4240
7CEC jl SHORT G_M43963_IG03 It's interesting that this also affects the performance.
It is possible to set such fields using reflection and in general we do not really have the capability to reason "non-locally" about stuff like this. It would require looking at the constructor of the class and determining that no ref to
Right, that's what Bruce was referring to above with the fact that it is loop invariant -- we'd like to hoist the null check out of the loop body always. It's also possible we should be more aggressive about hoisting constants out of loops when register pressure is low. |
Alright, thanks again for the explanations. |
It looks related to #61420, but we can keep it open for when someone works on hoisting. |
On main we manage to hoist the null check in both cases now. This was probably fixed by #68588. |
Using .Net6 on Windows 10, VS Code.
Not sure if this is an issue or not, but I don't understand what's going on.
Consider the following code :
The only difference between Test1 and Test2 is the upper bound, either Count or Values.Length.
Given that the enumerator is using an unsafe indexer, I would assume that this would have no effect on performance whatsoever. But this is not the case. Running this code through Benchmark.Net gives me the following result :
Looking at sharplab.io, the asm is indeed different between the two functions, but I'm not fluent enough in it to understand what's going on.
The text was updated successfully, but these errors were encountered: