Skip to content

Commit

Permalink
Added CreateSpan optimization for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
svick committed Oct 13, 2021
1 parent 0f2120d commit 580ec90
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,25 @@ public override BoundNode VisitConversion(BoundConversion node)

var rewrittenType = VisitType(node.Type);

// special handling for stackalloc converted to ROS<T>
if (node.Operand is BoundConvertedStackAllocExpression stackAllocExpression &&
TypeSymbol.Equals(rewrittenType.OriginalDefinition, _compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.ConsiderEverything))
// special handling for initializers converted to ROS<T>
if (TypeSymbol.Equals(rewrittenType.OriginalDefinition, _compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.ConsiderEverything))
{
bool hasCreateSpanHelper = _compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__CreateSpan_T) is not null;
var elementType = stackAllocExpression.ElementType;
var initializerOpt = stackAllocExpression.InitializerOpt;
if (CodeGen.CodeGenerator.UseCreateSpanForReadOnlyStackAlloc(hasCreateSpanHelper, elementType, initializerOpt,
/* TODO: how to find out if this is ENC? */ supportsPrivateImplClass: true))
if (node.Operand is BoundConvertedStackAllocExpression or BoundArrayCreation)
{
return new BoundConvertedStackAllocExpression(stackAllocExpression.Syntax, elementType, VisitExpression(stackAllocExpression.Count), initializerOpt, rewrittenType);
bool hasCreateSpanHelper = _compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__CreateSpan_T) is not null;

var (elementType, initializerOpt, count) = node.Operand switch
{
BoundConvertedStackAllocExpression stackAlloc => (stackAlloc.ElementType, stackAlloc.InitializerOpt, VisitExpression(stackAlloc.Count)),
BoundArrayCreation arrayCreation => (((ArrayTypeSymbol)arrayCreation.Type).ElementType, arrayCreation.InitializerOpt, /* need some dummy expression */ _factory.Literal(0)),
_ => throw ExceptionUtilities.Unreachable
};

if (CodeGen.CodeGenerator.UseCreateSpanForReadOnlyStackAlloc(hasCreateSpanHelper, elementType, initializerOpt,
/* TODO: how to find out if this is ENC? */ supportsPrivateImplClass: true))
{
return new BoundConvertedStackAllocExpression(node.Operand.Syntax, elementType, count, initializerOpt, rewrittenType);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,36 @@ .maxstack 4
");
}

[Fact]
public void TestArray()
{
var comp = CreateCompilation(new[] { @"
using System;
static class C
{
static void Main(int i)
{
ReadOnlySpan<int> p = new int[] { 1, 2, 3 };
Write(p);
}
static void Write(ReadOnlySpan<int> span) {}
}
", CreateSpanDefinition }, targetFramework: TargetFramework.Net50);
CompileAndVerify(comp, verify: Verification.Fails)
.VerifyIL("C.Main",
@"
{
// Code size 16 (0x10)
.maxstack 1
IL_0000: ldtoken ""<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D""
IL_0005: call ""System.ReadOnlySpan<int> System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<int>(System.RuntimeFieldHandle)""
IL_000a: call ""void C.Write(System.ReadOnlySpan<int>)""
IL_000f: ret
}
");
}

private static string GetSource(string pointerType) => $@"
using System;
using T = {pointerType};
Expand Down

0 comments on commit 580ec90

Please sign in to comment.