I've just stumbled across this and I'm a bit puzzled.
I have an out-of-the-box VS 2010 F# project, with all default settings, targeting .NET 4.0.
The F# code is like this:
let test(a:int, b:int, c:int) = min a (min b c)
When I compile it for release, the generated IL contains some strange NOP
instructions scattered around. Like this:
The generated IL for this (with all default settings):
.method public static int32 test(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 20 (0x14)
.maxstack 4
.locals init ([0] int32 V_0)
// HERE
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: bge.s IL_0009
IL_0005: ldarg.1
// HERE
IL_0006: nop
IL_0007: br.s IL_000b
IL_0009: ldarg.2
// HERE
IL_000a: nop
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: ldloc.0
IL_000e: bge.s IL_0012
IL_0010: ldarg.0
IL_0011: ret
IL_0012: ldloc.0
IL_0013: ret
} // end of method Module1::test
My .fsproj
project configuration is:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\TestFsIL.XML</DocumentationFile>
</PropertyGroup>
Now, if I comment out line <DebugType>pdbonly</DebugType>
, the NOP
instructions
disappear. But of course so does the PDB file!
.method public static int32 test(int32 a,
int32 b,
int32 c) cil managed
{
// Code size 17 (0x11)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: bge.s IL_0007
IL_0004: ldarg.1
IL_0005: br.s IL_0008
IL_0007: ldarg.2
IL_0008: stloc.0
IL_0009: ldarg.0
IL_000a: ldloc.0
IL_000b: bge.s IL_000f
IL_000d: ldarg.0
IL_000e: ret
IL_000f: ldloc.0
IL_0010: ret
} // end of method Module1::test
There is also a subtle different in the .locals
line:
.locals init ([0] int32 V_0)
vs
.locals init (int32 V_0)
When I tried C# compiler, it generates NOP
instructions only in the
debug builds, but these seem to go away in release builds, even when
PDB files are included using <DebugType>pdbonly</DebugType>
.
Questions:
Why are NOP instructions generated in F# in release build when PDB files are included, when C# seems to be able to avoid this.
Is there any way to get rid of those NOP, but still have the PDB files?
PS. There are related questions on SO here and here, but all the answers there say
you are compiling in debug mode, if you compile in release mode, the
NOP
goes away
which contradicts my experience with F# compiler as demonstrated.