Open EgorBo opened 1 year ago
@vzarytovskii can F# here emit
call bool [System.Runtime]System.Type::op_Equality(class [System.Runtime]System.Type, class [System.Runtime]System.Type)
instead of
call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/HashCompare::GenericEqualityIntrinsic<class [System.Runtime]System.Type>(!!0, !!0
? Or otherwise we need to do special handling for GenericEqualityIntrinsic
in JIT
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak See info in area-owners.md if you want to be subscribed.
Author: | EgorBo |
---|---|
Assignees: | - |
Labels: | `area-CodeGen-coreclr` |
Milestone: | - |
https://github.com/dotnet/fsharp/issues/526 Same with >, >=, <, <= etc operators
By default F# =
evaluates structural equality so it will always go through these helpers.
Some relevant discussions (it's a known problem): https://github.com/dotnet/fsharp/issues/8447#issuecomment-583668989 https://github.com/dotnet/fsharp/issues/5019#issuecomment-392964318 https://github.com/dotnet/fsharp/issues/6228
I guess we can generate op_Equality for System.Type (and other known types like DateTime, TimeSpan, UtcDateTime, Range, Guid, etc).
@vzarytovskii afaik @TIHan mentioned at some point this is not sound due to System.Type
being a derivable type. We could limit that optimization to immediate invocations and comparisons on typeof instances though. I.e. arguments like (ty: Type) would still generate structural equality. For DateTime and other such non-collection structs I agree it should be entirely safe to generate op_Equality.
@vzarytovskii afaik @TIHan mentioned at some point this is not sound due to
System.Type
being a derivable type. We could limit that optimization to immediate invocations and comparisons on typeof instances though. I.e. arguments like (ty: Type) would still generate structural equality.
Yeah, and I think we do it in Type Providers ourselves, and yeah, I meant that we can limit it to the System.Type
only, and not derivatives.
Type testing at runtime is not needed in F#.
Is this still the case when (non-collectible) typeof
becoming constant at runtime?
Codegen for 8.0 RC 2:
; Program+Program.f()
; typeof<int> = typeof<float>
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^
mov rcx,offset MD_Microsoft.FSharp.Core.LanguagePrimitives+HashCompare.GenericEqualityIntrinsic[[System.Type, System.Private.CoreLib]](System.Type, System.Type)
mov rdx,19080205140
mov r8,19080205898
jmp qword ptr [7FFA6643F9F0]; Microsoft.FSharp.Core.LanguagePrimitives+HashCompare.GenericEqualityIntrinsic[[System.__Canon, System.Private.CoreLib]](System.__Canon, System.__Canon)
; Total bytes of code 36
GenericEqualityIntrinsic is still not inlined.
Is there any workaround or better way to do this if you have to compare many types?
let test myType =
if myType = typeof<bool> then ...
elif myType = typeof<float> then ...
elif myType = typeof<ValueOption<decimal>> then ...
elif ...
The following F# snippet:
Emits this IL:
and this codegen:
expected codegen: