The attribute System.Runtime.CompilerServices.MethodImplAttribute
can be used to give hints to the JIT compiler about how to handle the decorated method. In particular, the option MethodImplOptions.AggressiveInlining
instructs the compiler to inline the affected method if possible. Unfortunately the F# compiler seems to simply ignore this attribute when generating IL.
Example: The following C# code
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Inc(int x) => x + 1;
is translated to
.method public hidebysig static int32 Inc(int32 x) cil managed aggressiveinlining
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: add
IL_0003: ret
}
Note the "aggressiveinlining" flag.
This F# code however
[<MethodImpl(MethodImplOptions.AggressiveInlining)>]
let inc x = x + 1
becomes
.method public static int32 inc(int32 x) cil managed
{
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
No "aggressiveinlining". I also tried to apply the attribute to static and non-static methods of proper classes (type ...
), but the result is the same.
If however I apply it to a custom indexer, like so
type Dummy =
member self.Item
with [<MethodImpl(MethodImplOptions.AggressiveInlining)>] get x = x + 1
the resulting IL is
.method public hidebysig specialname instance int32 get_Item(int32 x) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.MethodImplAttribute::.ctor(valuetype [mscorlib]System.Runtime.CompilerServices.MethodImplOptions) = ( 01 00 00 01 00 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
... though I'm not sure whether that is equivalent to the "aggressiveinling" flag generated by the C# compiler.
Is that behavior desired/expected? Is it a bug in the F# compiler?
(Note: I'm aware of the F# inline
keyword, but that only works for F# clients of my library, not C# consumers.)
PreserveSig
,Synchronized
, andNoInlining
are respected - seeComputeMethodImplAttribs
in IlxGen.fs – Protonema