back
60 comments
Oh dang, branch hints. I always thought they were so obvious, and never implemented, so they must be obviously bad. But, Intel is giving them a shot. Neat!
Giving them another shot. Pentium 4 had them, but there were some skill issues on the part of programmers using them, and so code quality rose when CPUs started ignoring them.
I don’t think it’s a skill issue. It’s that they’re really only useful with profile guided optimization—so you can have hints that reflect actual branch probabilities. But most developers don’t seem to bother to do that.
I wouldn't say that PGO is necessary to predict branches correctly. Lots of branches are exceptional control flow (error checks, bounds checks, etc.) and compilers will almost always correctly statically predict not taken for them. Any branch with a target that's postdominated by a throw or a process abort can basically be safely predicted not taken (after all, if you got it wrong, the penalty is going to be minuscule compared to the cost of the exception).
The hardware itself is already very good at predicting the direction. I think the point about PGO here is that you need it to find infrequently-occuring biased-taken branches.

When you encounter a biased-taken branch that isn't currently being tracked by the machine, you're always condemned to pay the cost of a misprediction because the default prediction is "not-taken". The hinting here is supposed to indicate "when encountering this branch, don't predict not-taken by default."

If memory serves, wasn't that a bit of a tool minefield back then, too? It’s been a while but I thought I remembered a few colleagues trying GCC’s version which involved building a new version of GCC, slowing down the builds a fair amount, and then seeing only a small benefit – far less than they got switching to the first AMD Opteron when it came out a year later.
Arguably on P4 they were required to get any kind of throughput due to an incredibly long execution pipeline Intel contrived to keep pushing clock frequency up. Branch mispredictions were extremely costly on that architecture.
Yes, the Pentium 4 pipeline was ~32 cycles long, which meant that a branch misprediction carried a huge penalty. Processors today have settled on using a ~15-cycle pipeline.
I've probably read about it and forgotten, but what on earth was it doing in all those pipeline stages?

Were there a lot of idle/no-op stages for simple instructions? Or did most instructions, even simple ones, actually get some useful work done for each of those 32ish stages?

I can see how branch hints are useful, but in practice isn't the sign of the distance to the branch target the implicit hint? If the predictor doesn't have any other information it assumes that backwards branches are taken and forward branches are not. So, you can imagine how the compiler would rearrange the program to align with that implication, where possible.

One of the things that the BOLT post-link optimizer does is rearrange basic blocks to reduce taken forward branches, based on the profiles.

You can't reorder some kinds of branches, like retry sequences.

I have absolutely no idea how important that it. But there exist that bit of extra complication on the real world.

Retry sequences are unlikely to be the kind that the branch prediction is that important? I'd also expect that they are larger than the threshold that is common for branches that are likely to be taken many times.

That is, the stuff that will go into a retry of something likely has far more setup than your typical hot loop.

Huh, that’s a funny and true perspective. I always took the “branches backwards tend to be loops” assumption as true, but of course there’s no reason a compiler or linker couldn’t use that assumption as well.
Yes I don't really get it. For non-loop branches if the compiler has knows enough to insert a branch hint it would also already arrange the generated code so that was the fall through cases, which is already much more efficient when predicted and aligns the default fall through assumption in the CPU.
IIRC, SPARC also used them, which... probably suggests that it's not totally terrible.
Then again SPARC had register windows ... so ...
I believe PowerPC had them as well. No idea how effective they were.
I took computer architecture in the mid-late-90s and branch hints were talked about as a thing that was being done.
Yeah, in my class (a couple years ago, but not decades) they were covered as something that seemed like a neat idea, but then didn’t help much for actual programs. The general theme in that class was that everything cool added more complexity than the performance benefit could justify, and got in the way of making things wider.

Same for branch delays slots.

From distant memory: they were effective for at least some PowerPC implementations. I don't recall how much, but it was considered worthwhile in hot code for at least some machines. However, IIRC, branch prediction wasn't as advanced at that point; a modern implementation might not see the same benefits.
The i960CA and CF had branch hints. It was bit 1 in the branch and the compare and branch opcodes.
Do compilers even generate these hints?
Usually not by default, but GCC and other compilers have intrinsics like __builtin_expect [1] which may generate branch hints.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index...

