Skip to content
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

[RyuJIT] Make casthelpers cold for sealed classes #49295

Merged
merged 3 commits into from
Mar 10, 2021

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Mar 8, 2021

string  Test_sealed(object o) => (string)o;
Program Test(object o) => (Program)o;


public class Program { } // not sealed

Currently we optimize such casts in JIT to the following:

if (o == null)
    return null;
else if (GetMethodTable(o) == %pMT%)
    return o;
else
    return CORINFO_HELP_CHKCASTCLASS_SPECIAL;

In case of "sealed" classes that CORINFO_HELP_CHKCASTCLASS_SPECIAL is only used to throw InvalidCastException for cases when the input object is of a wrong type, so we can mark the whole block as rarely-executed.

; Method Pr:Test_sealed(System.Object):System.String:this
G_M52918_IG01:
       sub      rsp, 40
G_M52918_IG02:
       mov      rax, rdx
       test     rax, rax
       je       SHORT G_M52918_IG04
G_M52918_IG03:
       mov      rcx, 0xD1FFAB1E
       cmp      qword ptr [rax], rcx
       jne      SHORT G_M52918_IG05
G_M52918_IG04:
       add      rsp, 40
       ret      
G_M52918_IG05:
       call     CORINFO_HELP_CHKCASTCLASS_SPECIAL
       int3     
; Total bytes of code: 38



; Method Pr:Test(System.Object):Program:this
G_M38393_IG01:
       sub      rsp, 40
G_M38393_IG02:
       mov      rax, rdx
       test     rax, rax
       je       SHORT G_M38393_IG05
G_M38393_IG03:
       mov      rcx, 0xD1FFAB1E
       cmp      qword ptr [rax], rcx
       je       SHORT G_M38393_IG05
G_M38393_IG04:
       call     CORINFO_HELP_CHKCASTCLASS_SPECIAL
G_M38393_IG05:
       nop      
G_M38393_IG06:
       add      rsp, 40
       ret      
; Total bytes of code: 38

Jit-diff:

PMI CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for  default jit

Summary of Code Size diffs:
(Lower is better)

Total bytes of base: 53833604
Total bytes of diff: 53849742
Total bytes of delta: 16138 (0.03% of base)
    diff is a regression.


Top file regressions (bytes):
       11545 : Microsoft.CodeAnalysis.VisualBasic.dasm (0.20% of base)
        3738 : Microsoft.CodeAnalysis.CSharp.dasm (0.08% of base)
         759 : CommandLine.dasm (0.15% of base)
         474 : System.Private.Xml.dasm (0.01% of base)
         474 : System.Data.Common.dasm (0.03% of base)
         332 : System.DirectoryServices.dasm (0.08% of base)
         204 : Microsoft.CSharp.dasm (0.05% of base)
         199 : System.Configuration.ConfigurationManager.dasm (0.06% of base)
          82 : Newtonsoft.Json.Bson.dasm (0.09% of base)
          76 : System.Management.dasm (0.02% of base)
          71 : System.Data.Odbc.dasm (0.04% of base)
          70 : System.Threading.Tasks.Parallel.dasm (0.03% of base)
          69 : Microsoft.VisualBasic.Core.dasm (0.01% of base)
          61 : System.Diagnostics.EventLog.dasm (0.07% of base)
          58 : System.Linq.Expressions.dasm (0.01% of base)
          49 : System.DirectoryServices.AccountManagement.dasm (0.01% of base)
          39 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (0.00% of base)
          38 : System.IO.Packaging.dasm (0.04% of base)
          24 : System.Diagnostics.PerformanceCounter.dasm (0.03% of base)
          24 : Microsoft.Extensions.FileProviders.Physical.dasm (0.13% of base)

