最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Is [[likely]] redundant if [[unlikely]] exists in if-else branch in C++20? - Stack Overflow

programmeradmin2浏览0评论

Consider the following code:

void f1(bool ok) {
    if (ok) [[likely]] {
        // ...
    } else [[unlikely]] {
        // ...
    }
}

void f2(bool ok) {
    if (ok) [[likely]] {
        // ...
    } else {
        // ...
    }
}

void f3(bool ok) {
    if (ok)  {
        // ...
    } else [[unlikely]] {
        // ...
    }
}

Are f1, f2, and f3 equivalent from the view of compiler?

Consider the following code:

void f1(bool ok) {
    if (ok) [[likely]] {
        // ...
    } else [[unlikely]] {
        // ...
    }
}

void f2(bool ok) {
    if (ok) [[likely]] {
        // ...
    } else {
        // ...
    }
}

void f3(bool ok) {
    if (ok)  {
        // ...
    } else [[unlikely]] {
        // ...
    }
}

Are f1, f2, and f3 equivalent from the view of compiler?

Share Improve this question edited 2 days ago xmllmx asked Feb 8 at 8:09 xmllmxxmllmx 42.4k32 gold badges180 silver badges351 bronze badges 4
  • 1 it is something like, the compiler assigns a heuristic probability to each branch, and it optimizes for the "hot" path. the compiler can be mistaken about what hot path to optimize for, and using [[likely]] or [[unlikely]] will help it by changing its heuristics, but it is up to the compiler how to interpret them or modify its internal heuristics, it may just ignore them entirely, see C++20’s likely Attribute - Optimizations, Pessimizations, and unlikely Consequences - CppCon – Ahmed AEK Commented Feb 8 at 8:13
  • 3 I've reopened this because the dupes (from the first glance) don't talk about the equivalence of those 3 options. Perhaps consider changing the title so it looks less like a dupe. – HolyBlackCat Commented Feb 8 at 8:32
  • @HolyBlackCat, I've changed the title. – xmllmx Commented Feb 8 at 8:38
  • 1 For simple cases like you describe, theoretically, yes. For more complicated cases (e.g. multiple branches with some annotated [likely], some [unlikely], and some unannotated) possibly not. Practically, it will depend on quality of implementation of the compiler, and if/ how it responds to (or even ignores) such annotations. – Peter Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 5

Is [[likely]] redundant if [[unlikely]] exists in if-else branches in C++20?

Basically yes, it is redundant, except for one case that MSVC doesn't handle properly. If you apply just one of the attributes to the true branch of an if statement, all compilers work as expected and don't require an opposite attribute on the else branch.

Lack of documentation

The C++ standard under [dcl.attr.likelihood] provides no clear usage guidance for this case, and neither do any of the compiler manuals.

Clang has this example:

if (b) [[likely]] { // Placement on the first statement in the branch.
  // The compiler will optimize to execute the code here.
} else {
}

An example where both [[unlikely]] and [[likely]] are used (in a non-contradictory or non-ignored way) doesn't exist in the documentation.

GCC seems to contain no documentation at all under Statement Attributes and Label Attributes, but one would expect that it works similarly to Clang.

MSVC documentation is also vague and just explains that the attributes are optimization hints, but doesn't say much about these usage edge cases.

Compiler output

If you flip [[likely]] and [[unlikely]] in your code, then it's possible to get some compiler divergence for f3 (https://godbolt.org/z/dffYv1E7r):

int t, f;

void f3(bool ok) {
    if (ok) {
        t = 0;
    } else [[likely]] {
        f = 0;
    }
}

GCC and Clang are biased towards f = 0 and jump to t = 0, but MSVC does the unexpected:

void f3(bool) PROC                                 ; f3, COMDAT
        test    cl, cl
        je      SHORT $LN2@f3
        mov     DWORD PTR int t, 0                  ; t
        ret     0
$LN2@f3:
        mov     DWORD PTR int f, 0                  ; f
        ret     0
void f3(bool) ENDP                                 ; f3

This output is biased towards t = 0 even though f = 0 is likely. Perhaps the MSVC bug here is that [[likely]] and [[unlikely]] attributes on else branches are ignored completely, and only the attributes after the condition of the if statement matter. I've reported this at https://developercommunity.visualstudio.com/t/likely-and-unlikely-attributes-a/10845089


Note: the fact that GCC emits slightly worse code than Clang and MSVC in the example is a known GCC Bug 47253. The output is still equivalent in behavior to Clang.

发布评论

评论列表(0)

  1. 暂无评论