Hello everyone,
I would like to propose __builtin_consistent, MD_consistent metadata, MIFlag::Consistent flag and additional argument to removeBranch,insertBranch methods to support consistent branches.
instructions.
The hint indicates that that branch is very consistent in its behaviour and very likely to always go in the same direction.
Proposal
To support generation of such consistent branches new builtin __builtin_consistent was added:
if (__builtin_consistent(x > 0)) {
foo();
}
It is used to specify that branches or switches having expression from it as condition are consistent.
The builtin set consistent metadata MD_consistent to instructions accordingly, which is taken into account and inherited by control flow optimizations. For this purpose consistent flag as argument was added to removeBranch and insertBranch target methods. Consistency also inherited to machine instructions level MIFlag::Consistent and on AArch64 target with FEAT_HBC for consistent branches BC.cond instructions are generated.
I think the intent of the new builtin is a way to say âthe branch will go one way or the other, but I donât know which.â But, IMO, Iâm not sure I really see the use of this as a frontend feature.
It seems to me that we should just use the existing branch_weights data that comes from __builtin_expect/__builtin_expect_with_probability to decide to emit a consistent-branch instruction in the backend, rather than introducing a new __builtin_consistent operation, even though the latter does, in theory, express something slightly different.
In general, you canât replace all usage of this with __builtin_expect. For example, suppose youâre doing runtime CPU detection to choose one path or another. The branch is predictable in the sense that it always goes the same way, but it doesnât make sense to say one path is more likely.
I guess we can use __builtin_expect as a hint for consistent branches, though; if youâre using __builtin_expect, probably the branch consistently branches towards the likely side, so we could use the âconsistentâ branch in the generated assembly. And probably that does cover most realistic uses.
It might be worth considering whether any optimizations could benefit from âconsistentâ markings; certain optimizations, like heuristics for flattening ccontrol flow, care whether the branch is predictable, not which way it goes goes any specific way.
As a counterpoint: in the linux kernel, they have a âstatic branchâ mechanism, used for such CPU-detection cases. This mechanism arranges to patch the instruction stream at boot time (and potentially at runtime, in some use-cases), to either have an unconditional branch or a nop. No conditional branch is ever used, so no condition needs to be evaluated at runtime. This is the epitome of a âconsistent branchâ! Yet, interestingly, the abstraction provided consists of a pair of APIs: static_branch_likely and static_branch_unlikely. There is no API for âI cannot guess which direction is more likely to be consistently takenâ!
my main input is: for an embedded/bare metal application it is hard to know the behavior of the branch with high accuracy, and so if we get it wrong it may hurt the performance of the application. so most of the time we may not use this builtin if it were available to us.