Top file improvements (bytes):
        -909 : System.Threading.Tasks.Dataflow.dasm (-0.09% of base)
        -638 : FSharp.Core.dasm (-0.02% of base)
        -118 : Newtonsoft.Json.dasm (-0.01% of base)
         -75 : System.Private.CoreLib.dasm (-0.00% of base)
         -54 : System.DirectoryServices.Protocols.dasm (-0.06% of base)
         -52 : System.Collections.dasm (-0.01% of base)
         -49 : System.ComponentModel.TypeConverter.dasm (-0.02% of base)
         -48 : System.Runtime.Serialization.Formatters.dasm (-0.05% of base)
         -43 : xunit.runner.utility.netcoreapp10.dasm (-0.02% of base)
         -37 : System.Collections.Specialized.dasm (-0.14% of base)
         -35 : System.Security.AccessControl.dasm (-0.04% of base)
         -32 : System.ObjectModel.dasm (-0.03% of base)
         -30 : System.IO.Pipelines.dasm (-0.04% of base)
         -28 : System.Net.Quic.dasm (-0.04% of base)
         -27 : System.Resources.Extensions.dasm (-0.08% of base)
         -27 : System.Security.Cryptography.X509Certificates.dasm (-0.02% of base)
         -26 : System.Data.OleDb.dasm (-0.01% of base)
         -22 : System.Speech.dasm (-0.01% of base)
         -18 : System.Net.HttpListener.dasm (-0.01% of base)
         -17 : System.Private.DataContractSerialization.dasm (-0.00% of base)

100 total files with Code Size differences (46 improved, 54 regressed), 171 unchanged.

