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

时间:2021-07-07 01:37:36

标签: c++ compiler-optimization

如果我们有一个程序在编译时指定了某些固定条件,编译器是否会确定并修复程序将始终运行在决策树的哪个“分支”?

例如,如果以下程序是使用 -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,依赖编译器优化本身并不是一件“坏事”。就我个人而言,我宁愿不这样做,但是当将上述程序嵌入到更现实/复杂的代码中时,尚不清楚如何重新组织上述程序的结构。我也找不到与上述内容相关的 Ofast 标志 (here) 的任何相关信息。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

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

相关问题