Can this reasonably reliably steer speculative execution?
Use `__builtin_speculation_safe_value` to defend against that.
51–60 of 70 posts
Can this reasonably reliably steer speculative execution?
Use `__builtin_speculation_safe_value` to defend against that.
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 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.
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%?
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 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…
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]] { … }
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.
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…
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?
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”.