-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Use constant indices when populating Lists and arrays in collection expressions #80999
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
Changes from 6 commits
536a406
fcb6eb3
c210cc9
738dcea
7aa7cab
877b12b
bd54c95
9ffa846
f9b7579
b5ed80e
38fdece
2fab349
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1177,13 +1177,22 @@ private BoundExpression CreateAndPopulateList(BoundCollectionExpression node, Ty | |
| // Populate the span. | ||
| var spanGetItem = ((MethodSymbol)_factory.WellKnownMember(WellKnownMember.System_Span_T__get_Item)).AsMember((NamedTypeSymbol)spanTemp.Type); | ||
|
|
||
| // int index = 0; | ||
| BoundLocal indexTemp = _factory.StoreToTemp( | ||
| _factory.Literal(0), | ||
| out assignmentToTemp); | ||
| localsBuilder.Add(indexTemp); | ||
| sideEffects.Add(assignmentToTemp); | ||
| // When there are no spread elements, we can use constant indices for better codegen. | ||
| // When there are spread elements, we need a mutable index variable for the CopyTo optimization. | ||
| bool useConstantIndices = numberIncludingLastSpread == 0; | ||
| BoundLocal? indexTemp = null; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. review with whitespace off. |
||
|
|
||
| if (!useConstantIndices) | ||
|
||
| { | ||
| // int index = 0; | ||
| indexTemp = _factory.StoreToTemp( | ||
| _factory.Literal(0), | ||
| out assignmentToTemp); | ||
| localsBuilder.Add(indexTemp); | ||
| sideEffects.Add(assignmentToTemp); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot CreateAndPopulateArray contains very similar logic for arrays. can you update the PR to use constant indices for those as well when possible?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Applied constant indices optimization to arrays in commit 9ffa846. Arrays now use the same optimization as Lists when there are no spread elements. |
||
|
|
||
| int currentElementIndex = 0; | ||
| AddCollectionExpressionElements( | ||
| elements, | ||
| spanTemp, | ||
|
|
@@ -1193,33 +1202,52 @@ private BoundExpression CreateAndPopulateList(BoundCollectionExpression node, Ty | |
| addElement: (ArrayBuilder<BoundExpression> expressions, BoundExpression spanTemp, BoundExpression rewrittenValue, bool isLastElement) => | ||
| { | ||
| Debug.Assert(spanTemp.Type is NamedTypeSymbol); | ||
| Debug.Assert(indexTemp.Type is { SpecialType: SpecialType.System_Int32 }); | ||
|
|
||
| var expressionSyntax = rewrittenValue.Syntax; | ||
| var elementType = ((NamedTypeSymbol)spanTemp.Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].Type; | ||
|
|
||
| // span[index] = element; | ||
| expressions.Add( | ||
| new BoundAssignmentOperator( | ||
| expressionSyntax, | ||
| _factory.Call(spanTemp, spanGetItem, indexTemp), | ||
| rewrittenValue, | ||
| isRef: false, | ||
| elementType)); | ||
| if (!isLastElement) | ||
| if (useConstantIndices) | ||
| { | ||
| // index = index + 1; | ||
| // span[0] = element; span[1] = element; etc. | ||
| expressions.Add( | ||
| new BoundAssignmentOperator( | ||
| expressionSyntax, | ||
| indexTemp, | ||
| _factory.Binary(BinaryOperatorKind.Addition, indexTemp.Type, indexTemp, _factory.Literal(1)), | ||
| _factory.Call(spanTemp, spanGetItem, _factory.Literal(currentElementIndex)), | ||
| rewrittenValue, | ||
| isRef: false, | ||
| indexTemp.Type)); | ||
| elementType)); | ||
| currentElementIndex++; | ||
| } | ||
| else | ||
| { | ||
| Debug.Assert(indexTemp is { Type.SpecialType: SpecialType.System_Int32 }); | ||
|
|
||
| // span[index] = element; | ||
| expressions.Add( | ||
| new BoundAssignmentOperator( | ||
| expressionSyntax, | ||
| _factory.Call(spanTemp, spanGetItem, indexTemp), | ||
| rewrittenValue, | ||
| isRef: false, | ||
| elementType)); | ||
| if (!isLastElement) | ||
| { | ||
| // index = index + 1; | ||
| expressions.Add( | ||
| new BoundAssignmentOperator( | ||
| expressionSyntax, | ||
| indexTemp, | ||
| _factory.Binary(BinaryOperatorKind.Addition, indexTemp.Type, indexTemp, _factory.Literal(1)), | ||
| isRef: false, | ||
| indexTemp.Type)); | ||
| } | ||
| } | ||
| }, | ||
| tryOptimizeSpreadElement: (ArrayBuilder<BoundExpression> sideEffects, BoundExpression spanTemp, BoundCollectionExpressionSpreadElement spreadElement, BoundExpression rewrittenSpreadOperand) => | ||
| { | ||
| Debug.Assert(!useConstantIndices, "Should not have spread elements when using constant indices"); | ||
| Debug.Assert(indexTemp is not null); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot have a similar comment here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment was already added in commit 38fdece at line 1270 (same location). |
||
|
|
||
| if (PrepareCopyToOptimization(spreadElement, rewrittenSpreadOperand) is not var (spanSliceMethod, spreadElementAsSpan, getLengthMethod, copyToMethod)) | ||
| return false; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.