Skip to content

Commit 77f04cd

Browse files
ExpandLinq: stop expanding Range().{ToArray()|ToList()}
These are already optimized in LINQ and vectorized in .NET 8, see #25
1 parent 7d16acf commit 77f04cd

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

src/DistIL/Passes/ExpandLinq.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,23 @@ public MethodPassResult Run(MethodTransformContext ctx)
4343

4444
private static bool IsProfitableToExpand(LinqSourceNode source, LinqSink sink)
4545
{
46-
//Unfiltered Count()/Any() is not profitable because we scan the entire source.
46+
//Unfiltered Count()/Any() is not profitable because we always scan over
47+
//the entire source, and LINQ specializes over collections and such.
4748
if (sink.SubjectCall is { NumArgs: 1, Method.Name: "Count" or "Any" }) {
4849
return false;
4950
}
50-
//Concretizing enumerator sources may not be profitable because
51+
//Expanding enumerator sources may not be profitable because
5152
//Linq can special-case source types and defer to e.g. Array.Copy().
5253
//Similarly, expanding an enumerator source to a loop sink is an expansive no-op.
5354
if (source is EnumeratorSource && source.Drain == sink) {
5455
return sink is not (ConcretizationSink or LoopSink);
5556
}
57+
//Range().ToArray() and ToList() are already special-cased by LINQ, and vectorized in .NET 8.
58+
// - https://github.com/dubiousconst282/DistIL/issues/25
59+
// - https://github.com/dotnet/runtime/pull/87992
60+
if (source is IntRangeSource && source.Drain == sink) {
61+
return sink is not ListOrArraySink;
62+
}
5663
return true;
5764
}
5865

0 commit comments

Comments
 (0)