首页 > 解决方案 > [[likely]] 和 [[unlikely]] 的效果可以传递/推断吗?

问题描述

C++20 引入了属性[[likely]][[unlikely]]用于可能执行或不太可能执行的信号语句以帮助优化。__likely从历史上看,这些属性是特定于编译器的,并且隐藏在__unlikely宏函数后面以帮助优化分支语句;然而,C++20 更进一步,允许它们出现在任何语句中。

从理论上讲,这应该允许基于上下文和可见性进行[[likely]]推断[[unlikely]]——例如:

// Just an opaque function to call so we see it in the generated assembly
void something_expensive();

// Something we know to always be unlikely
[[gnu::always_inline]]
inline void unlikely_code_path() {
    [[unlikely]] something_expensive();
}

void test_unlikely(bool x) {
    if (x) /* [[unlikely]] inferred? */ { unlikely_code_path(); }
}

我在这个例子中使用了inlined/visible 函数调用,因为我可以看到assert对于像为了。但是,我没有看到任何编译器实际上利用了这一点。

Live Example

GCC 和 Clang 都生成相同的汇编输出,它们都没有利用[[unlikely]](或[[likely]])知识:

test_unlikely(bool):
        test    dil, dil
        je      .L4
        jmp     something_expensive()
.L4:
        ret

我的期望是,它test_unlikely会知道[[unlikely]]分支并生成类似于 if this are 生成的内容if (b) [[unlikely]] { ...},即:

test_unlikely(bool):
        test    dil, dil
        jne     .L6
        ret
.L6:
        jmp     something_expensive()

编译器是否错过了标记“热门”和可能路径的机会?或者我是否缺少关于 C++ 语言的一些东西,实际上可能会阻止这种优化在实践中单独使用属性来实现?

注意:我知道 C++ 中的属性实际上是非绑定契约,因此编译器不需要尊重它们;但这里的编译显然尊重某些情况,这让我认为这只是一个错过的优化)

标签: c++optimizationc++20

解决方案


推荐阅读