Live data from Hacker News

C++ Attribute: Likely, Unlikely

en.cppreference.com

51–60 of 70 posts

Re: C++ Attribute: Likely, Unlikely

#51
post #39

Can this reasonably reliably steer speculative execution?

No, because speculative speculation attacks can choose to deliberately mislead the dynamic branch predictor prior to the actual attack.

Use `__builtin_speculation_safe_value` to defend against that.

Re: C++ Attribute: Likely, Unlikely

#52

What everybody should read before using these (Aaron Ballman is a Senior Staff Compiler Engineer for Intel and is the lead maintainer of the Clang open source compiler): https://blog.aaronballman.com/2020/08/dont-use-the-likely-or...

It's an odd article. The basic thesis is "use pgo instead", which is reasonable enough. It starts with a long diversion through edge cases of the attributes, none of which seemed particularly impactful in practice. Perhaps he was worried that just recommending pgo on its own wouldn't convince many people. There are many situations where you can't enable pgo organizationally, for example if you're part of a large comp…

PGO also doesn't always optimize in the correct direction. If I have an error handling path in a hot loop, PGO can only optimize around its branch if it actually sees that error occur, and then it will draw wrong conclusions about the branch into the error handler because, absent fudging the tests, it will think the error path has higher importance than it does. I don't want the compiler to optimize for the error path at all, I want it to pessimize it to prioritize the non-error path. But the PGO analysis doesn't know that, it only sees branch patterns and probabilities, and not all error handling paths use exceptions.

PGO is also a pain to use in some situations. You need to be able to regularly exercise all of the main paths in the program under instrumentation, preferably automated, using a configuration as close to release build as possible. That's hard to do when your release build lacks automation support, has nondeterministic behavior by design, cross-compiles to another platform, or requires networked services to exercise main paths. I don't even know how people deal with PGO when there is a requirement for deterministic builds.

Re: C++ Attribute: Likely, Unlikely

#53

Any ideas how "likely" it needs to be benefit from likely? more than 50%? or 75%? or 90%? Can it be detrimental if it has higher changes but still close to 50%?

For GCC at least, 90% is what the optimizer assumes by default. With the GCC-specific version you can specify any arbitrary chance; specifyig 50% encourages `cmov`.

Re: C++ Attribute: Likely, Unlikely

#54
post #49

Earlier quoted context omitted.

I don’t think they suggested avoiding the checks, unless I’ve missed something?

The part that's confusing me is the part about avoiding clutter – if you have to do all the checks anyway, what clutter are you avoiding by changing the order of them?

I believe the likelihood annotations are the things they are talking about, for cluttering the code. Not the argument checks.

Re: C++ Attribute: Likely, Unlikely

#55
post #33

I often write my code pessimally in this regard so have a note in the back of my mind to someday use these in a few hot paths. When I say “pessimally” I mean I usually check the unlikely cases right away and then put the normal case last: Blah foo (something& arg) { if (is_invalid (arg)) return blah(0); if (is_inactive (arg)) return blah(1); // ok do all the normal stuff } It makes the code clearer but slightly slowe…

> I could always write a conditional for the hot path up front, but code is for human readers, right? Does C or C++ actually make any promises that it’ll assume the “true” branch of the conditional will be taken? I always assumed that the compiler could make whatever weird decision it wants for that sort of thing. TBH I’d probably just write normal stuff as a function, and then call that function directly in cases wh…

No. The traditional compiler heuristic is to assume backwards branches are taken (loops) and forward branches are not.

Re: C++ Attribute: Likely, Unlikely

#56

Earlier quoted context omitted.

This is standardizing vendor-specific attributes that have existed for many years. The code that use these probably use some preprocessor macro to select the right builtins, and aren't going to gain much new clutter to replace those macros. I believe this is the proposal that added them: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p04... The "references" section has links to GCC and Clang builtins: https…

> This is standardizing vendor-specific attributes Except the standard’s likely and unlikely attributes invented new syntax that is not drop-in compatible with clang’s and gcc’s attributes. Where clang and gcc would use: if (__builtin_expect(x > 0, 1)) { … } the standard uses: if (x > 0) [[likely]] { … }

It's definitely an unconventional syntax. In addition to the above, OpenMP and shader languages annotate the branch statement for parallelism or branch/predication hints. I can't think of precedent for C++ putting the hints in the branch targets. It does have some advantages, but it's not very intuitive. The first time I tried to use the new hints I did [[likely]] if(), which of course did nothing.

Re: C++ Attribute: Likely, Unlikely

#57

Earlier quoted context omitted.

> I could always write a conditional for the hot path up front, but code is for human readers, right? Does C or C++ actually make any promises that it’ll assume the “true” branch of the conditional will be taken? I always assumed that the compiler could make whatever weird decision it wants for that sort of thing. TBH I’d probably just write normal stuff as a function, and then call that function directly in cases wh…

No. The traditional compiler heuristic is to assume backwards branches are taken (loops) and forward branches are not.

[deleted]

Re: C++ Attribute: Likely, Unlikely

#59
post #33

I often write my code pessimally in this regard so have a note in the back of my mind to someday use these in a few hot paths. When I say “pessimally” I mean I usually check the unlikely cases right away and then put the normal case last: Blah foo (something& arg) { if (is_invalid (arg)) return blah(0); if (is_inactive (arg)) return blah(1); // ok do all the normal stuff } It makes the code clearer but slightly slowe…

> I could always write a conditional for the hot path up front, but code is for human readers, right? Does C or C++ actually make any promises that it’ll assume the “true” branch of the conditional will be taken? I always assumed that the compiler could make whatever weird decision it wants for that sort of thing. TBH I’d probably just write normal stuff as a function, and then call that function directly in cases wh…

[deleted]

Re: C++ Attribute: Likely, Unlikely

#60
post #49

Earlier quoted context omitted.

I don’t think they suggested avoiding the checks, unless I’ve missed something?

The part that's confusing me is the part about avoiding clutter – if you have to do all the checks anyway, what clutter are you avoiding by changing the order of them?

That conditional would be checked, then if it failed, checked again after the normal case has run, in order to choose the arm to follow.

Not a huge deal execution-time-wise, but from a reader’s PoV, the way I write it says, “ok, the special cases don’t apply to the body so I don’t have to worry that the index will be out of range (or whatever) and can just focus on the logic”.

Post reply on HN