Top method regressions (bytes):
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,__Canon):Nullable`1:this
         812 ( 9.00% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,ubyte):Nullable`1:this
         812 ( 9.00% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,short):Nullable`1:this
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,int):Nullable`1:this
         812 ( 7.50% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,Vector`1):Nullable`1:this
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,long):Nullable`1:this
         812 ( 8.84% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,Nullable`1):Nullable`1:this
         810 ( 8.97% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,double):Nullable`1:this
         289 ( 3.12% of base) : CommandLine.dasm - ResultExtensions:Flatten(Result`2):Result`2 (8 methods)
         276 ( 8.32% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:Visit(BoundNode,Vector`1):Nullable`1:this
         248 (16.40% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - StateMachineMethodToClassRewriter:TryUnwrapBoundStateMachineScope(byref,byref):bool:this (8 methods)
         230 ( 8.12% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:Visit(BoundNode,Nullable`1):Nullable`1:this
         228 ( 8.20% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:Visit(BoundNode,ubyte):Nullable`1:this
         228 ( 8.20% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:Visit(BoundNode,short):Nullable`1:this
         185 ( 3.18% of base) : CommandLine.dasm - <>c__13`2:<Collect>b__13_0(Result`2,Result`2):Result`2:this (8 methods)
         152 ( 0.94% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - MethodToClassRewriter`1:RewriteBlock(BoundBlock,ArrayBuilder`1,ArrayBuilder`1):BoundBlock:this (8 methods)
         114 ( 2.48% of base) : System.Data.Common.dasm - SqlConvert:ChangeType2(Object,int,Type,IFormatProvider):Object
         105 ( 1.46% of base) : CommandLine.dasm - Trial:Collect(IEnumerable`1):Result`2 (8 methods)
         105 ( 1.61% of base) : CommandLine.dasm - ResultExtensions:Collect(IEnumerable`1):Result`2 (8 methods)
          93 ( 3.08% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Binder:BindExpression(ExpressionSyntax,bool,bool,bool,DiagnosticBag):BoundExpression:this

Top method improvements (bytes):
        -650 (-53.76% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - MethodStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,IdentifierTokenSyntax,TypeParameterListSyntax,ParameterListSyntax,SimpleAsClauseSyntax,HandlesClauseSyntax,ImplementsClauseSyntax):this
        -476 (-42.81% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - DeclareStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,KeywordSyntax,LiteralExpressionSyntax,KeywordSyntax,LiteralExpressionSyntax,ParameterListSyntax,SimpleAsClauseSyntax):this
        -336 (-38.31% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - PropertyStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,IdentifierTokenSyntax,ParameterListSyntax,AsClauseSyntax,EqualsValueSyntax,ImplementsClauseSyntax):this
        -297 (-42.13% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - DelegateStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,TypeParameterListSyntax,ParameterListSyntax,SimpleAsClauseSyntax):this
        -297 (-42.13% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - EventStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,ParameterListSyntax,SimpleAsClauseSyntax,ImplementsClauseSyntax):this
        -215 (-12.86% of base) : FSharp.Core.dasm - FSharpRef`1:CompareTo(Object,IComparer):int:this (8 methods)
        -163 (-4.38% of base) : System.Private.CoreLib.dasm - EventProvider:WriteEvent(byref,long,long,long,ref):bool:this
        -160 (-6.92% of base) : FSharp.Core.dasm - FSharpList`1:CompareTo(Object,IComparer):int:this (8 methods)
        -144 (-7.70% of base) : FSharp.Core.dasm - FSharpOption`1:CompareTo(Object,IComparer):int:this (8 methods)
        -112 (-7.87% of base) : System.Threading.Tasks.Dataflow.dasm - <>c:<.ctor>b__9_5(Task,Object):this (16 methods)
        -102 (-7.08% of base) : System.Threading.Tasks.Dataflow.dasm - <>c:<.ctor>b__9_6(Task,Object):this (16 methods)
         -99 (-8.61% of base) : Microsoft.CodeAnalysis.CSharp.dasm - SyntaxFactory:MethodDeclaration(SyntaxList`1,SyntaxTokenList,TypeSyntax,ExplicitInterfaceSpecifierSyntax,SyntaxToken,TypeParameterListSyntax,ParameterListSyntax,SyntaxList`1,BlockSyntax,ArrowExpressionClauseSyntax,SyntaxToken):MethodDeclarationSyntax
         -86 (-4.28% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - CodeGenerator:EmitExpressionCore(BoundExpression,bool):this
         -77 (-5.29% of base) : System.Private.CoreLib.dasm - UnicodeEncoding:GetCharCount(long,int,DecoderNLS):int:this
         -75 (-2.58% of base) : CommandLine.dasm - ParserResultExtensions:MapResult(ParserResult`1,Func`2,Func`2):Nullable`1 (16 methods)
         -72 (-13.74% of base) : System.Threading.Tasks.Dataflow.dasm - <>c:<ProcessMessageWithTask>b__8_0(Task,Object):this (8 methods)
         -69 (-0.70% of base) : System.Data.Common.dasm - XmlTreeGen:SchemaTree(XmlDocument,XmlWriter,DataSet,DataTable,bool):this
         -63 (-6.29% of base) : Newtonsoft.Json.dasm - DataTableConverter:CreateRow(JsonReader,DataTable,JsonSerializer)
         -62 (-3.52% of base) : System.Private.Xml.dasm - XmlSerializationWriterCodeGen:WritePrimitive(String,String,String,Object,String,TypeMapping,bool,bool,bool):this
         -62 (-13.63% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Conversions:ClassifyExpressionReclassification(BoundExpression,TypeSymbol,Binder,byref):int

Top method regressions (percentages):
          36 (21.56% of base) : System.Private.CoreLib.dasm - MethodBuilder:Equals(Object):bool:this
          19 (19.59% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - NameSyntax:get_Arity():int:this
         248 (16.40% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - StateMachineMethodToClassRewriter:TryUnwrapBoundStateMachineScope(byref,byref):bool:this (8 methods)
          27 (15.79% of base) : System.Data.Common.dasm - DefaultValueTypeConverter:ConvertFrom(ITypeDescriptorContext,CultureInfo,Object):Object:this
          30 (15.38% of base) : Microsoft.CodeAnalysis.CSharp.dasm - MethodToStateMachineRewriter:TryUnwrapBoundStateMachineScope(byref,byref):bool:this
           9 (15.25% of base) : System.Linq.Expressions.dasm - LambdaCompiler:EmitRuntimeVariablesExpression(Expression):this
           7 (10.45% of base) : System.Private.CoreLib.dasm - <>c:<AssignCancellationToken>b__49_1(Object):this
          12 ( 9.76% of base) : System.Private.Xml.dasm - ReflectionXmlSerializationWriter:IsDefaultValue(TypeMapping,Object,Object,bool):bool:this
          19 ( 9.69% of base) : CommandLine.dasm - UnParserExtensions:IsEmpty(Object):bool
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,__Canon):Nullable`1:this
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,int):Nullable`1:this
         812 ( 9.17% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,long):Nullable`1:this
         812 ( 9.00% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,ubyte):Nullable`1:this
         812 ( 9.00% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,short):Nullable`1:this
         810 ( 8.97% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,double):Nullable`1:this
          20 ( 8.89% of base) : Microsoft.CodeAnalysis.CSharp.dasm - LocalRewriter:HasSideEffects(BoundStatement):bool
         812 ( 8.84% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:VisitInternal(BoundNode,Nullable`1):Nullable`1:this
          20 ( 8.47% of base) : Microsoft.CodeAnalysis.CSharp.dasm - CodeGenerator:IsRef(BoundExpression):bool:this
          20 ( 8.44% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - LocalRewriter:HasSideEffects(BoundStatement):bool
         276 ( 8.32% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - BoundTreeVisitor`2:Visit(BoundNode,Vector`1):Nullable`1:this

Top method improvements (percentages):
        -650 (-53.76% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - MethodStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,IdentifierTokenSyntax,TypeParameterListSyntax,ParameterListSyntax,SimpleAsClauseSyntax,HandlesClauseSyntax,ImplementsClauseSyntax):this
        -476 (-42.81% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - DeclareStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,KeywordSyntax,LiteralExpressionSyntax,KeywordSyntax,LiteralExpressionSyntax,ParameterListSyntax,SimpleAsClauseSyntax):this
        -297 (-42.13% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - DelegateStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,TypeParameterListSyntax,ParameterListSyntax,SimpleAsClauseSyntax):this
        -297 (-42.13% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - EventStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,KeywordSyntax,IdentifierTokenSyntax,ParameterListSyntax,SimpleAsClauseSyntax,ImplementsClauseSyntax):this
        -336 (-38.31% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - PropertyStatementSyntax:.ctor(ushort,ref,ref,SyntaxNode,GreenNode,KeywordSyntax,IdentifierTokenSyntax,ParameterListSyntax,AsClauseSyntax,EqualsValueSyntax,ImplementsClauseSyntax):this
         -20 (-28.57% of base) : Microsoft.CodeAnalysis.CSharp.dasm - SyntaxFactory:ParseSyntaxTree(SourceText,ParseOptions,String,CancellationToken):SyntaxTree
         -25 (-22.12% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - LocalRewriter:VisitObjectCreationInitializer(BoundObjectInitializerExpressionBase,BoundExpression,BoundExpression):BoundNode:this
         -15 (-22.06% of base) : System.Net.HttpListener.dasm - <>c:<GetClientCertificateAsync>b__42_0(AsyncCallback,Object):IAsyncResult:this
         -15 (-22.06% of base) : System.Net.HttpListener.dasm - <>c:<GetContextAsync>b__44_0(AsyncCallback,Object):IAsyncResult:this
         -21 (-20.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - CSharpSemanticModel:GetSpeculativeAliasInfoCore(int,SyntaxNode,int):IAliasSymbol:this
         -21 (-20.59% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - VBSemanticModel:GetSpeculativeAliasInfoCore(int,SyntaxNode,int):IAliasSymbol:this
         -12 (-20.00% of base) : System.Linq.Expressions.dasm - LambdaCompiler:EmitUnaryExpression(Expression,int):this
         -12 (-20.00% of base) : System.Linq.Expressions.dasm - LambdaCompiler:EmitConvertUnaryExpression(Expression,int):this
         -27 (-19.85% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Binder:WarnOnRecursiveAccess(BoundExpression,int,DiagnosticBag):this
         -44 (-19.56% of base) : Microsoft.CodeAnalysis.CSharp.dasm - LocalRewriter:AddObjectOrCollectionInitializers(byref,byref,ArrayBuilder`1,BoundExpression,BoundExpression):this
         -14 (-18.92% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - SyntaxFactory:ParseSyntaxTree(SourceText,ParseOptions,String,CancellationToken):SyntaxTree
         -17 (-17.00% of base) : Microsoft.CodeAnalysis.CSharp.dasm - MethodBodySemanticModel:Bind(Binder,CSharpSyntaxNode,DiagnosticBag):BoundNode:this
         -30 (-16.67% of base) : System.Runtime.Serialization.Formatters.dasm - ObjectReader:ParseMemberEnd(ParseRecord):this
         -10 (-16.39% of base) : System.DirectoryServices.dasm - SchemaNameCollection:System.Collections.IList.Insert(int,Object):this
         -44 (-16.36% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Binder:ComputeCaseClauseCondition(BoundCaseClause,byref,BoundExpression,DiagnosticBag):BoundCaseClause:this

6913 total methods with Code Size differences (2805 improved, 4108 regressed), 261298 unchanged.

Size improvement examples:
https://www.diffchecker.com/4hK014gu
https://www.diffchecker.com/tWgKrbyl (from my understanding - it merged cold tails)
but mostly it's a regression due to additional jumps (from cold blocks).

/cc @AndyAyersMS @VSadov

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 8, 2021
@SingleAccretion
Copy link
Contributor

I am wondering - could these cold blocks be safely marked as BBJ_THROW? This would presumably help to avoid the redundant jumps.

@EgorBo
Copy link
Member Author

EgorBo commented Mar 8, 2021

I am wondering - could these cold blocks be safely marked as BBJ_THROW? This would presumably help to avoid the redundant jumps.

heh, I'm testing it now :-)

@AndyAyersMS
Copy link
Member

I wonder if we should introduce a new throw helper for this?

Among other things we might be able to common the calls (tail merge) which might mitigate some of the code size increase you are seeing.

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

I wonder if we should introduce a new throw helper for this?

From my understanding, all of our corinfo throw helpers are paramterless - and this one requires arguments:

System.InvalidCastException: Unable to cast object of type 'Tests' to type 'System.String'

so we can't merge same call but with different arguments.

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

New diff is 16138 but most of it is:

       11545 : Microsoft.CodeAnalysis.VisualBasic.dasm (0.20% of base)
        3738 : Microsoft.CodeAnalysis.CSharp.dasm (0.08% of base)

for other stuff the diff is small because the change introduces a very little size diff (0-few bytes). e.g. for this case:

string Test(object o) => (string)o;

old codegen:

; Method Pr:Test_sealed(System.Object):System.String:this
G_M52918_IG01:
       sub      rsp, 40
G_M52918_IG02:
       mov      rax, rdx
       test     rax, rax
       je       SHORT G_M52918_IG05
G_M52918_IG03:
       mov      rcx, 0xD1FFAB1E
       cmp      qword ptr [rax], rcx
       je       SHORT G_M52918_IG05
G_M52918_IG04:
       call     CORINFO_HELP_CHKCASTCLASS_SPECIAL
G_M52918_IG05:
       nop      
G_M52918_IG06:
       add      rsp, 40
       ret      
; Total bytes of code: 38

new codegen:

; Method Pr:Test_sealed(System.Object):System.String:this
G_M52918_IG01:
       sub      rsp, 40
G_M52918_IG02:
       mov      rax, rdx
       test     rax, rax
       je       SHORT G_M52918_IG04
G_M52918_IG03:
       mov      rcx, 0xD1FFAB1E
       cmp      qword ptr [rax], rcx
       jne      SHORT G_M52918_IG05
G_M52918_IG04:
       add      rsp, 40
       ret      
G_M52918_IG05:
       call     CORINFO_HELP_CHKCASTCLASS_SPECIAL
       int3     
; Total bytes of code: 38

38 vs 38! (nop -> int3)

@AndyAyersMS
Copy link
Member

So the size regressions in say BoundTreeVisitor`2:VisitInternal are from longer jumps?

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

So the size regressions in say BoundTreeVisitor`2:VisitInternal are from longer jumps?

Here is the diff: https://www.diffchecker.com/7cVv3EsU

I can take a look on why tails weren't merged or can file an issue for it and do it later if it already meets the bar to be merged as is now.

@AndyAyersMS
Copy link
Member

Presumably it is this method: https://github.com/dotnet/roslyn/blob/6da1274c9d24c2f90a48290394a951b23617f2a3/src/Compilers/CSharp/Portable/BoundTree/BoundTreeVisitors.cs#L30-L42

where all the as casts should succeed and so all those throw cases should go away. Can you look into a case like this and see why we can't clean it up?

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

Presumably it is this method: https://github.com/dotnet/roslyn/blob/6da1274c9d24c2f90a48290394a951b23617f2a3/src/Compilers/CSharp/Portable/BoundTree/BoundTreeVisitors.cs#L30-L42

where all the as casts should succeed and so all those throw cases should go away. Can you look into a case like this and see why we can't clean it up?

@AndyAyersMS no, it's a similar method but from VisualBasic 🙂 https://github.com/dotnet/roslyn/blob/6da1274c9d24c2f90a48290394a951b23617f2a3/src/Compilers/VisualBasic/Portable/BoundTree/BoundTreeVisitor.vb

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

Regarding the fgTailMergeThrows - it's too simple, works only for parameterless helper funcs (and it happens right after Global Morph) - I wonder if it makes sense to extend it and also run somewhere later after VN so we can use VN to compare complex trees. But I'd love to leave this PR as is in this case.

@AndyAyersMS
Copy link
Member

Seems like the BoundVisitor cases don't require tail merge though -- those residual helpers should get optimized away as it is the is guarding as pattern, right? Can you dig in and figure out why that's not happening?

@EgorBo
Copy link
Member Author

EgorBo commented Mar 9, 2021

Seems like the BoundVisitor cases don't require tail merge though -- those residual helpers should get optimized away as it is the is guarding as pattern, right? Can you dig in and figure out why that's not happening?

So the actual method from the diff is this one: https://github.com/dotnet/roslyn/blob/main/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb#L9290

it has a number of CType(variable, SomeRefClass) which are guarded by a custom enum (JIT doesn't know it relates to the underlying type) - so the cast helpers are valid.

Simplified sharplab repro: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AbEA3YaAuIAhgM4C2APgJJkAO0+JABAMoCeJ+MZAsAFD8ACgFdgGAJZgmAUQB2wskwByEACYwA0uNmr+TfQDFxMDKqqyAZhD36AglChE2tsGBgkSNpgFk2K9fxyqjLyvALhImKSTADCGKTMvv4wAPLAAFZeTFlZkRJSBsKyYPjiELI+bIXFABSyaprawbbMyVo6aEwAQmwASjAWTPXqTC1MEBkwJQCUTKSVyWmZfPqrqywmU/ixpDBDDe26K2sn+jG7ygdNAHRJDdnHp09M/fjCUBUxACpstDB1DU6d3US2mWWe5xIe2kGCh4Oeq1e7wqKnwAAttABzeH6IKsTYlLJ46olMqyHKPB54uIJIA==

@AndyAyersMS
Copy link
Member

guarded by a custom enum

Got it. Thanks.

@EgorBo EgorBo merged commit 016ec29 into dotnet:main Mar 10, 2021
thaystg added a commit to thaystg/runtime that referenced this pull request Mar 10, 2021
* upstream/main: (83 commits)
  Fix a crash in llvm if the sreg of a setret is not set because the methods ends with a throw. (dotnet#49122)
  [macOS-arm64] Disable failing libraries tests (dotnet#49400)
  improve PriorityQueue documentation (dotnet#49392)
  [wasm] Fix debugger tests (dotnet#49206)
  [mono] Fix the emission of EnumEqualityComparer instances into the corlib AOT image. (dotnet#49402)
  jitutils M2M renaming reaction (dotnet#49430)
  WinHttpHandler: Read HTTP/2 trailing headers
  [RyuJIT] Make casthelpers cold for sealed classes (dotnet#49295)
  JIT: Non-void ThrowHelpers (dotnet#48589)
  Update package index for servicing (dotnet#49417)
  Remove unnecessary check on polymorphic serialization (dotnet#48464)
  Remove release build cron triggers from jitstress jobs (dotnet#49333)
  [main] Update dependencies from dotnet/arcade dotnet/llvm-project dotnet/runtime-assets (dotnet#49359)
  Implement AppleCryptoNative_X509GetRawData using SecCertificateCopyData
  [AndroidCrypto] Support a zero-length salt for HMACs. (dotnet#49384)
  Use managed implementation of pbkdf2 for Android's one-shot implementation. (dotnet#49314)
  Make 303 redirects do GET like Net Framework (dotnet#49095)
  Make sure event generation is incremental (dotnet#48903)
  Add amd and Surface arm64 perf runs (dotnet#49389)
  Enregister EH var that are single def (dotnet#47307)
  ...
@JulieLeeMSFT JulieLeeMSFT added this to the 6.0.0 milestone Mar 23, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Apr 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants