-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Swapping with tuple deconstruction compiles to inferior IL code compared to using a temporary variable #53300
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. |
If you check the JIT asm on sharplab you'll find they have the same output. |
Yes, that makes sense, but I still think that we should produce the best IL possible, since it will take less time to JIT and will be smaller. Especially since it seems that they bothered to do it for C# temporary variable so it should be easier to implement if it's already implemented elsewhere, and I'm sure that they had a good reason to do it for C# temporary variable. |
While that may be reasonable for you to assume, the only responsibility the compiler has is producing correct IL. Producing optimized IL would require much more analysis, most of which can't be done if you're compiling something like a class library (no entry point).
And your metrics for this statement are where? |
I see your point re making correct IL, that's probably fair enough then, but this optimisation has nothing to do whether it's a class library or not, it's just swapping locals, it doesn't rely on any library at all, or the possible behaviour differences between a library and an executable (which shouldn't be different if you ask me since you can reference it even if it has an entry point). |
I just noticed this conversation in dotnet/runtime: dotnet/runtime#64412 (comment) |
Yes, the only guarantee the compiler makes is producing correct IL, which means that this isn't a bug, but it's still a reasonable feature request and an improvement, especially given the big focus on performance in today's .NET. Also, this would just be a small focused optimization to eliminate a local or avoid creating it in the first place, nothing to do with interprocedural optimization, so your comment about a class library and entry points is irrelevant. |
@Neme12 JIT performs optimization for x64 |
That type is 64 bits. Try one that's larger, e.g. |
I'd also like to say that in terms of inlining, tuple destruction can be a turn off sometimes. Elaboration on what IL code I propose gets emitted: For a field on the left (a): For a pointer or byref on the left (a): For a local variable (a): And for things on the right, it is just the standard way of loading them onto the stack. |
Description
Swapping / reordering variables compiles to slower IL code when using tuple destruction than a temporary variable.
I tested this in Release mode.
The following C# code
should be equivalent in IL output to
, but the first compiles to:
and the second compiles to
With the essential code being for (1):
, and for (2):
I did test this on .NET 5 locally, but also on an online .NET 6 compiler at https://sharplab.io/, which uses a very recent version.
I also imagine that a similar thing happens for other variants, such as:
etc.
Surely these destruction assignments should be as simple as
ld
all of the variables, and thenst
them all (as long as there's not too many).Interestingly, the tuple destruction code essentially uses a temporary variable in IL, whereas the temporary variable code eliminates it.
Not sure if this belongs on roslyn or on here.
The text was updated successfully, but these errors were encountered: