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

Unreachable try/catch not elided by JIT #9012

Closed
stephentoub opened this issue Sep 25, 2017 · 4 comments
Closed

Unreachable try/catch not elided by JIT #9012

stephentoub opened this issue Sep 25, 2017 · 4 comments
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI enhancement Product code improvement that does NOT require public API changes/additions optimization tenet-performance Performance related issue
Milestone

Comments

@stephentoub
Copy link
Member

Consider:

using System;

class Program
{
    static void Main()
    {
        Foo(42);
    }

    static void Foo<T>(T input)
    {
        if (typeof(T) == typeof(int))
        {
            Console.WriteLine(((int)(object)input).ToString());
        }
        else
        {
            try { Console.WriteLine("else"); }
            catch (Exception e) { Console.WriteLine(e); }
        }
    }
}

The JitDisasm for Foo is:

G_M46115_IG01:
       55                   push     rbp
       56                   push     rsi
       4883EC28             sub      rsp, 40
       488D6C2430           lea      rbp, [rsp+30H]
       488965F0             mov      qword ptr [rbp-10H], rsp
       8BF1                 mov      esi, ecx

G_M46115_IG02:
       E8AA5BFDFF           call     System.Globalization.NumberFormatInfo:get_CurrentInfo():ref
       4C8BC0               mov      r8, rax
       8BCE                 mov      ecx, esi
       33D2                 xor      rdx, rdx
       E8AE209D5F           call     System.Number:FormatInt32(int,ref,ref):ref
       488BC8               mov      rcx, rax
       E82EFCFFFF           call     System.Console:WriteLine(ref)
       90                   nop

G_M46115_IG03:
       488D65F8             lea      rsp, [rbp-08H]
       5E                   pop      rsi
       5D                   pop      rbp
       C3                   ret

G_M46115_IG04:
       CC                   int3

G_M46115_IG05:
       488D65F8             lea      rsp, [rbp-08H]
       5E                   pop      rsi
       5D                   pop      rbp
       C3                   ret

G_M46115_IG06:
       55                   push     rbp
       56                   push     rsi
       4883EC28             sub      rsp, 40
       488B6920             mov      rbp, qword ptr [rcx+32]
       48896C2420           mov      qword ptr [rsp+20H], rbp
       488D6D30             lea      rbp, [rbp+30H]

G_M46115_IG07:
       488BCA               mov      rcx, rdx
       E8FBFBFFFF           call     System.Console:WriteLine(ref)
       488D05D7FFFFFF       lea      rax, G_M46115_IG05

G_M46115_IG08:
       4883C428             add      rsp, 40
       5E                   pop      rsi
       5D                   pop      rbp
       C3                   ret

but if I remove the try/catch and just leave the Console.WriteLine from the try block:

using System;

class Program
{
    static void Main()
    {
        Foo(42);
    }

    static void Foo<T>(T input)
    {
        if (typeof(T) == typeof(int))
        {
            Console.WriteLine(((int)(object)input).ToString());
        }
        else
        {
            Console.WriteLine("else");
        }
    }
}

the else is removed as expected:

G_M46115_IG01:
       56                   push     rsi
       4883EC20             sub      rsp, 32
       8BF1                 mov      esi, ecx

G_M46115_IG02:
       E8B45BFDFF           call     System.Globalization.NumberFormatInfo:get_CurrentInfo():ref
       4C8BC0               mov      r8, rax
       8BCE                 mov      ecx, esi
       33D2                 xor      rdx, rdx
       E8B820A05F           call     System.Number:FormatInt32(int,ref,ref):ref
       488BC8               mov      rcx, rax
       E838FCFFFF           call     System.Console:WriteLine(ref)
       90                   nop

G_M46115_IG03:
       4883C420             add      rsp, 32
       5E                   pop      rsi
       C3                   ret

This is also impacting the ability for Foo to be inlined, i.e. even with AggressiveInlining it won't be inlined if the try/catch exists in the else branch.

cc: @AndyAyersMS

category:cq
theme:flowgraph
skill-level:intermediate
cost:small

@AndyAyersMS
Copy link
Member

The jit is super conservative right now and marks the first block in a try with BBF_DONT_REMOVE when processing the method EH clauses. This essentially ensures the first block in a try will remain in the method forever, even if it appears unreachable.

If we refactored some of the type equality optimizations so that they could be run directly from the importer via gtFoldExpr and friends, then in examples like the above, the jit would avoid importing the
code in the EH region all together, and perhaps this would sidestep the problem. It would also have a nice TP benefit as less code would be imported in cases that do extensive type specialization.

The jit rejects methods with EH clauses very early in its candidate screening. Even if we fix the issue above and EH goes away in the method "eventually", more work would be needed to unblock inlining these methods.

@stephentoub
Copy link
Member Author

Thanks, @AndyAyersMS.

@AndyAyersMS
Copy link
Member

Above example was fixed in dotnet/coreclr#14244, which also cleaned up some cases of AwaitUnsafeOnCompleted.

@ZainRizvi
Copy link

If this issue is fixed (as per the above comment from @AndyAyersMS) are you okay with closing it?

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 20, 2020
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 enhancement Product code improvement that does NOT require public API changes/additions optimization tenet-performance Performance related issue
Projects
None yet
Development

No branches or pull requests

4 participants