【问题标题】:Prevent compiler from separating function's instructions防止编译器分离函数的指令
【发布时间】:2020-04-15 12:04:03
【问题描述】:

我有一段这样结构的代码:

__forceinline void problemFunction(bool condition, int & value)
{
    if (condition)
    {
        value = 0;
        return;
    }

    // ...
    // a lot of calculations
    // ...
}

void caller()
{
    bool condition;
    int value;

    // ...

    problemFunction(condition, value);
    someOtherStuff();
}

但是在反汇编中打开优化的构建发布配置后,我得到了这样的结果:

void caller()
{
    bool condition;
    int value;

    // ...

    if (condition)
        value = 0;
    else
        goto CalculateLabel;

ReturnProblemFunctionLabel:

    someOtherStuff();
    goto ReturnLabel;

CalculateLabel:
    // ...
    // a lot of calculations
    // ...
    goto ReturnProblemFunctionLabel;

ReturnLabel:

}

ProblemFunction 被分成两部分。问题是第二部分位于someOtherStuff函数调用之后。

如何在本地抑制这种优化?

我在 Windows 10 上使用 Visual Studio 2019 版本 16.4.2。

【问题讨论】:

  • 您有什么理由要这样做吗?这没有错或任何事情。行为完全相同。
  • 在 C++20 中,您可以使用可能/不太可能属性 (see here) 标记 if 语句。不知道Visual Studio 2019现在有没有支持。
  • 请解释为什么这是一个问题。
  • 你明确地标记了你的函数__forceinline,所以编译器确实内联了它。一旦内联,它就不再是一个单独的函数了。编译器只是在单个函数中重新排序操作。你想解决什么问题?
  • 允许编译器重新排列代码,前提是生成的代码与未重新排列的代码执行相同的操作。看起来就是这里的情况。你能写出一个有效的 C++ 程序来区分吗?如果不是,则更改是可以的。

标签: c++ windows visual-studio optimization


【解决方案1】:

在 C++20 中,您可以使用可能/不太可能属性标记分支(请参阅 this questioncppreference),这可以为编译器提供有关如何更好地优化代码的提示。在您的原始帖子中,我假设传递给problemFunction 的条件通常为假,这意味着在大多数情况下是不必要的跳转。

正如你在godbolt 上看到的,如果你用[[unlikely]] 标记你的if 语句,g++ 将输出你想要的结果,但msvc 不会改变生成的代码。请注意,此示例只是一个基本演示。编译你的实际程序可能会得到不同的结果。

还要注意,由于分支预测,跳转并不一定意味着性能更差。您必须衡量执行时间才能得出任何有意义的结论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2017-06-02
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多