__builtin_expect() is a GCC-derived builtin that's used as a hint for branch prediction:
The Clang/LLVM implementation of this feature introduced an LLVM intrinsic to convey the hint to the optimizer:
There are problems with this (and several were noted in the above thread, but it didn't change the outcome):
- We created an intrinsic to improve perf, but the intrinsic can harm optimization by interfering with other passes.
- To solve that, create a pass to always transform the intrinsic into metadata at a very early stage. But now every program is paying a compile-time tax for a feature that is rarely used.
- The IR lowering uses profile weight metadata as the means for conveying the hint. But the hint is meant to be a programmer override for profile data. That is, "I don't care what the profile says; I want my code to use this source-level hint." So it should use a different kind of metadata, not profile weight. We added the inverse programmer hint as metadata - __builtin_unpredictable():
so I think we can enhance that to solve this problem.
This patch is an intermediate step. It doesn't try to solve #3 above, but it handles #1 and clears the way to deprecate the llvm.expect intrinsic and delete the LowerExpectIntrinsic pass (problem #2).
This is part of solving:
But to complete that, we need to make changes in SimplifyCFG and possibly other places, so that we're propagating and using the expect/unpredictable metadata as intended. Ref: D18133, D18220, rL264527, rL266442