Open stephentoub opened 4 years ago
Tagging @agocke
Bringing over a case from #54659 that is compelling here:
using System;
public class C {
public Span<char> M0(Span<Char> s, int pos) => s[..pos];
public Span<char> M1(Span<Char> s, int pos) => s[0..pos];
public Span<char> M2(Span<Char> s, int pos) => s.Slice(0, pos);
}
These should produce identical IL but do not because we end up spilling to temporaries even though there are no side effects here.
I just implemented range based slicing in dozens of places in the ImageSharp codebase as a result of the default analysis suggestion. It was a shock to discover that the codegen was less optimal. I would imagine many others in the wild would find this surprising also.
This is fixed for the most part already (likely as part of https://github.com/dotnet/roslyn/pull/57535)
But it still captures the receiver even if it's being used once if that at all matters. (sharplab.io)
Version Used: https://github.com/dotnet/roslyn/commit/441c154b27eafc9ed04feda1786f0f07ce448f14
To preserve side-effecting behavior, avoid introducing duplicate operations, and maintain order of operations, Roslyn generates temporaries for the lower and upper bounds of a range, e.g.
is compiled to the equivalent of:
However, such temps aren't necessary when Roslyn can prove there are no such issues with the bounds. For example, for the following where both bounds are const:
it currently generates the equivalent of:
as:
when it could instead just generate the equivalent of:
aka
This pattern of both bounds being a const shows up when parsing known formats with known offsets.
The same holds when just the lower bound is a const, e.g.
the compiler is currently generating:
when it could instead generate the equivalent of:
This pattern shows up when trimming off the end of something.
It's also possible to do better when using a negative offset index. For example:
currently results in the equivalent of:
but could instead produce:
This pattern shows up when trimming things off both ends, such as quotes off of a string.