48

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?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Leedehai
  • 3,660
  • 3
  • 21
  • 44
  • If a condition is more likely in an if statement then put it first – Mercer Aug 11 '18 at 08:45
  • 3
    @Mercer I know; but it's not what I'm asking.. – Leedehai Aug 11 '18 at 08:47
  • 3
    It could be just partially implemented. Start with checking the g++ documentation and see if it should be supported. – molbdnilo Aug 11 '18 at 08:53
  • 1
    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. – Mercer Aug 11 '18 at 08:59
  • Do you have an example you can show us? – SherylHohman Sep 03 '18 at 10:10
  • @Mercer 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: https://godbolt.org/z/WcPbPv – HarryLeong Dec 28 '19 at 11:19

3 Answers3

26

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

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Ok.. so currently the compiler just partially implemented this attribute. – Leedehai Aug 11 '18 at 08:56
  • @Leedehai I would say that in general support for features from upcoming C++20 standard is purely experimental at this point. – user7860670 Aug 11 '18 at 09:02
  • 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. – Mercer Aug 11 '18 at 09:05
  • 1
    @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 :-) – paxdiablo Aug 11 '18 at 09:48
  • 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. – Mercer Aug 11 '18 at 09:53
  • @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... – paxdiablo Aug 11 '18 at 15:05
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.

Gabriele Giuseppini
  • 1,541
  • 11
  • 19
  • 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 ? – xryl669 Mar 24 '22 at 17:03
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".

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 15
    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) {`. – rustyx Mar 18 '19 at 21:15
  • 1
    @rustyx 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. – Octo Poulos Jul 16 '22 at 22:44