.net 在引擎盖下,编译器如何优化布尔比较操作?

bqujaahr  于 2023-10-21  发布在  .NET
关注(0)|答案(1)|浏览(130)

注意:我在这个问题中使用PowerShell作为示例,但这同样适用于任何.NET语言。

在.NET中,我很想知道布尔逻辑的不同计算方法是如何工作的。

  • 当考虑实际应用和用例时(即使是 * 非常 * 长的运行循环),速度差异是如此微不足道,以至于“这并不重要”,这将布尔考虑简化为简单地选择编码标准/格式。
  • “哪个布尔比较运算符更快?“不是这个问题的重点

一般来说(我并不是要求每个现代CPU架构的机器语言指令集的全面列表),.NET编译器如何“优化”这些布尔比较中的每一个,以及在一天结束时,CPU是否使用不同的指令来评估这些看似相同的比较?

  • 关于== TRUE
  • -eq $true-ne $false
  • 关于== FALSE
  • (-not (<statement>)) vs -eq $false vs -ne $true
  • #假设每个比较都只限于(保证)布尔结果,为了简单说明,我们忽略了$null。
  • #历史背景加分
u3r8eeie

u3r8eeie1#

Charlieface提供了关键指针:
sharplab.io是一个很棒的站点,它允许您检查给定的C# / F# / Visual Basic代码片段在IL(或JIT ASM)方面编译为什么。
使用它,您可以基于以下C#代码观察到以下情况:

public class C {
    bool b = false;
    int dummy = 0;
    public void M() {
        // equivalent positive tests
        if(b) { ++dummy; }
        if(b == true) { ++dummy; }
        if(b != false) { ++dummy; }
        // equivalent negative tests
        if(!b) { ++dummy; } 
        if(b == false) { ++dummy; }
        if(b != true) { ++dummy; }
    }
}
  • 等价的 * 正 * 测试确实编译为 * 非常相同的IL代码 *(原则上,抽象如下):
ldarg.0
  ldfld bool C::b
  brfalse.s <target-statement>
  • 同样,等价的 negative tests all 编译为:
ldarg.0
  ldfld bool C::b
  brtrue.s <target-statement>

顺便说一句:请注意逻辑是如何 * 颠倒 * 的:对(有效)true的测试产生brfalse.s指令,即,如果测试为 not true,则跳转到何处,反之亦然(brtrue.s
要自己试验结果:

  • 使用此链接。
  • 通过右侧窗格中的Results编译列表,您还可以要求将您的输入代码 * 反编译为C#*(无论原始输入语言如何),这证实了上述发现:
  • 等价的 positive 测试 all 反编译为:
if (b) ...
  • 等效的 negative 测试 all 反编译为:
if (!b) ...

相关问题