简单的添加方法生成了过多的IL代码

4

我正在尝试使用IL代码来改进我的C#数学运算能力。其中一个问题是,C#不允许在泛型上进行数学运算,但是IL允许-至少对于原始数据类型(有趣的是不包括十进制类型)。因此,我创建了一些测试方法来检查结果的IL代码。

以下是C#方法的代码:

  public static float Add(float A, float B)
  {
        return A + B;
  }

这是使用VS2015SP2 / Release + Optimizations编译的结果。为了确保,以下是来自构建的csc命令行:
C:\Program Files (x86)\MSBuild\14.0\bin\csc.exe /noconfig /nowarn:1701,1702,2008 /nostdlib+ /platform:anycpu32bitpreferred /errorreport:prompt /warn:4 /define:TRACE /errorendlocation /preferreduilang:en-US /highentropyva+ /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\Microsoft.CSharp.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\mscorlib.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Data.DataSetExtensions.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Data.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Net.Http.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Xml.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.Xml.Linq.dll" /debug- /filealign:512 /optimize+ /out:obj\Release\ConsoleApplication1.exe /ruleset:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets\MinimumRecommendedRules.ruleset" /subsystemversion:6.00 /target:exe /utf8output Program.cs Properties\AssemblyInfo.cs "C:\Users\Martin\AppData\Local\Temp.NETFramework,Version=v4.5.2.AssemblyAttributes.cs" obj\Release\TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs obj\Release\TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs obj\Release\TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
    .method public hidebysig static 
    float32 Add (
        float32 A,
        float32 B
    ) cil managed 
{
    // Method begins at RVA 0x2054
    // Code size 9 (0x9)
    .maxstack 2
    .locals init (
        [0] float32
    )

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldarg.1
    IL_0003: add
    IL_0004: stloc.0
    IL_0005: br.s IL_0007

    IL_0007: ldloc.0
    IL_0008: ret
} // end of method Program::Add

你知道为什么这段代码中仍然有nop,为什么有一个本地变量以及为什么在结尾处有一个无作用的跳转吗?

我明白最终的即时编译器可能会解决这个问题,但是如果我看到这个问题,我不知道是否可以信任即时编译器。

谢谢
马丁


nop 是因为您在调试配置中构建。如果您想要更干净的 IL,您可以构建发布配置。 - Abdullah Nehir
不是真的。正如我所写的,优化已经开启并且我已经切换到发布模式。 - msedi
分支操作码使您能够在方法结束处设置断点。同样,这是由于调试配置的原因。 - Abdullah Nehir
明白了。但是我能做的就只有切换到发布模式并勾选“优化代码”复选框,你知道我怎么在VS GUI输出中检查msbuild的命令行参数吗? - msedi
是的,我错过了你写的是在发布配置中构建。但我的经验表明,构建配置存在问题。您能否检查项目属性(而不是工具栏上的组合框),并确保也配置为发布? - Abdullah Nehir
显示剩余2条评论
1个回答

2

很抱歉,我无法重复您的结果。使用csc /debug- /optimize+编译后,再使用ildasm,我得到:

.method public hidebysig static float32  Add(float32 A,
                                             float32 B) cil managed
{
  // Code size       4 (0x4)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  add
  IL_0003:  ret
} // end of method Program::Add

这是我从优化代码中期望的结果。如果我将其更改为 optimize-,我会得到你发布的代码。你是否检查了 Debug 和 Release 子目录?


这正是我得到的。当禁用优化时,我得到了OP的代码。 - Rob
嗨,杰西和罗布。有时候有人向我展示我有多愚蠢是很有帮助的。你是完全正确的,杰西。 - msedi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接