gpt4 book ai didi

f# - 为什么F#编译器即使在发行版中也生成IL NOP?

转载 作者:行者123 更新时间:2023-12-04 04:07:02 29 4
gpt4 key购买 nike

我偶然发现了这个,我有点困惑。

我有一个现成的VS 2010 F#项目,具有所有默认设置,目标是.NET 4.0。

F#代码如下所示:

let test(a:int, b:int, c:int) = min a (min b c)

当我对其进行编译以进行发布时,生成的IL包含一些奇怪的 NOP指令四处散落。像这样:

为此生成的IL(具有所有默认设置):
.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

我的 .fsproj项目配置为:
  <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>

现在,如果我注释掉 <DebugType>pdbonly</DebugType>行,则 NOP指令
消失。但是PDB文件当然也是如此!
.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
.locals行中也有一个细微的区别:
.locals init ([0] int32 V_0)


.locals init (int32 V_0)

当我尝试使用C#编译器时,它仅在
调试版本,但即使在发布版本中,它们似乎也消失了
使用 NOP包含PDB文件。

问题:
  • 为什么在包含PDB文件且C#似乎能够避免这种情况的情况下,在F#的F#版本中生成NOP指令。
  • 有什么方法可以摆脱那些NOP,但仍然拥有PDB文件吗?

  • PS。有关于SO here的相关问题
    here
    但是那里所有的答案都说

    you are compiling in debug mode, if you compile in release mode, the NOP goes away



    这与我所展示的F#编译器的经验相矛盾。

    最佳答案

    我不完全知道这在F#编译器内部如何工作(F#团队的某个人可能会有更好的答案),但是我的猜测是,生成nop指令只是生成可从中引用的位置的相当简单的方法。 pdb文件。
    pdb文件需要为代码中的表达式指定一些IL范围,您可以在其中放置一个断点-在“调试”和“发布”模式下都是这种情况。这意味着,如果将断点放置在某个位置,则IL中需要有一个对应的位置。但是,如果没有与源代码位置相对应的实际指令,则编译器需要插入一些内容-因此添加了nop

    在 Release模式下,F#编译器进行了更多优化,但是如果您需要pdb文件,它仍然需要为所有源代码位置提供位置。在C#中可能不需要这样做,因为C#与源IL的映射更加紧密,但是在F#中避免这种情况可能会更加困难。

    关于f# - 为什么F#编译器即使在发行版中也生成IL NOP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10139168/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com