Skip to content

DynamicMethod calls without inlining  #34500

@kkokosa

Description

@kkokosa

JIT seems to be less aggressive in inlining with IL generated for calling DynamicMethod from another DynamicMethod. Not sure if it is expected/desirable behaviour and whether it can be easily fixed?

Simple code:

public class C {
    public static int MethodA(int x) => MethodB(x, 1000);        
    public static int MethodB(int x, int y) => x * x + y;
}

is translated to:

.method public hidebysig static int32 MethodA (int32 x) cil managed 
{
    .maxstack 8
    IL_0000: ldarg.0
    IL_0001: ldc.i4 1000
    IL_0006: call int32 C::MethodB(int32, int32)
    IL_000b: ret
}
.method public hidebysig static int32 MethodB (int32 x, int32 y) cil managed 
{
    .maxstack 8
    IL_0000: ldarg.0
    IL_0001: ldarg.0
    IL_0002: mul
    IL_0003: ldarg.1
    IL_0004: add
    IL_0005: ret
}

and then JIT produces nice result of MethodA:

C.MethodA(Int32)
    L0000: mov eax, ecx
    L0002: imul eax, ecx
    L0005: add eax, 0x3e8
    L000a: ret

while in case ILGenerator producing exactly the same IL:

private static DynamicMethod EmitMethodA(DynamicMethod secondMethod)
{
    DynamicMethod code = new DynamicMethod(string.Empty, typeof(int), new[] { typeof(int) });
    var ilGen = code.GetILGenerator();
    ilGen.Emit(OpCodes.Ldarg_0);
    ilGen.Emit(OpCodes.Ldc_I4, 1000);
    ilGen.EmitCall(OpCodes.Call, secondMethod, null);
    ilGen.Emit(OpCodes.Ret);
    return code;
}
private static DynamicMethod EmitMethodB()
{
    DynamicMethod code = new DynamicMethod(string.Empty, typeof(int), new [] {typeof(int), typeof(int)});
    var ilGen = code.GetILGenerator();
    ilGen.Emit(OpCodes.Ldarg_0);
    ilGen.Emit(OpCodes.Dup);
    ilGen.Emit(OpCodes.Mul);
    ilGen.Emit(OpCodes.Ldarg_1);
    ilGen.Emit(OpCodes.Add);
    ilGen.Emit(OpCodes.Ret);
    return code;
}

JIT produces non-inlined methods:

> !u 00007ff9`c50b0080
Normal JIT generated code
DynamicClass.(Int32)
Begin 00007FF9C50B0080, size 12
00007ff9`c50b0080 bae8030000      mov     edx,3E8h
00007ff9`c50b0085 48b87052fbc4f97f0000 mov rax,7FF9C4FB5270h
00007ff9`c50b008f 48ffe0          jmp     rax

> !u 00007ff9`c50b00f0
Normal JIT generated code
DynamicClass.(Int32, Int32)
Begin 00007FF9C50B00F0, size 8
00007ff9`c50b00f0 8bc1            mov     eax,ecx
00007ff9`c50b00f2 0fafc1          imul    eax,ecx
00007ff9`c50b00f5 03c2            add     eax,edx
00007ff9`c50b00f7 c3              ret

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions