How to use C++20's likely/unlikely attribute in if-else statement
Asked Answered
C

3

51

This question is about C++20's [[likely]]/[[unlikely]] feature, not compiler-defined macros.

This documents (cppreference) only gave an example on applying them to a switch-case statement. This switch-case example compiles perfectly with my compiler (g++-7.2) so I assume the compiler has implemented this feature, though it's not yet officially introduced in current C++ standards.

But when I use them like this: if (condition) [[likely]] { ... } else { ... }, I got a warning:

"warning: attributes at the beginning of statement are ignored [-Wattributes]".

So how should I use these attributes in an if-else statement?

Chloramphenicol answered 11/8, 2018 at 8:36 Comment(6)
If a condition is more likely in an if statement then put it firstBartley
@Bartley I know; but it's not what I'm asking..Chloramphenicol
It could be just partially implemented. Start with checking the g++ documentation and see if it should be supported.Fowle
As molbdnillo said; since the c++20 standard isn't complete let alone published it's up to the compiler to integrate new features how it likes.Bartley
Do you have an example you can show us?Calefacient
@Bartley Putting the mostly likely condition to the first statement is not equivalent to using [[likely]]. Sometimes the compiler will change if(...) A else B to if (not ...) B else A. And this will break the pipeline, then it would be slow.Here is an example: godbolt.org/z/WcPbPvTittle
C
27

Based on example from Jacksonville’18 ISO C++ Report the syntax is correct, but it seems that it is not implemented yet:

if (a>b) [[likely]] {

10.6.6 Likelihood attributes [dcl.attr.likelihood] draft

Convector answered 11/8, 2018 at 8:51 Comment(6)
Ok.. so currently the compiler just partially implemented this attribute.Chloramphenicol
@Chloramphenicol I would say that in general support for features from upcoming C++20 standard is purely experimental at this point.Convector
I find it peculiar that the while loop example provided within that link has the likely token placed after the brace rather than before like it is in the rest of the examples.Bartley
@Mercer, the latest ISO draft just states that the attributes can be assigned to a label or statement so it appears that while (cond) [[likely]] { x(); y(); } and while (cond) { [[likely]] x(); y(); } are equally valid. I'm not sure if it makes much sense to only mark the first statement as a compound statement as likely but maybe the committee knows more than I - actually that seems likely, know that I think about it :-)Stomacher
I just had a look at the examples in the provided draft and it omits an example for a while loop entirely. Time will tell.Bartley
@Mercer, it's probably allowed, at least at the moment, the draft states: "The attribute-tokens likely and unlikely may be applied to labels or statements" (and statements can be simple or compound). But I'm unsure as to the value of a single [[likely]] statement within a sequence, unless the sequence can be broken (maybe via exception or exit()?). As you say, time will tell...Stomacher
C
7

As of today, cppreference states that, for example, likely (emphasis mine):

Applies to a statement to allow the compiler to optimize for the case where paths of execution including that statement are more likely than any alternative path of execution that does not include such a statement.

That suggests that the place to put the attribute is in the statement that is most likely, i.e.:

if (condition) { [[likely]] ... } else { ... }

This syntax is accepted, for example, by Visual Studio 2019 16.7.0 when compiling with /std:c++latest.

Claudieclaudina answered 25/7, 2020 at 22:40 Comment(1)
What is the result of this: if (cond) { if (cond2) [[likely]] { f(); } else { g(); } } else { h(); } ? Honestly, it's hard to get which one is understood as likely ? The outer true branch ? The inner true branch ?Lynettelynn
S
5

So how should I use these attributes in an if-else statement?

Exactly as you are doing, your syntax is correct as per the example given in the draft standard (simplified to show relevant bits only):

int f(int n) {
    if (n > 5) [[unlikely]] {
        g(0);
        return n * 2 + 1;
    }

    return 3;
}

But you should understand that this feature is a relatively new one, so may only have placeholders in implementations to allow you to set the attributes. This appears apparent from your warning message.


You should also understand that, unless certain wording changes between the latest draft and the final product, even compliant implementations are able to ignore these attributes. They are very much suggestions to the compiler, like inline in C. From that latest draft n4762 (at the time of this answer, and with my emphasis):

Note: The use of the likely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more likely than any alternative path of execution that does not include such an attribute on a statement or label.

Note the word "allow" rather than "force", "require" or "mandate".

Stomacher answered 11/8, 2018 at 9:33 Comment(2)
It would have been A LOT easier to port existing code based on __builtin_expect, e.g. if (likely(a>b)) { if we could specify the attribute inside the if-statement: if ([[likely]] a>b) {.Gaspard
@Gaspard But the syntax also works for switch case where it's even more useful than the if. I'm getting nice performance improvements with it.Thermocline

© 2022 - 2024 — McMap. All rights reserved.