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

JIT: Drop redundant static initializations from (Equality)Comparer<T>.Default #50446

Merged
merged 16 commits into from
Jul 8, 2021

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Mar 30, 2021

Implements #48358

void Test(int x)
{
    IEqualityComparer<int> comparer = EqualityComparer<int>.Default;
    for (int i = 0; i < 100; i++)
    {
        if (comparer.Equals(i, x))
            Console.WriteLine(i);
    }
}

Current codegen (tier1, bypassed tier0 due to loop):

G_M52364_IG01:             
       57                   push     rdi
       56                   push     rsi
       53                   push     rbx
       4883EC20             sub      rsp, 32
       8BF2                 mov      esi, edx
G_M52364_IG02:             
       48B92800E7CFF97F0000 mov      rcx, 0x7FF9CFE70028
       BA13000000           mov      edx, 19
       E83362215F           call     CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS
       48B9902DCCC83B020000 mov      rcx, 0x23BC8CC2D90
       488B39               mov      rdi, gword ptr [rcx]
       33DB                 xor      ebx, ebx
G_M52364_IG03:             
       8BCB                 mov      ecx, ebx
       393F                 cmp      dword ptr [rdi], edi
       3BCE                 cmp      ecx, esi
       0F94C1               sete     cl
       0FB6C9               movzx    rcx, cl
       85C9                 test     ecx, ecx
       7407                 je       SHORT G_M52364_IG05
G_M52364_IG04:              
       8BCB                 mov      ecx, ebx
       E885EBFFFF           call     System.Console:WriteLine(int)
G_M52364_IG05:              
       FFC3                 inc      ebx
       83FB64               cmp      ebx, 100
       7CE2                 jl       SHORT G_M52364_IG03
G_M52364_IG06:              
       4883C420             add      rsp, 32
       5B                   pop      rbx
       5E                   pop      rsi
       5F                   pop      rdi
       C3                   ret      
; Total bytes of code 82

NOTE: ^ Equals is inlined (with help of #48279) but there is some redundant mess (static initialization + nullcheck for field).

New codegen:

G_M52364_IG01:           
       57                   push     rdi
       56                   push     rsi
       4883EC28             sub      rsp, 40
       8BF2                 mov      esi, edx
G_M52364_IG02:         
       33FF                 xor      edi, edi
G_M52364_IG03:              
       8BCF                 mov      ecx, edi
       3BCE                 cmp      ecx, esi
       0F94C1               sete     cl
       0FB6C9               movzx    rcx, cl
       85C9                 test     ecx, ecx
       7407                 je       SHORT G_M52364_IG05
G_M52364_IG04:            
       8BCF                 mov      ecx, edi
       E8A9EBFFFF           call     System.Console:WriteLine(int)
G_M52364_IG05:            
       FFC7                 inc      edi
       83FF64               cmp      edi, 100
       7CE4                 jl       SHORT G_M52364_IG03
G_M52364_IG06:          
       4883C428             add      rsp, 40
       5E                   pop      rsi
       5F                   pop      rdi
       C3                   ret      
; Total bytes of code 45

It looks to me it's easier to just not inline get_Default so we'll have a named-intrinsic always available (instead of COMMA(cctor, IND(FLD_ADDR))) so we can always query its class handle via gtGetClassHandle (see this) or drop the whole call if we see its return value is not used anywhere.

It should allow us to remove workaround such as this one and a similar one in the PriorityQueue.

jit-diff (-f --pmi)

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: 53037241
Total bytes of diff: 53001399
Total bytes of delta: -35842 (-0.07% of base)
    diff is an improvement.


Top file regressions (bytes):
        2193 : CommandLine.dasm (0.44% of base)
         387 : System.Composition.TypedParts.dasm (0.87% of base)
         387 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (0.01% of base)
         258 : xunit.execution.dotnet.dasm (0.11% of base)
         129 : xunit.core.dasm (0.18% of base)
         129 : System.Linq.Queryable.dasm (0.04% of base)
         117 : Microsoft.CodeAnalysis.dasm (0.01% of base)
          84 : Microsoft.CSharp.dasm (0.02% of base)

Top file improvements (bytes):
      -15107 : System.Collections.Immutable.dasm (-1.14% of base)
       -7373 : System.Collections.dasm (-1.28% of base)
       -4926 : System.Linq.Parallel.dasm (-0.24% of base)
       -3791 : System.Private.CoreLib.dasm (-0.08% of base)
       -2100 : System.Data.Common.dasm (-0.14% of base)
       -1919 : System.Linq.dasm (-0.19% of base)
       -1016 : System.Linq.Expressions.dasm (-0.13% of base)
        -767 : System.Collections.Concurrent.dasm (-0.20% of base)
        -699 : Newtonsoft.Json.dasm (-0.08% of base)
        -475 : System.Text.Json.dasm (-0.08% of base)
        -374 : xunit.assert.dasm (-0.27% of base)
        -337 : Microsoft.CodeAnalysis.CSharp.dasm (-0.01% of base)
        -262 : Microsoft.CodeAnalysis.VisualBasic.dasm (-0.00% of base)
        -175 : Microsoft.Diagnostics.FastSerialization.dasm (-0.16% of base)
        -175 : System.ObjectModel.dasm (-0.16% of base)
         -30 : System.Text.RegularExpressions.dasm (-0.01% of base)

24 total files with Code Size differences (16 improved, 8 regressed), 247 unchanged.

Top method regressions (bytes):
         120 (30.77% of base) : System.Private.CoreLib.dasm - Nullable:Equals(Nullable`1,Nullable`1):bool (6 methods)
         112 (17.69% of base) : System.Private.CoreLib.dasm - ValueTask`1:Equals(ValueTask`1):bool:this (8 methods)
          84 ( 8.08% of base) : Microsoft.CodeAnalysis.CSharp.dasm - <>f__AnonymousType0`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : Microsoft.CodeAnalysis.CSharp.dasm - <>f__AnonymousType1`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType0`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType3`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType4`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType5`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType7`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType8`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType9`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType10`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType11`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType12`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType13`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType14`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType15`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType16`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType17`2:Equals(Object):bool:this (8 methods)
          84 ( 8.08% of base) : CommandLine.dasm - <>f__AnonymousType18`2:Equals(Object):bool:this (8 methods)

