diff --git a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs index 5c2e18b3382b65..f214dc095a84d5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs @@ -7,9 +7,13 @@ namespace System.Collections.Generic { public abstract partial class Comparer : IComparer, IComparer { + // This method is special cased in R2R, with its implementation replaced by IL helper + [Intrinsic] + private static Comparer Create() => (Comparer)ComparerHelpers.CreateDefaultComparer(typeof(T)); + // To minimize generic instantiation overhead of creating the comparer per type, we keep the generic portion of the code as small // as possible and define most of the creation logic in a non-generic class. - public static Comparer Default { [Intrinsic] get; } = (Comparer)ComparerHelpers.CreateDefaultComparer(typeof(T)); + public static Comparer Default { [Intrinsic] get; } = Create(); } internal sealed partial class EnumComparer : Comparer where T : struct, Enum diff --git a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs index 3fa3a14abffa30..d4e32bad8f97ae 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs @@ -8,9 +8,13 @@ namespace System.Collections.Generic { public abstract partial class EqualityComparer : IEqualityComparer, IEqualityComparer { + // This method is special cased in R2R, with its implementation replaced by IL helper + [Intrinsic] + private static EqualityComparer Create() => (EqualityComparer)ComparerHelpers.CreateDefaultEqualityComparer(typeof(T)); + // To minimize generic instantiation overhead of creating the comparer per type, we keep the generic portion of the code as small // as possible and define most of the creation logic in a non-generic class. - public static EqualityComparer Default { [Intrinsic] get; } = (EqualityComparer)ComparerHelpers.CreateDefaultEqualityComparer(typeof(T)); + public static EqualityComparer Default { [Intrinsic] get; } = Create(); } public sealed partial class GenericEqualityComparer : EqualityComparer where T : IEquatable? diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs index 5460cad265c0d6..7e1d4b59038743 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs @@ -120,6 +120,20 @@ private MethodIL TryGetPerInstantiationIntrinsicMethodIL(MethodDesc method) return InterlockedIntrinsics.EmitIL(_compilationModuleGroup, method); } + if (mdType.Namespace.SequenceEqual("System.Collections.Generic"u8)) + { + if (mdType.Name.SequenceEqual("Comparer`1"u8)) + { + if (method.Name.SequenceEqual("Create"u8)) + return ComparerIntrinsics.EmitComparerCreate(method); + } + else if (mdType.Name.SequenceEqual("EqualityComparer`1"u8)) + { + if (method.Name.SequenceEqual("Create"u8)) + return ComparerIntrinsics.EmitEqualityComparerCreate(method); + } + } + return null; }