runtime: RyuJIT: Methods that store to arguments can't be inlined

EDIT: Modified after figuring out the reason.

The following code wont be inlined because the arguments are modified inside the method body:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void WildCopy(byte* dest, byte* src, byte* destEnd)
{
    // This copy will use the same data that has already being copied as source
    // It is more of a repeater than a copy per-se. 

    do
    {
        *((ulong*)dest) = *((ulong*)src);
        dest += sizeof(ulong);
        src += sizeof(ulong);
    }
    while (dest < destEnd);
}

However this code which clone the arguments is inlined without questions:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void WildCopy(byte* destPtr, byte* srcPtr, byte* destEndPtr)
{
    byte* dest = destPtr;
    byte* src = srcPtr;
    byte* destEnd = destEndPtr;

    // This copy will use the same data that has already being copied as source
    // It is more of a repeater than a copy per-se. 

    do
    {
        *((ulong*)dest) = *((ulong*)src);
        dest += sizeof(ulong);
        src += sizeof(ulong);
    }
    while (dest < destEnd);
}

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

It is there in 1.1, along with the must-throw/no-return changes.

More trivial example:

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static int inlineMe(int a, int b, int c)
    {
        a = 1;
        return a + b + c;
    }
    public static void Main(string[] args)
    {
        int a = 0;
        int b = 1;
        int c = 2;

        int res = inlineMe(a, b, c);
        Console.WriteLine($"res={res}");
    }

JitDump:

INLINER: Marking ConsoleApplication.Program:inlineMe(int,int,int):int as NOINLINE because of stores to argument INLINER: during ‘fgInline’ result ‘failed this callee’ reason ‘stores to argument’

This is actually pretty bad. All that is required to invalidate inlining a callee was that a parameter was killed. After removing InlineObservation::CALLEE_STORES_TO_ARGUMENT, I’m getting type mismatch TYP_REF != TYP_LONG.

I’ll check in a minute and let you know. However in that case, it should still be eligible for inlining as the pointers are passed by value. There is nothing that prevents the JIT to realize that.