-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Rework JIT<->EE communication for struct promotion #87917
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
Conversation
Rework the communication so that the JIT asks the EE for struct field related information relevant to promotion in a single JIT-EE call of a new function called getTypeLayout. Crossgen2 can then more easily provide the information that the JIT is allowed to depend on. As a side effect, removes CORINFO_FLG_CUSTOMLAYOUT (which fixes dotnet#71711) and CORINFO_FLG_DONT_DIG_FIELDS. Fix dotnet#85511 Fix dotnet#71711
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsRework the communication so that the JIT asks the EE for struct field related information relevant to promotion in a single JIT-EE call of a new function called getTypeLayout. Crossgen2 can then more easily provide the information that the JIT is allowed to depend on. As a side effect, removes CORINFO_FLG_CUSTOMLAYOUT (which fixes #71711) and CORINFO_FLG_DONT_DIG_FIELDS.
|
/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress, runtime-jit-experimental, runtime-coreclr outerloop |
Azure Pipelines successfully started running 4 pipeline(s). |
Having these class handles floating around in the JIT is problematic during prejit where the JIT-EE calls allowed on "random" type handles (in this case the type of a field of a struct) is limited. Precursor to dotnet#87917
Having these class handles floating around in the JIT is problematic during prejit where the JIT-EE calls allowed on "random" type handles (in this case the type of a field of a struct) is limited. Precursor to dotnet#87917
… in the recursive function
/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress, runtime-coreclr outerloop |
/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress |
Azure Pipelines successfully started running 2 pipeline(s). |
Having these class handles floating around in the JIT is problematic during prejit where the JIT-EE calls allowed on "random" type handles (in this case the type of a field of a struct) is limited. Precursor to dotnet#87917
cc @dotnet/jit-contrib PTAL @AndyAyersMS (JIT side) @davidwrighton (VM/crossgen2 parts). This passed outerloop and the jitstress pipelines above. I've verified that this is no diff with jit-diff PMI for win-x64. I'll do some more validation for other platforms before merging this. For CG2 it is a size regression overall over frameworks to enable this promotion, at least on win-x64. It seems primarily to be because promotion disables last-use copy omission for implicit byrefs. Since this optimization is new in .NET 8 it still means this is not a size-wise regression going from .NET 7 to .NET 8. I'm including the changes from #87967 as part of this PR but expect those changes to merge separately before this. Those are JIT changes to make sure we are no longer passing type handles returned by CG2 for arbitrary fields around throughout the JIT -- there is a documented contract for how those type handles can be used now. win-x64 CG2 diffsFound 453 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 38402462
Total bytes of diff: 38524554
Total bytes of delta: 122092 (0.32 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
20988 : System.Security.Cryptography.dasm (3.19% of base)
18253 : System.Private.Xml.dasm (0.69% of base)
13602 : System.Text.Json.dasm (3.13% of base)
10728 : Microsoft.CodeAnalysis.VisualBasic.dasm (0.22% of base)
10546 : Microsoft.CodeAnalysis.CSharp.dasm (0.17% of base)
6586 : System.Security.Cryptography.Pkcs.dasm (2.75% of base)
6435 : System.Net.Http.dasm (1.28% of base)
2793 : System.Security.Cryptography.Cose.dasm (5.96% of base)
2553 : System.Private.DataContractSerialization.dasm (0.40% of base)
2352 : System.Formats.Asn1.dasm (3.20% of base)
2271 : System.Net.Sockets.dasm (1.50% of base)
2147 : System.Formats.Tar.dasm (3.03% of base)
2080 : System.Runtime.Numerics.dasm (2.06% of base)
1894 : System.Net.Security.dasm (1.29% of base)
1779 : System.Net.Quic.dasm (2.63% of base)
1186 : Microsoft.CodeAnalysis.dasm (0.06% of base)
1148 : Newtonsoft.Json.dasm (0.21% of base)
1128 : System.Numerics.Tensors.dasm (4.05% of base)
1115 : System.Data.Common.dasm (0.11% of base)
905 : System.Private.Xml.Linq.dasm (0.83% of base)
Top file improvements (bytes):
-1285 : System.Text.Encodings.Web.dasm (-4.54% of base)
-600 : System.Text.Encoding.CodePages.dasm (-1.06% of base)
-574 : System.Text.RegularExpressions.dasm (-0.20% of base)
-517 : System.Threading.RateLimiting.dasm (-1.24% of base)
-475 : xunit.runner.utility.netcoreapp10.dasm (-0.36% of base)
-450 : System.DirectoryServices.AccountManagement.dasm (-0.20% of base)
-428 : ILCompiler.Reflection.ReadyToRun.dasm (-0.34% of base)
-350 : System.Reflection.MetadataLoadContext.dasm (-0.23% of base)
-303 : System.Linq.Parallel.dasm (-0.11% of base)
-296 : System.Web.HttpUtility.dasm (-2.72% of base)
-289 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (-0.01% of base)
-273 : Microsoft.Extensions.Caching.Memory.dasm (-1.67% of base)
-262 : System.Configuration.ConfigurationManager.dasm (-0.09% of base)
-236 : System.IO.Compression.dasm (-0.35% of base)
-177 : System.Diagnostics.EventLog.dasm (-0.18% of base)
-135 : System.Drawing.Primitives.dasm (-0.43% of base)
-116 : Microsoft.Extensions.FileProviders.Physical.dasm (-0.79% of base)
-114 : System.Threading.Tasks.Parallel.dasm (-0.45% of base)
-103 : System.Speech.dasm (-0.03% of base)
-94 : System.Management.dasm (-0.03% of base)
148 total files with Code Size differences (41 improved, 107 regressed), 129 unchanged.
Top method regressions (bytes):
1462 (24.40% of base) : System.Net.Http.dasm - System.Net.Http.Headers.QPackStaticTable:.cctor()
708 (63.05% of base) : System.Private.Xml.dasm - System.Xml.Serialization.CodeGenerator:.cctor()
650 (20.09% of base) : System.Net.Http.dasm - System.Net.Http.Http2Connection+Http2Stream:.cctor()
643 (12.33% of base) : System.Text.Json.dasm - System.Text.Json.JsonDocument:TryGetValue(int,byref):bool:this (15 methods)
517 ( 9.37% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpDeclarationComputer:ComputeDeclarations(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.ISymbol,Microsoft.CodeAnalysis.SyntaxNode,System.Func`3[Microsoft.CodeAnalysis.SyntaxNode,System.Nullable`1[int],bool],bool,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1[Microsoft.CodeAnalysis.DeclarationInfo],System.Nullable`1[int],System.Threading.CancellationToken)
498 (66.49% of base) : System.Reflection.DispatchProxy.dasm - System.Reflection.DispatchProxyGenerator+ProxyBuilder:.cctor()
407 (26.81% of base) : System.Private.Xml.dasm - System.Xml.Xsl.IlGen.XmlILOptimizerVisitor:FoldArithmetic(int,System.Xml.Xsl.Qil.QilLiteral,System.Xml.Xsl.Qil.QilLiteral):System.Xml.Xsl.Qil.QilNode:this
371 ( 1.37% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this
360 ( 6.56% of base) : System.Private.Xml.dasm - System.Xml.XmlTextReaderImpl+<ParseXmlDeclarationAsync>d__505:MoveNext():this
353 (20.84% of base) : System.Private.Xml.dasm - System.Xml.XmlDocument:.cctor()
342 ( 9.20% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicDeclarationComputer:ComputeDeclarationsCore(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.SyntaxNode,System.Func`3[Microsoft.CodeAnalysis.SyntaxNode,System.Nullable`1[int],bool],bool,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1[Microsoft.CodeAnalysis.DeclarationInfo],System.Nullable`1[int],System.Threading.CancellationToken)
336 (33.50% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializer:SerializeInternal(Newtonsoft.Json.JsonWriter,System.Object,System.Type):this
330 ( 1.09% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this
322 ( 5.84% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.CoreTypeHelpers:GetFullName(int,byref,byref)
321 (20.55% of base) : System.Data.Common.dasm - System.Data.Common.TimeSpanStorage:Aggregate(int[],int):System.Object:this
313 (17.55% of base) : System.Text.Json.dasm - System.Text.Json.JsonSerializer:LookupProperty(System.Object,System.ReadOnlySpan`1[ubyte],byref,System.Text.Json.JsonSerializerOptions,byref,bool):System.Text.Json.Serialization.Metadata.JsonPropertyInfo
311 ( 6.26% of base) : System.Private.Xml.dasm - System.Xml.DtdParser+<GetTokenAsync>d__173:MoveNext():this
310 ( 9.36% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.SymbolDisplayVisitor:VisitMethod(Microsoft.CodeAnalysis.IMethodSymbol):this
294 ( 5.21% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.Scanner:ScanNumericLiteral(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList`1[Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.VisualBasicSyntaxNode]):Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.SyntaxToken:this
289 (15.59% of base) : System.Diagnostics.Process.dasm - System.Diagnostics.NtProcessManager:GetProcessInfos(System.Diagnostics.PerformanceCounterLib,int,int,System.ReadOnlySpan`1[ubyte]):System.Diagnostics.ProcessInfo[]
Top method improvements (bytes):
-948 (-16.64% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.RegexWriter:EmitFragment(ubyte,System.Text.RegularExpressions.RegexNode,int):this
-435 (-18.61% of base) : System.Text.Encoding.CodePages.dasm - System.Text.ISCIIEncoding:GetChars(ulong,int,ulong,int,System.Text.DecoderNLS):int:this
-427 (-8.97% of base) : xunit.console.dasm - Xunit.ConsoleClient.CommandLine:Parse(System.Predicate`1[System.String]):Xunit.XunitProject:this
-370 (-17.53% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.ConfigReader_Json:Load(System.IO.Stream):Xunit.TestAssemblyConfiguration
-351 (-39.00% of base) : System.Text.Encodings.Web.dasm - System.Text.Encodings.Web.DefaultJavaScriptEncoder+EscaperImplementation:<EncodeUtf16>g__TryEncodeScalarAsHex|5_0(System.Object,System.Text.Rune,System.Span`1[ushort]):int
-344 (-6.01% of base) : System.Runtime.Numerics.dasm - System.Globalization.FormatProvider+Number:NumberToStringFormat(byref,byref,System.ReadOnlySpan`1[ushort],System.Globalization.NumberFormatInfo)
-344 (-40.52% of base) : System.Text.Encodings.Web.dasm - System.Text.Encodings.Web.DefaultJavaScriptEncoder+EscaperImplementation:<EncodeUtf8>g__TryEncodeScalarAsHex|4_0(System.Object,System.Text.Rune,System.Span`1[ubyte]):int
-321 (-19.42% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.ImplementsHelper:ValidateImplementedMember[System.__Canon](System.__Canon,System.__Canon,Microsoft.CodeAnalysis.VisualBasic.Syntax.QualifiedNameSyntax,Microsoft.CodeAnalysis.VisualBasic.Binder,Microsoft.CodeAnalysis.VisualBasic.BindingDiagnosticBag,Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,System.String,byref):System.__Canon
-306 (-47.37% of base) : Microsoft.Extensions.Logging.Console.dasm - Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter:GetLogLevelConsoleColors(int):Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter+ConsoleColors:this
-289 (-9.26% of base) : System.Private.Xml.dasm - System.Xml.XmlConvert:DecodeName(System.String):System.String
-281 (-41.63% of base) : System.Text.Encodings.Web.dasm - System.Text.Encodings.Web.DefaultUrlEncoder+EscaperImplementation:EncodeUtf16(System.Text.Rune,System.Span`1[ushort]):int:this
-275 (-42.90% of base) : System.Text.Encodings.Web.dasm - System.Text.Encodings.Web.DefaultUrlEncoder+EscaperImplementation:EncodeUtf8(System.Text.Rune,System.Span`1[ubyte]):int:this
-275 (-17.87% of base) : System.Private.Uri.dasm - System.UriBuilder:ToString():System.String:this
-267 (-24.61% of base) : System.IO.Compression.dasm - System.IO.Compression.Zip64ExtraField:TryGetZip64BlockFromGenericExtraField(System.IO.Compression.ZipGenericExtraField,bool,bool,bool,bool,byref):bool
-253 (-5.10% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.GeneratorDriver:RunGeneratorsCore(Microsoft.CodeAnalysis.Compilation,Microsoft.CodeAnalysis.DiagnosticBag,System.Threading.CancellationToken):Microsoft.CodeAnalysis.GeneratorDriverState:this
-247 (-5.67% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonWriter:WriteValue(Newtonsoft.Json.JsonWriter,int,System.Object)
-244 (-5.44% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonWriter:WriteValueAsync(Newtonsoft.Json.JsonWriter,int,System.Object,System.Threading.CancellationToken):System.Threading.Tasks.Task
-229 (-11.21% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Schema.JsonSchemaGenerator:GenerateInternal(System.Type,int,bool):Newtonsoft.Json.Schema.JsonSchema:this
-213 (-8.64% of base) : System.Private.Xml.dasm - System.Xml.Xsl.XPathConvert+BigNumber:DblToRgbFast(double,ubyte[],byref,byref):bool
-193 (-6.78% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Schema.JsonSchemaBuilder:ProcessSchemaProperties(Newtonsoft.Json.Linq.JObject):this
Top method regressions (percentages):
51 (137.84% of base) : System.Net.Security.dasm - System.Net.Security.TlsFrameHelper:SkipOpaqueType1(System.ReadOnlySpan`1[ubyte]):System.ReadOnlySpan`1[ubyte]
78 (91.76% of base) : System.Private.Xml.dasm - System.Xml.Schema.Compiler:IsValidOccurrenceRangeRestriction(System.Xml.Schema.XmlSchemaParticle,System.Xml.Schema.XmlSchemaParticle):bool
78 (91.76% of base) : System.Private.Xml.dasm - System.Xml.Schema.SchemaCollectionCompiler:IsValidOccurrenceRangeRestriction(System.Xml.Schema.XmlSchemaParticle,System.Xml.Schema.XmlSchemaParticle):bool
102 (79.69% of base) : xunit.console.dasm - Internal.Microsoft.Extensions.DependencyModel.CompilationOptions:.cctor()
102 (79.69% of base) : Microsoft.Extensions.DependencyModel.dasm - Microsoft.Extensions.DependencyModel.CompilationOptions:.cctor()
15 (78.95% of base) : System.IO.Compression.dasm - System.IO.Compression.ZipArchive:CreateEntry(System.String):System.IO.Compression.ZipArchiveEntry:this
15 (78.95% of base) : System.IO.Compression.ZipFile.dasm - System.IO.Compression.ZipFileExtensions:CreateEntryFromFile(System.IO.Compression.ZipArchive,System.String,System.String):System.IO.Compression.ZipArchiveEntry
54 (78.26% of base) : System.Numerics.Tensors.dasm - System.Numerics.Tensors.ArrayUtilities:GetIndex(int[],System.ReadOnlySpan`1[int],int):int
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(double):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(float):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(int):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(long):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.DateTimeOffset):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Decimal):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Guid):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Nullable`1[double]):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Nullable`1[long]):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Nullable`1[System.DateTime]):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Nullable`1[System.DateTimeOffset]):System.Text.Json.Nodes.JsonNode
13 (72.22% of base) : System.Text.Json.dasm - System.Text.Json.Nodes.JsonNode:op_Implicit(System.Nullable`1[System.Decimal]):System.Text.Json.Nodes.JsonNode
Top method improvements (percentages):
-14 (-77.78% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.TestAssemblyConfiguration:get_MethodDisplayOptionsOrDefault():int:this
-14 (-73.68% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.TestAssemblyConfiguration:get_DiagnosticMessagesOrDefault():bool:this
-14 (-73.68% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.TestAssemblyConfiguration:get_InternalDiagnosticMessagesOrDefault():bool:this
-14 (-73.68% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.TestAssemblyConfiguration:get_ParallelizeAssemblyOrDefault():bool:this
-14 (-73.68% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.TestAssemblyConfiguration:get_StopOnFailOrDefault():bool:this
-27 (-72.97% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.LastValue:Update(double):this
-20 (-71.43% of base) : Microsoft.Extensions.FileProviders.Physical.dasm - Microsoft.Extensions.FileProviders.PhysicalFileProvider:set_UseActivePolling(bool):this
-20 (-71.43% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_DateFormatHandling(int):this
-20 (-71.43% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_DateParseHandling(int):this
-20 (-71.43% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_DateTimeZoneHandling(int):this
-20 (-71.43% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_FloatFormatHandling(int):this
-20 (-71.43% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_Formatting(int):this
-40 (-65.57% of base) : System.Collections.Immutable.dasm - System.Collections.HashHelpers:get_Primes():System.ReadOnlySpan`1[int]
-40 (-65.57% of base) : System.Configuration.ConfigurationManager.dasm - System.Configuration.XmlUtil:get_PositionOffset():System.ReadOnlySpan`1[int]
-40 (-65.57% of base) : System.Reflection.Metadata.dasm - System.Reflection.Metadata.Ecma335.HasCustomAttributeTag:get_TagToTokenTypeArray():System.ReadOnlySpan`1[uint]
-40 (-65.57% of base) : System.Reflection.Metadata.dasm - System.Reflection.Metadata.Ecma335.HasCustomDebugInformationTag:get_TagToTokenTypeArray():System.ReadOnlySpan`1[uint]
-64 (-64.65% of base) : System.Private.DataContractSerialization.dasm - System.Runtime.Serialization.ObjectToIdCache:GetPrime(int):int
-20 (-64.52% of base) : System.Composition.Convention.dasm - System.Composition.Convention.ImportConventionBuilder:AsMany(bool):System.Composition.Convention.ImportConventionBuilder:this
-20 (-62.50% of base) : System.Composition.Convention.dasm - System.Composition.Convention.ImportConventionBuilder:AsMany():System.Composition.Convention.ImportConventionBuilder:this
-17 (-60.71% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.JsonSerializerSettings:set_FloatParseHandling(int):this
9532 total methods with Code Size differences (3046 improved, 6486 regressed), 256068 unchanged. |
|
||
printf("\n"); | ||
printf(" "); | ||
printIndent(indentStack); | ||
printf(" %-6s V%02u.%s (offs=0x%02x) -> ", varTypeName(fieldVarDsc->TypeGet()), tree->GetLclNum(), | ||
fieldName, fieldVarDsc->lvFldOffset); | ||
printf(" %-6s %s -> ", varTypeName(fieldVarDsc->TypeGet()), fieldVarDsc->lvReason); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is switched to use lvReason
that already contains a description of promoted fields of similar nature, to avoid the use of the field above.
// TODO-Quirk: The old logic disallowed promotion for "custom layout" HFAs. | ||
// The equivalent check now is the following, but it is quite meaningless. | ||
if (treeNodes[0].hasSignificantPadding && compiler->IsHfa(typeHnd)) | ||
{ | ||
return CanConstructAndPromoteField(&structPromotionInfo); | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove this in a follow-up. It requires fixing a small bug in LSRA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments
src/coreclr/inc/corinfo.h
Outdated
// | ||
// Parameters: | ||
// typeHnd - Handle of the type. | ||
// treeNodes - [out] Pointer to tree node entries to write. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically [in, out]
? Specifically, on entry it points to an array of CORINFO_TYPE_LAYOUT_NODE
memory with *numTreeNodes
elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see in the JIT you call this with an arbitrary array of 256 elements, and bail on numbers above that.
If a caller wanted to allocate exactly the right number of nodes, what would they do? Perhaps they could
call this with treeNodes == nullptr
and *numTreeNodes == 0
and on exit *numTreeNodes
would equal the size needed? But that is semantically questionable since *numTreeNodes
is "the number of entries written" which would have to be zero. So you'd have to iterate, sending larger and larger buffers to the API.
Should it be supported to get exactly the number needed in one call? Either here, or in a getTypeLayoutNodeCount
API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically
[in, out]
? Specifically, on entry it points to an array ofCORINFO_TYPE_LAYOUT_NODE
memory with*numTreeNodes
elements.
I'll add a comment to this regard.
I see in the JIT you call this with an arbitrary array of 256 elements, and bail on numbers above that.
If a caller wanted to allocate exactly the right number of nodes, what would they do? Perhaps they could
call this with treeNodes == nullptr and *numTreeNodes == 0 and on exit *numTreeNodes would equal the size needed? But that is semantically questionable since *numTreeNodes is "the number of entries written" which would have to be zero. So you'd have to iterate, sending larger and larger buffers to the API.Should it be supported to get exactly the number needed in one call? Either here, or in a getTypeLayoutNodeCount API?
I picked the number by measuring how many nodes the largest structs in all our SPMI collections have, doubling it, and rounding it up (IIRC it was between 80-100 nodes).
The 256 limit on the JIT side also serves to limit ourselves from pathological cases, because it is very easy (especially with upcoming inline arrays) to create structs with tons and tons of nodes in its layout. For physical promotion hitting this limit will just result in slightly conservative behavior, where we will believe padding to be significant. For large structs that are only going to be partially promoted that's not going to be harmful to CQ. For regular promotion we have a natural limit of 9 nodes due to its restrictions. So I would say that for now this is ok, and if we end up in a situation where it is too conservative in physical promotion we can look into improving it (IMO, a more preferable design in that situation might be callback based, e.g. walkTypeLayout
-- but not sure we have much prior art to that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For very large structs do you envision some way for the jit to indicate priority, eg from some prior analysis we see the field at offset 0xNNN is important and so we'd like to make sure the layout describes it explicitly, but that some other fields are not interesting and can just be treated as significant padding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the API could take a range to return fields in, though then I think again the callback approach would be more flexible and with fewer downsides.
The actual "field type" parts are not used by physical promotion, so if regular promotion didn't exist this API would be quite a bit simpler (returning just a flat array of the significant segments). But for regular promotion it would technically be fine if it picked out a set of up to 4 fields it is interested in and only tried to promote these, though of course we would end up with dependent promotion a lot of the time.
@@ -4735,6 +4735,86 @@ CORINFO_FIELD_HANDLE MethodContext::repGetFieldInClass(CORINFO_CLASS_HANDLE clsH | |||
return result; | |||
} | |||
|
|||
void MethodContext::recGetTypeLayout(GetTypeLayoutResult result, CORINFO_CLASS_HANDLE typeHnd, CORINFO_TYPE_LAYOUT_NODE* nodes, size_t numNodes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it confusing that this takes size_t numNodes
instead of size_t* numNodes
like the API itself? (although presumably it shouldn't alter the number)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I initially had it as the pointer but realized this shouldn't be modified by the recording part, and changed it. I think I'll leave it like that.
src/coreclr/inc/corinfo.h
Outdated
// | ||
// Parameters: | ||
// typeHnd - Handle of the type. | ||
// treeNodes - [out] Pointer to tree node entries to write. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For very large structs do you envision some way for the jit to indicate priority, eg from some prior analysis we see the field at offset 0xNNN is important and so we'd like to make sure the layout describes it explicitly, but that some other fields are not interesting and can just be treated as significant padding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed the VM and CrossGen2/NativeAOT specific changes, and they look good to me. I have not reviewed any of the changes in the JIT itself.
Returning the input type handle back to the JIT is ok. That means the type handle is the direct type of an IL parameter, which we know is encodable.
I ran superpmi-collect for a special version of this branch that runs both promotions (to make sure all the data is available in the collections). Then I was able to use SPMI to get diffs for all other platforms. I checked disasm for win-x64, linux-x64, win-arm64, linux-arm64, and win-x86 and confirmed for all of these that this does not have any diffs in the non crossgen2 collections. For the crossgen2 collections I will post the diffs, but first after I recollect them with one fix: I noticed that we stopped allowing normal promotion of vector structs since it bails out on the CG2 side. That promotion should be ok to do, so I have refined the check to allow it and will rerun diffs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM
Diffs. As mentioned above most of the regressions are from this disabling last-use copy omission optimization, and also some from #88086. Also some of the usual code size increases around promotion are seen, like block copies being turned into individual field copies which may take bigger code. We might consider separately if we should try to tune our promotion heuristics for CG2 since it seems like there may be some potential code size savings in doing so. (Diffs may look small, but keep in mind these are diffs from a single collection) |
Rework the communication so that the JIT asks the EE for struct field related information relevant to promotion in a single JIT-EE call of a new function called getTypeLayout. Crossgen2 can then more easily provide the information that the JIT is allowed to depend on.
As a side effect, removes CORINFO_FLG_CUSTOMLAYOUT (which fixes #71711) and CORINFO_FLG_DONT_DIG_FIELDS.
Fix #85511
Fix #71711
This also makes physical promotion more precise with regards to padding that can be skipped as part of block operations, since we now recursively consider padding in sub structures as insignificant.
See my comment below for some more information.
Note: I previous had a PR that also enabled recursive struct promotion together with this, but I think that needs a separate investigation of the diffs to allow.