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

JIT: Physical promotion readback mechanism does not take implicit control flow into account #86498

Closed
jakobbotsch opened this issue May 19, 2023 · 1 comment · Fixed by #86706
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone

Comments

@jakobbotsch
Copy link
Member

jakobbotsch commented May 19, 2023

Physical promotion currently relies on being able to insert pending read backs before control is transferred to any successor block. This happens at the end of the block, but doing it this way does not take implicit control flow into account. For example:

using System;
using System.Runtime.CompilerServices;

public class Program
{
    public static int Main()
    {
        int result = Test();
        if (result == 100)
        {
            Console.WriteLine("PASS");
        }
        else
        {
            Console.WriteLine("FAIL: Returned {0}", result);
        }

        return result;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static int Test()
    {
        Foo f = new();
        try
        {
            f.X = 15;
            f.Y = 20;
            f.X += f.Y;
            f.Y *= f.X;

            // f will be physically promoted and will require a read back after this call.
            // However, there is implicit control flow happening that the read back should happen before.
            f = Call(f);
            ThrowException();
            return -1;
        }
        catch (Exception ex)
        {
            return f.X + f.Y;
        }
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static Foo Call(Foo f)
    {
        return new Foo { X = 75, Y = 25 };
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static void ThrowException()
    {
        throw new Exception();
    }

    private struct Foo
    {
        public short X, Y;
    }
}

To fix we can likely insert any pending read backs before any GTF_EXCEPT marked tree when in a try region.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 19, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label May 19, 2023
@jakobbotsch jakobbotsch self-assigned this May 19, 2023
@ghost
Copy link

ghost commented May 19, 2023

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Issue Details

Physical promotion currently relies on being able to insert pending read backs before control flow is transferred to any successor block. This happens at the end of the block, but doing it this way does not take implicit control flow into account. For example:

using System;
using System.Runtime.CompilerServices;

public class Program
{
    public static int Main()
    {
        int result = Test();
        if (result == 100)
        {
            Console.WriteLine("PASS");
        }
        else
        {
            Console.WriteLine("FAIL: Returned {0}", result);
        }

        return result;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static int Test()
    {
        Foo f = new();
        try
        {
            f.X = 15;
            f.Y = 20;
            f.X += f.Y;
            f.Y *= f.X;

            // f will be physically promoted and will require a read back after this call.
            // However, there is implicit control flow happening that the read back should happen before.
            f = Call(f);
            ThrowException();
            return -1;
        }
        catch (Exception ex)
        {
            return f.X + f.Y;
        }
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static Foo Call(Foo f)
    {
        return new Foo { X = 75, Y = 25 };
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static void ThrowException()
    {
        throw new Exception();
    }

    private struct Foo
    {
        public short X, Y;
    }
}

To fix we can likely insert any pending read backs before any GTF_EXCEPT marked tree when in a try region.

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr, untriaged

Milestone: -

@jakobbotsch jakobbotsch removed the untriaged New issue has not been triaged by the area owner label May 19, 2023
@jakobbotsch jakobbotsch added this to the 8.0.0 milestone May 19, 2023
jakobbotsch added a commit to jakobbotsch/runtime that referenced this issue May 24, 2023
Physical promotion relies on being able to read back any promoted field
that is fresher in its struct local before control flows to any
successor block. This was failing to take implicit control flow into
account.

Fix dotnet#86498
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label May 24, 2023
jakobbotsch added a commit that referenced this issue May 26, 2023
…it control flow (#86706)

Physical promotion relies on being able to read back any promoted field
that is fresher in its struct local before control flows to any
successor block. This was failing to take implicit control flow into
account.

Fix #86498
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label May 26, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jun 26, 2023
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
Projects
None yet
1 participant