了解针对编译时逻辑的编译器优化

Understanding compiler optimisations for compile time logic

如果我们有一个程序在编译时指定某些 固定 条件,编译器是否确定并修复程序将始终 'branch' 决策树的哪个 'branch' =27=]在?

例如,如果使用 -Ofast 标志编译以下程序,程序是否会花费任何时间实际检查 if (aFixedCondition) 循环?

int main() {
    bool aFixedCondition = true;
    if (aFixedCondition)
        Run_A();
    else
        Run_B();
}

这是否也扩展到我们对程序生命周期中不变的固定条件进行大量重复检查的情况。类似于:

int main() {
    bool aFixedCondition = true;
    for (int i = 0; i < 100000; i++) {
        if (aFixedCondition)
            Run_A();
        else
            Run_B();
    }
}

根据此 post, it is not a 'bad thing' per se to rely on compiler optimisations. Personally I'd rather not do this, but it is unclear how to re-organise the structure of the above program when it is embedded in a more realistic/complicated code. I also could not find anything relevant about the Ofast flag (here) 与上述相关。

在您显示的代码中,每个优秀的编译器都会识别 if 条件为真,并且如果启用优化,Run_B(); 代码将无法访问。然后它将从程序中删除 aFixedConditionRun_B(); 代码的计算,以及 bool aFixedCondition = true;.

你给出的条件当然是简单化了。 if 语句或循环中可能存在始终为真(或始终为假)的控制表达式,但由于程序中的各种复杂性,编译器无法识别这一点。最先进的技术是,如果我们可以很容易地看到某个条件在某些直接的逻辑行中始终为真,那么编译器也应该能够做到,因此在这种情况下我们可能会依赖编译器优化。但是,如果不容易看出表达式始终为真(或始终为假),则优化更多地取决于编译器质量和程序的特定情况。

在编译时常量但不能用预处理器测试完成的测试条件中使用它并不罕见。例如,在:

if (sizeof x == 4)
    DoCodeA();
else
    DoCodeB();

我们希望编译器知道 x 的大小(忽略它有一些 运行 时间变量大小的可能性,就像 C 的可变长度数组一样)并从中删除未选择的代码程序。