【问题标题】:Simple Add method produces too much IL code简单的 Add 方法产生过多的 IL 代码
【发布时间】:2016-07-29 01:16:07
【问题描述】:

我正在尝试通过使用 IL 代码来改进我的 C# 数学运算。目前的一个问题是 C# 不允许对泛型进行数学运算,但 IL 允许 - 至少对于原始数据类型(有趣的是不是十进制)。出于这个原因,我在 C# 中创建了一些测试方法来检查生成的 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)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\Microsoft.CSharp.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\mscorlib.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.Core.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.Data.DataSetExtensions.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.Data.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.Net.Http.dll" /参考:“C:\程序文件(x86)\参考 程序集\Microsoft\Framework.NETFramework\v4.5.2\System.Xml.dll" /参考:“C:\程序文件(x86)\参考 程序集\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 工具\规则集\MinimumRecommendedRules.ruleset" /subsystemversion:6.00 /target:exe /utf8output Program.cs 属性\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 (TaskId:27) 1>

    .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,你可以在发布配置中构建。
  • 并非如此。正如我所写,优化已打开,我切换到发布模式。
  • 分支操作码使您能够在方法结束时设置断点。 Agin,因为调试配置。
  • 明白。但是我无能为力,只能切换到发布并选中“优化代码”复选框,你知道如何在 VS GUI 输出中检查 msbuild 的命令行参数吗?
  • 是的,我错过了您在发布配置中编写的内容。但是我的经验表明构建配置有问题。你会检查项目属性(不是工具栏上的组合框)并确保也配置为发布?

标签: c# cil


【解决方案1】:

恐怕我不能重复你的结果。使用 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

这是我对优化代码的期望。实际上,如果我更改为优化-,我会得到您发布的代码。您是否正在检查 Debug 与 Release 子目录?

【讨论】:

  • 这正是我得到的。禁用优化时我得到 OPs 代码。
  • 嗨,杰西和罗布。有时,有人向我展示我有多愚蠢会有所帮助。你完全正确,杰西。
猜你喜欢
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 2017-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多