Skip to content

RyuJIT: IsValueType and IsAssignableFrom optimizations aren't inlining friendly. #40381

Closed
@EgorBo

Description

@EgorBo

#1157 introduced a jit optimization to optimize typeof(X).IsValueType to true/false. However, it seems this optimization doesn't work with inlining (same for IsAssignableFrom), e.g.:

bool Test() => Foo(typeof(int));

bool Foo(Type t1) => t1.IsValueType;

Codegen for Test (with Foo inlined):

G_M31255_IG01:
       4883EC28             sub      rsp, 40
G_M31255_IG02:
       48B9A09BC9ECF87F0000 mov      rcx, 0x7FF8ECC99BA0
       E82D238D5F           call     CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
       488BC8               mov      rcx, rax
       48B8D8A8BEECF87F0000 mov      rax, 0x7FF8ECBEA8D8
       488B00               mov      rax, qword ptr [rax]
       3909                 cmp      dword ptr [rcx], ecx
G_M31255_IG03:
       4883C428             add      rsp, 40
       48FFE0               rex.jmp  rax

Expected codegen:

       mov      eax, 1   ;; return true
       ret  

the problem here is the fact that when we inline Foo we save typeof(int) into a temp variable (GT_LCL_VAR) and then importer is not able to optimize get_IsValueType because it expects input to be typeof(X) (CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) rather than an unknown local, here is the IR after inlining:

# var tmp = typeof(x);
*  ASG       ref   
+--*  LCL_VAR   ref    V02 tmp1         
\--*  CALL help ref    HELPER.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
   \--*  CNS_INT(h) long   0x7ff8ecc99ba0 class


# return tmp.IsValueType;
*  CALL void   System.RuntimeType.IsValueTypeImpl
\--*  LCL_VAR   ref    V02 tmp1  

if we could, instead of saving typeof(x) into a temp propogate it by value during inlining I believe we'd get:

*  CALL void   System.RuntimeType.IsValueTypeImpl
\--*  CALL help ref    HELPER.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
   \--*  CNS_INT(h) long   0x7ff8ecc99ba0 class

Other options: early CSE ? or when I import get_IsValueType and see LCL_VAR arg with lvSingleDef flag - can I quickly get its assignment node?

PS: the same issue prevents the new API Type.IsAssignableTo to be typeof(X) friendly since it uses IsAssignableFrom under the hood.

/cc @dotnet/jit-contrib

category:cq
theme:inlining
skill-level:expert
cost:large

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions