Runtime: JIT: Intrinsify EqualityComparer<T>.Default.Equals and GetHashCode calls

Created on 10 Aug 2016  路  6Comments  路  Source: dotnet/runtime

_Extracted from New methods for EqualityComparer._

Tuples could directly benefit from that. As well as any code which gets IEqualityComparer<T> externally - it could devirtualize calls to Equals and GetHashCode if the instance passed in is EqualityComparer<T>.Default.

Quoting @jkotas :

The .NET Native compiler for UWP does similar transformation of EqualityComparer.Default.Equals to reduce binary size for full AOT. You can see the class library side of the implementation here: https://github.com/dotnet/corert/blob/master/src/System.Private.Reflection.Execution/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs. The compiler side of the implementation is closed source unfortunately, but there is no rocket science in it.
This optimization would make RyuJIT better AOT codegenerator for CoreRT project, closer to the .NET Native compiler for UWP compiler.

The beauty of doing this as JIT optimization is that it will kick in for all existing code, without any changes.

area-CodeGen-coreclr enhancement optimization tenet-performance

Most helpful comment

Am going to start in on this.

All 6 comments

Would be great to have this, although it may require duplicating some more logic with EqualityComparer.CreateComparer. +1

Does it have a chance to appear in 2.0?

I am not aware of anybody working on this right now, so it is pretty unlikely.

Am going to start in on this.

I have this partially working now, see master...AndyAyersMS:EqualityComparerDefault
For
```C#
public static bool Compare(ref ValueTuple a, ref ValueTuple b)
{
return a.Equals(b);
}

we now get the following code
```asm
; Total bytes of code 23, prolog size 0

G_M57469_IG02:
   mov      eax, dword ptr [rdx]
   mov      edx, dword ptr [rdx+4]
   cmp      dword ptr [rcx], eax
   jne      SHORT G_M57469_IG03
   cmp      dword ptr [rcx+4], edx
   sete     al
   movzx    rax, al
   jmp      SHORT G_M57469_IG04

G_M57469_IG03:
   xor      eax, eax

G_M57469_IG04:
   ret

instead of

; Total bytes of code 108, prolog size 7

G_M57469_IG01:
   push     rdi
   push     rsi
   push     rbx
   sub      rsp, 48
   mov      rsi, rcx

G_M57469_IG02:
   mov      edi, dword ptr [rdx]
   mov      ebx, dword ptr [rdx+4]
   mov      rcx, 0x7FFF427D3028
   mov      edx, 79
   call     CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS
   mov      rcx, 0x1EE27732820
   mov      rcx, gword ptr [rcx]
   mov      edx, dword ptr [rsi]
   mov      r8d, edi
   mov      rax, qword ptr [rcx]
   mov      rax, qword ptr [rax+72]
   call     qword ptr [rax+32] ;; virtual
   test     eax, eax
   je       SHORT G_M57469_IG03
   mov      rcx, 0x1EE27732820
   mov      rcx, gword ptr [rcx]
   mov      edx, dword ptr [rsi+4]
   mov      r8d, ebx
   mov      rax, qword ptr [rcx]
   mov      rax, qword ptr [rax+72]
   call     qword ptr [rax+32] ;; virtual
   jmp      SHORT G_M57469_IG04

G_M57469_IG03:
   xor      eax, eax

G_M57469_IG04:
   add      rsp, 48
   pop      rbx
   pop      rsi
   pop      rdi
   ret

This uses an explicit expansion of Equals by the jit when T is a simple integer type. It would be cleaner if the jit could determine what class Default exactly refers to, then regular devirt/inline could kick in and we'd handle all the methods on the comparer and use their actual implementations.

I'm not sure how to best go about doing that. It seems like the knowledge of this mapping might need to be hard coded on the VM side?

Also we might want to tone down struct promotion a bit, so we don't eagerly load all the fields like we do here. Or else move the loads closer to their uses....

I'm not sure how to best go about doing that. It seems like the knowledge of this mapping might need to be hard coded on the VM side?

Yes. .NET Native has some code for it - it is probably not 100% reusable for RyuJIT, but bits and pieces may be. As you have said, the basic idea is that the virtual comparer gets replaced by a concrete one - like https://github.com/dotnet/corert/blob/280f6a0e29954d31c94263d6137d215ca71282fd/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs#L155.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jchannon picture jchannon  路  3Comments

jzabroski picture jzabroski  路  3Comments

btecu picture btecu  路  3Comments

bencz picture bencz  路  3Comments

matty-hall picture matty-hall  路  3Comments