In practice this doesn't result with a special-kinded instruction to hint the CPU branch-predictor but only affects the compiler to generate a codegen that is optimized for better CPU instruction-cache utilization. E.g. it will try to move the less likely code out from the hot code path and as such the likely code is going to be more dense and co-located next to each other.
Quite popular in the Linux kernel code, as far as I've seen over the years. See [1] for some discussion over on SO.

[1]: https://stackoverflow.com/questions/109710

I think in general we're overdue for more compiler directives, and not just branch hints. As heterogenous architectures become more standard, we really need a way to tag what functions are best to run with what types of instructions. For example, tag a function that will utilize SIMD so that if a thread is running this function, the operating system knows to try to have it run on the cores that support SIMD. As of now, with P and E Cores for Intel, Intel is straight up disabling instructions to ensure uniform instruction support.
IDK but I know C++ has [[likely]] and [[unlikely]] hints:

https://en.cppreference.com/w/cpp/language/attributes/likely

They were not necessary, as the CPU would run the both sides of the branch in parallel and scrap the irrelevant side when it was known to be false. Essentially making a hint pointless, as it was not utilized at all.

Now the execution of both sides of a branch is basis for the 'Specter' side-channel attack. Access restricted data in the false branch, data access still happen even though it was restricted.

That is essentially impossible to prevent and disabling it killed a lot of cpu performance, branch hints might be the next best thing.

> Now the execution of both sides of a branch is basis for the 'Specter' side-channel attack. Access restricted data in the false branch, data access still happen even though it was restricted.

By all accounts of Spectre I've seen, the processor never tries to speculate both sides of the branch. Instead, it always predicts one side of the branch, and speculatively executes that side only: when it later turns out to have been a misprediction, it rolls back the speculative execution, and proceeds to execute the other side from scratch. Both sides are executed at some point, but not simultaneously.

If you’re not speculatively executing, you don’t need a branch hint because you don’t need to speculate which way it goes.

Also, I don’t think executing both sides of a branch ever took off on any mainstream CPUs (unless Itanium counts). It wastes power to spend half your execution units on things that won’t be committed, why not use them on the other hyperthread instead?

Yeah I'm pretty sure most CPUs don't actually execute both branches. They pick the most likely one and execute that.

See https://people.computing.clemson.edu/~mark/eager.html

"AI has been very popular among people wishing they had seven fingers on each hand instead of five"
Newer models don’t have this issue.

Now, everyone gets five fingers and a thumb, as requested.

But most unfortunate for Numbers. We have 4 fingers, making binary capabilities, now if we had 60 fingers... then it would be a different story. With 5 fingers on each hand, and two hands, that is the product of two primes, and with 7 fingers on 3 hands, also the product of two primes... You have something to look forward to in Genetic Engineering 2077. Eight fingers on 4 hands? Personally, my fingers count only to 1023, and have for decades.

The article points out specific use of specific techniques to probe cache and other efficiencies, which is valuable.

"....and 17 other bus stop conversations you'd never expect to have."
Think of how much more you could get done
I call it "the stranger".
I think another hand instead of extra fingers would be much more productive
Totally, I'm making a somewhat 'disposable'/weak joke

It's a fun play on the idea of a productivity enhancer. AI - the extra fingers or hand - does well to spare me effort, I just think productivity may not be the right way to look at things

"[I'd do it but] I only have 5 fingers"
Emacs users and Lisp? For sure, since the ITS days.
I wondered if this was a saying translated from another language.
People downvoting you probably don't realise this is a direct quote from the article. Maybe if you had written some actual comment, too...
Sorry about no additional comment, I couldn't think of something clever that included an Inigo Montoya reference...
> Inigo Montoya reference

Huh? Who?

It's the latter bit for me. Ok, so it's a quote from the article. So what? What's interesting about it? What's funny about it? Don't make me guess. Tell my why you thought it was worth your time copy-pasting it into the comment box. Foster some discussion!
FTR, that had me chuckle, it's quite funny considering the fingers nightmares current day generative "AI" comes up with
It was a no-content throwaway comment in the article too; highlighting it on HN is pointless. I doubt the downvoters would care much whether it was in the article or not.