Skip to content

Commit

Permalink
Use the List(int) constructor if possible when lowering collection ex…
Browse files Browse the repository at this point in the history
…pressions (#72427)
  • Loading branch information
jbevain authored Mar 12, 2024
1 parent c3565da commit af15182
Show file tree
Hide file tree
Showing 2 changed files with 1,017 additions and 898 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -883,12 +883,33 @@ private BoundExpression CreateAndPopulateList(BoundCollectionExpression node, Ty
}
}

// Create a temp for the knownLength
BoundAssignmentOperator assignmentToTemp;
BoundLocal? knownLengthTemp = null;

BoundObjectCreationExpression rewrittenReceiver;
if (useKnownLength && elements.Length > 0 && !useOptimizations)
if (useKnownLength && elements.Length > 0)
{
// List<ElementType> list = new(N + s1.Length + ...);
var constructor = ((MethodSymbol)_factory.WellKnownMember(WellKnownMember.System_Collections_Generic_List_T__ctorInt32)).AsMember(collectionType);
rewrittenReceiver = _factory.New(constructor, ImmutableArray.Create(GetKnownLengthExpression(elements, numberIncludingLastSpread, localsBuilder)));
var knownLengthExpression = GetKnownLengthExpression(elements, numberIncludingLastSpread, localsBuilder);

if (useOptimizations)
{
// If we use optimizations, we know the length of the resulting list, and we store it in a temp so we can pass it to List.ctor(int32) and to CollectionsMarshal.SetCount

// int knownLengthTemp = N + s1.Length + ...;
knownLengthTemp = _factory.StoreToTemp(knownLengthExpression, out assignmentToTemp, isKnownToReferToTempIfReferenceType: true);
localsBuilder.Add(knownLengthTemp);
sideEffects.Add(assignmentToTemp);

// List<ElementType> list = new(knownLengthTemp);
rewrittenReceiver = _factory.New(constructor, ImmutableArray.Create<BoundExpression>(knownLengthTemp));
}
else
{
// List<ElementType> list = new(N + s1.Length + ...)
rewrittenReceiver = _factory.New(constructor, ImmutableArray.Create(knownLengthExpression));
}
}
else
{
Expand All @@ -898,7 +919,6 @@ private BoundExpression CreateAndPopulateList(BoundCollectionExpression node, Ty
}

// Create a temp for the list.
BoundAssignmentOperator assignmentToTemp;
BoundLocal listTemp = _factory.StoreToTemp(rewrittenReceiver, out assignmentToTemp, isKnownToReferToTempIfReferenceType: true);
localsBuilder.Add(listTemp);
sideEffects.Add(assignmentToTemp);
Expand All @@ -909,9 +929,10 @@ private BoundExpression CreateAndPopulateList(BoundCollectionExpression node, Ty
Debug.Assert(useKnownLength);
Debug.Assert(setCount is { });
Debug.Assert(asSpan is { });
Debug.Assert(knownLengthTemp is { });

// CollectionsMarshal.SetCount<ElementType>(list, N + s1.Length + ...);
sideEffects.Add(_factory.Call(receiver: null, setCount, listTemp, GetKnownLengthExpression(elements, numberIncludingLastSpread, localsBuilder)));
// CollectionsMarshal.SetCount<ElementType>(list, knownLengthTemp);
sideEffects.Add(_factory.Call(receiver: null, setCount, listTemp, knownLengthTemp));

// var span = CollectionsMarshal.AsSpan<ElementType(list);
BoundLocal spanTemp = _factory.StoreToTemp(_factory.Call(receiver: null, asSpan, listTemp), out assignmentToTemp, isKnownToReferToTempIfReferenceType: true);
Expand Down
Loading

0 comments on commit af15182

Please sign in to comment.