Top method improvements (bytes):
       -1568 (-3.00% of base) : System.Linq.Parallel.dasm - IntersectQueryOperator`1:WrapPartitionedStreamHelper(PartitionedStream`2,PartitionedStream`2,IPartitionedStreamRecipient`1,CancellationToken):this (64 methods)
       -1400 (-2.21% of base) : System.Linq.Parallel.dasm - UnionQueryOperator`1:WrapPartitionedStreamFixedBothTypes(PartitionedStream`2,PartitionedStream`2,IPartitionedStreamRecipient`1,int,CancellationToken):this (64 methods)
       -1400 (-21.45% of base) : System.Data.Common.dasm - EnumerableRowCollection`1:AddSortExpression(Func`2,bool,bool):this (64 methods)
        -468 (-1.73% of base) : System.Linq.dasm - Enumerable:Min(IEnumerable`1,Func`2):Nullable`1 (48 methods)
        -468 (-1.54% of base) : System.Linq.dasm - Enumerable:Max(IEnumerable`1,Func`2):Nullable`1 (48 methods)
        -407 (-14.07% of base) : System.Collections.dasm - PriorityQueue`2:MoveDownDefaultComparer(ValueTuple`2,int):this (8 methods)
        -376 (-34.00% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(KeyValuePair`2):bool:this (8 methods)
        -375 (-18.03% of base) : System.Collections.Immutable.dasm - ImmutableDictionary`2:WithComparers(IEqualityComparer`1,IEqualityComparer`1):ImmutableDictionary`2:this (8 methods)
        -375 (-11.15% of base) : System.Collections.Immutable.dasm - ImmutableSortedDictionary`2:WithComparers(IComparer`1,IEqualityComparer`1):ImmutableSortedDictionary`2:this (8 methods)
        -375 (-28.54% of base) : System.Collections.Immutable.dasm - ImmutableSortedDictionary`2:.ctor(IComparer`1,IEqualityComparer`1):this (8 methods)
        -375 (-19.35% of base) : System.Collections.Immutable.dasm - Builder:.ctor(ImmutableSortedDictionary`2):this (8 methods)
        -368 (-27.46% of base) : System.Collections.dasm - SortedList`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(KeyValuePair`2):bool:this (8 methods)
        -360 (-19.67% of base) : System.Collections.dasm - SortedDictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(KeyValuePair`2):bool:this (8 methods)
        -355 (-17.03% of base) : System.Linq.Expressions.dasm - CollectionExtensions:ListEquals(ReadOnlyCollection`1,ReadOnlyCollection`1):bool (8 methods)
        -352 (-24.24% of base) : System.Collections.dasm - SortedList`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(KeyValuePair`2):bool:this (8 methods)
        -352 (-26.97% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(KeyValuePair`2):bool:this (8 methods)
        -350 (-39.64% of base) : Newtonsoft.Json.dasm - BidirectionalDictionary`2:.ctor():this (8 methods)
        -350 (-3.60% of base) : System.Linq.dasm - Enumerable:SequenceEqual(IEnumerable`1,IEnumerable`1,IEqualityComparer`1):bool (8 methods)
        -350 (-39.28% of base) : System.Collections.dasm - SortedSet`1:CreateSetComparer():IEqualityComparer`1 (8 methods)
        -350 (-35.46% of base) : System.Collections.dasm - SortedSet`1:CreateSetComparer(IEqualityComparer`1):IEqualityComparer`1 (8 methods)

Top method regressions (percentages):
          18 (75.00% of base) : System.Private.CoreLib.dasm - NonRandomizedStringEqualityComparer:.ctor(SerializationInfo,StreamingContext):this
           8 (53.33% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(int):bool:this (2 methods)
           8 (47.06% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(long):bool:this (2 methods)
           8 (42.11% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(ubyte):bool:this (2 methods)
           8 (38.10% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(short):bool:this (2 methods)
         120 (30.77% of base) : System.Private.CoreLib.dasm - Nullable:Equals(Nullable`1,Nullable`1):bool (6 methods)
           8 (20.51% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(Vector`1):bool:this (2 methods)
          56 (18.92% of base) : System.Private.CoreLib.dasm - ValueTuple`1:Equals(ValueTuple`1):bool:this (8 methods)
         112 (17.69% of base) : System.Private.CoreLib.dasm - ValueTask`1:Equals(ValueTask`1):bool:this (8 methods)
           8 (16.33% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(double):bool:this (2 methods)
          42 (13.29% of base) : System.Private.CoreLib.dasm - EqualityComparer`1:get_Default():EqualityComparer`1 (8 base, 9 diff methods)
           8 (12.31% of base) : Microsoft.CodeAnalysis.dasm - Collection`1:Contains(Nullable`1):bool:this (2 methods)
          80 (11.56% of base) : System.Private.CoreLib.dasm - Nullable:Compare(Nullable`1,Nullable`1):int (6 methods)
          84 (10.49% of base) : Microsoft.CSharp.dasm - KeyPair`2:Equals(KeyPair`2):bool:this (8 methods)
          84 (10.49% of base) : System.Private.CoreLib.dasm - ValueTuple`2:Equals(ValueTuple`2):bool:this (8 methods)
           9 ( 9.09% of base) : Microsoft.CodeAnalysis.dasm - MergedAliases:AddNonIncluded(ArrayBuilder`1,String)
          45 ( 8.69% of base) : Microsoft.CodeAnalysis.CSharp.dasm - <>f__AnonymousType0`2:GetHashCode():int:this (8 methods)
          45 ( 8.69% of base) : Microsoft.CodeAnalysis.CSharp.dasm - <>f__AnonymousType1`2:GetHashCode():int:this (8 methods)
          45 ( 8.69% of base) : CommandLine.dasm - <>f__AnonymousType0`2:GetHashCode():int:this (8 methods)
          45 ( 8.69% of base) : CommandLine.dasm - <>f__AnonymousType3`2:GetHashCode():int:this (8 methods)

Top method improvements (percentages):
        -216 (-52.94% of base) : System.Collections.dasm - PriorityQueue`2:get_Comparer():IComparer`1:this (8 methods)
         -53 (-46.90% of base) : System.Collections.dasm - LinkedList`1:Find(long):LinkedListNode`1:this
         -51 (-45.95% of base) : System.Collections.dasm - LinkedList`1:Find(int):LinkedListNode`1:this
        -178 (-45.52% of base) : xunit.assert.dasm - Assert:StrictEqual(Vector`1,Vector`1)
         -43 (-44.79% of base) : System.Private.CoreLib.dasm - <>c:<CreateManifestString>b__18_1(KeyValuePair`2,KeyValuePair`2):int:this
         -51 (-43.59% of base) : System.Collections.dasm - LinkedList`1:FindLast(ubyte):LinkedListNode`1:this
        -175 (-43.32% of base) : System.Collections.dasm - TreeSet`1:.ctor():this (8 methods)
         -25 (-43.10% of base) : xunit.assert.dasm - Assert:StrictEqual(int,int)
         -25 (-43.10% of base) : xunit.assert.dasm - Assert:NotStrictEqual(int,int)
         -79 (-42.93% of base) : System.Collections.dasm - LinkedList`1:FindLast(double):LinkedListNode`1:this
         -25 (-41.67% of base) : Newtonsoft.Json.dasm - CollectionUtils:AddDistinct(IList`1,int):bool
        -200 (-41.67% of base) : System.Collections.dasm - PriorityQueue`2:InitializeComparer(IComparer`1):IComparer`1 (8 methods)
         -25 (-41.67% of base) : System.Collections.Immutable.dasm - ImmutableList`1:IndexOf(int):int:this
         -63 (-41.45% of base) : System.Collections.dasm - LinkedList`1:Find(double):LinkedListNode`1:this
         -53 (-41.09% of base) : System.Collections.dasm - LinkedList`1:FindLast(long):LinkedListNode`1:this
         -25 (-40.32% of base) : Newtonsoft.Json.dasm - CollectionUtils:AddDistinct(IList`1,ubyte):bool
         -25 (-40.32% of base) : Newtonsoft.Json.dasm - CollectionUtils:AddDistinct(IList`1,short):bool
         -25 (-40.32% of base) : Newtonsoft.Json.dasm - CollectionUtils:AddDistinct(IList`1,long):bool
         -25 (-40.32% of base) : System.Collections.Immutable.dasm - ImmutableList`1:IndexOf(ubyte):int:this
         -25 (-40.32% of base) : System.Collections.Immutable.dasm - ImmutableList`1:IndexOf(short):int:this

683 total methods with Code Size differences (577 improved, 106 regressed), 267772 unchanged.

crossgen jit-diff:

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

Summary of Code Size diffs:
(Lower is better)

Total bytes of base: 33504668
Total bytes of diff: 33502640
Total bytes of delta: -2028 (-0.01% of base)
    diff is an improvement.


Top file improvements (bytes):
       -1922 : System.Private.CoreLib.dasm (-0.06% of base)
         -52 : CommandLine.dasm (-0.04% of base)
         -38 : System.Text.Json.dasm (-0.01% of base)
         -10 : Microsoft.CSharp.dasm (-0.00% of base)
          -4 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (-0.00% of base)
          -2 : Microsoft.CodeAnalysis.dasm (-0.00% of base)

6 total files with Code Size differences (6 improved, 0 regressed), 265 unchanged.

Top method regressions (bytes):
          54 ( 6.22% of base) : System.Private.CoreLib.dasm - EqualityComparer`1:get_Default():EqualityComparer`1 (35 base, 38 diff methods)
           7 ( 0.69% of base) : System.Private.CoreLib.dasm - Type:GetEnumData(byref,byref):this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`1:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`1:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`1:GetHashCode():int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`2:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`2:System.IComparable.CompareTo(Object):int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`2:GetHashCode():int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`3:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`3:System.IComparable.CompareTo(Object):int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`3:GetHashCode():int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`4:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`4:System.IComparable.CompareTo(Object):int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`4:GetHashCode():int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`5:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`5:System.IComparable.CompareTo(Object):int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`5:GetHashCode():int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`6:Equals(Object):bool:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`6:System.IComparable.CompareTo(Object):int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`6:GetHashCode():int:this

Top method improvements (bytes):
        -260 (-20.34% of base) : System.Private.CoreLib.dasm - ValueTuple`2:Equals(ValueTuple`2):bool:this (15 methods)
        -232 (-10.85% of base) : System.Private.CoreLib.dasm - ValueTuple`2:Equals(Object):bool:this (15 methods)
        -200 (-14.22% of base) : System.Private.CoreLib.dasm - ValueTuple`2:CompareTo(ValueTuple`2):int:this (15 methods)
        -180 (-6.41% of base) : System.Private.CoreLib.dasm - ValueTuple`2:System.IComparable.CompareTo(Object):int:this (15 methods)
        -160 (-9.38% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(long):bool:this (4 methods)
        -138 (-7.32% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(long,byref):bool:this (4 methods)
        -114 (-5.01% of base) : System.Private.CoreLib.dasm - Dictionary`2:TryInsert(long,__Canon,ubyte):bool:this (3 methods)
         -75 (-4.68% of base) : System.Private.CoreLib.dasm - Dictionary`2:FindValue(long):byref:this (4 methods)
         -74 (-6.32% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(KeyValuePair`2):bool:this (10 methods)
         -70 (-7.29% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(KeyValuePair`2):bool:this (10 methods)
         -52 (-16.67% of base) : System.Private.CoreLib.dasm - ValueTask`1:Equals(ValueTask`1):bool:this (3 methods)
         -51 (-9.66% of base) : System.Private.CoreLib.dasm - ValueTuple`3:Equals(ValueTuple`3):bool:this (4 methods)
         -47 (-5.82% of base) : System.Private.CoreLib.dasm - ValueTuple`3:Equals(Object):bool:this (4 methods)
         -42 (-6.45% of base) : System.Private.CoreLib.dasm - ValueTuple`3:CompareTo(ValueTuple`3):int:this (4 methods)
         -39 (-3.49% of base) : System.Private.CoreLib.dasm - ValueTuple`3:System.IComparable.CompareTo(Object):int:this (4 methods)
         -38 (-9.18% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(int):bool:this
         -38 (-0.44% of base) : System.Text.Json.dasm - JsonPropertyInfo`1:GetMemberAndWriteJson(Object,byref,Utf8JsonWriter):bool:this (20 methods)
         -34 (-4.60% of base) : System.Private.CoreLib.dasm - Dictionary`2:TryInsert(int,__Canon,ubyte):bool:this
         -33 (-1.26% of base) : System.Private.CoreLib.dasm - ArraySortHelper`1:Sort(Span`1,IComparer`1):this (13 methods)
         -33 (-1.00% of base) : System.Private.CoreLib.dasm - GenericArraySortHelper`1:Sort(Span`1,IComparer`1):this (12 methods)

Top method regressions (percentages):
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`2:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`3:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`4:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`5:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`6:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`7:GetHashCode():int:this
           7 (21.21% of base) : System.Private.CoreLib.dasm - Tuple`8:GetHashCode():int:this
           7 (20.59% of base) : System.Private.CoreLib.dasm - NonRandomizedStringEqualityComparer:.ctor(SerializationInfo,StreamingContext):this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`1:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`1:GetHashCode():int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`2:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`3:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`4:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`5:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`6:System.IComparable.CompareTo(Object):int:this
           7 (17.07% of base) : System.Private.CoreLib.dasm - Tuple`8:System.IComparable.CompareTo(Object):int:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`1:Equals(Object):bool:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`2:Equals(Object):bool:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`3:Equals(Object):bool:this
           7 (16.28% of base) : System.Private.CoreLib.dasm - Tuple`4:Equals(Object):bool:this

Top method improvements (percentages):
         -19 (-26.39% of base) : System.Private.CoreLib.dasm - <>c:<CreateManifestString>b__18_1(KeyValuePair`2,KeyValuePair`2):int:this
         -29 (-23.02% of base) : System.Private.CoreLib.dasm - Dictionary`2:ContainsValue(long):bool:this
         -27 (-21.77% of base) : System.Private.CoreLib.dasm - Dictionary`2:ContainsValue(int):bool:this
         -27 (-20.93% of base) : System.Private.CoreLib.dasm - Dictionary`2:ContainsValue(bool):bool:this
        -260 (-20.34% of base) : System.Private.CoreLib.dasm - ValueTuple`2:Equals(ValueTuple`2):bool:this (15 methods)
         -26 (-20.31% of base) : System.Private.CoreLib.dasm - Dictionary`2:ContainsValue(ushort):bool:this
         -52 (-16.67% of base) : System.Private.CoreLib.dasm - ValueTask`1:Equals(ValueTask`1):bool:this (3 methods)
        -200 (-14.22% of base) : System.Private.CoreLib.dasm - ValueTuple`2:CompareTo(ValueTuple`2):int:this (15 methods)
        -232 (-10.85% of base) : System.Private.CoreLib.dasm - ValueTuple`2:Equals(Object):bool:this (15 methods)
         -51 (-9.66% of base) : System.Private.CoreLib.dasm - ValueTuple`3:Equals(ValueTuple`3):bool:this (4 methods)
        -160 (-9.38% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(long):bool:this (4 methods)
         -38 (-9.18% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(int):bool:this
        -138 (-7.32% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(long,byref):bool:this (4 methods)
         -70 (-7.29% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(KeyValuePair`2):bool:this (10 methods)
         -31 (-6.71% of base) : System.Private.CoreLib.dasm - Dictionary`2:Remove(int,byref):bool:this
         -42 (-6.45% of base) : System.Private.CoreLib.dasm - ValueTuple`3:CompareTo(ValueTuple`3):int:this (4 methods)
        -180 (-6.41% of base) : System.Private.CoreLib.dasm - ValueTuple`2:System.IComparable.CompareTo(Object):int:this (15 methods)
         -74 (-6.32% of base) : System.Private.CoreLib.dasm - Dictionary`2:System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(KeyValuePair`2):bool:this (10 methods)
         -47 (-5.82% of base) : System.Private.CoreLib.dasm - ValueTuple`3:Equals(Object):bool:this (4 methods)
         -20 (-5.15% of base) : System.Private.CoreLib.dasm - Dictionary`2:FindValue(int):byref:this

91 total methods with Code Size differences (62 improved, 29 regressed), 201759 unchanged.

@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 30, 2021
@stephentoub
Copy link
Member

It should allow us to remove workaround such as this one and a similar one in the PriorityQueue.

Are you planning to do that in this PR? 😄

@EgorBo
Copy link
Member Author

EgorBo commented Mar 30, 2021

It should allow us to remove workaround such as this one and a similar one in the PriorityQueue.

Are you planning to do that in this PR? 😄

Yes but I want to see green CI first to make sure it doesn't crash anything 🙂

@EgorBo
Copy link
Member Author

EgorBo commented Apr 1, 2021

@dotnet/jit-contrib PTAL, failures are not related to this PR.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be 3 things going on here that are interesting. I would like you to think about how to handle each a bit more generally:

  • Avoiding extra work when repeatedly checking for named intrinsics. Seems like here we could mark call sites with failed lookups with some new call flag, and short-circuit future lookups if that flag was set.
  • Allowing some user methods to be considered "pure" or effectively pure. Instead of repeatedly analyzing for this we could also mark the call site or similar. Generalizing VN to handle arbitrary cases of pure user methods seems challenging though.
  • Deciding not to inline some pure functions if we suspect their results are not going to be used and the benefit of inlining them is marginal, so it is easy later on to dead call them.

@EgorBo
Copy link
Member Author

EgorBo commented Apr 5, 2021

  • Avoiding extra work when repeatedly checking for named intrinsics. Seems like here we could mark call sites with failed lookups with some new call flag, and short-circuit future lookups if that flag was set.

That flag is unset for most intrinsics, only just a few survive after impIntrinsic (literally just 5) - still makes sense to reset the flag once we handle those 5 I agree.

  • Allowing some user methods to be considered "pure" or effectively pure. Instead of repeatedly analyzing for this we could also mark the call site or similar. Generalizing VN to handle arbitrary cases of pure user methods seems challenging though.

I wonder if it's easier to do on the Roslyn side (however, I assume Roslyn doesn't want to do this kind of things for performance reasons - otherwise Nullability Analysis would be super powerful)

  • Deciding not to inline some pure functions if we suspect their results are not going to be used and the benefit of inlining them is marginal, so it is easy later on to dead call them.

it'd be nice to have! But first we need to make sure the function we're about to inline is pure (or contains "ignorable" side-effects) so basically solve the second question first.

@EgorBo
Copy link
Member Author

EgorBo commented Apr 7, 2021

@dotnet/jit-contrib PTAL

@EgorBo
Copy link
Member Author

EgorBo commented Apr 26, 2021

Ping @dotnet/jit-contrib

…comparer-live

# Conflicts:
#	src/coreclr/jit/gentree.h
@EgorBo
Copy link
Member Author

EgorBo commented Jun 14, 2021

@dotnet/jit-contrib @AndyAyersMS can anybody please take a look, thanks

@EgorBo
Copy link
Member Author

EgorBo commented Jul 5, 2021

@sandreenko @jakobbotsch could you please take a look?

Copy link
Member

@jakobbotsch jakobbotsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Can we get rid of the definition of GTF_CALL_M_HELPER_SPECIAL_DCE now?
Also remember to remove the workarounds that are no longer necessary.

@EgorBo EgorBo merged commit 46e5fe1 into dotnet:main Jul 8, 2021
EgorBo added a commit to EgorBo/runtime-1 that referenced this pull request Jul 27, 2021
EgorBo added a commit that referenced this pull request Jul 29, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 7, 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.

6 participants