Branches
branches provides branch prediction hints, control flow assumptions, abort, and manual data prefetch (read & write) helpers for performance optimization, using stable Rust primitives where available and falling back to core::intrinsics on nightly.
Usage
To use branches, use following command:
For a no_std environment, disable the default features(std and prefetch) by using following command:
For a no_std with prefetch feature:
Functions
The following functions are provided by branches:
likely(b: bool) -> bool: Returns the input value but provides hints for the compiler that the statement is likely to be true.unlikely(b: bool) -> bool: Returns the input value but provides hints for the compiler that the statement is unlikely to be true.assume(b: bool): Assumes that the input condition is always true and causes undefined behavior if it is not. On stable Rust, this function usescore::hint::unreachable_unchecked()to achieve the same effect.abort(): Aborts the execution of the process immediately and without any cleanup.prefetch_read_data<T, const LOCALITY: i32>(addr: *const T): Hints the CPU to load data ataddrinto cache for an upcoming read.LOCALITYselects cache behavior (e.g. 0 = L1, 1 = L2, 2 = L3, other = non‑temporal or arch default).prefetch_write_data<T, const LOCALITY: i32>(addr: *const T): Hints the CPU to load a line for an upcoming write. SameLOCALITYsemantics as above.
Guidelines:
- Only prefetch a small distance ahead (tune empirically).
- Too-far or excessive prefetching can evict useful cache lines.
- Never rely on prefetch for correctness; it is purely a performance hint.
Likely/Unlikely example
This example demonstrates how likely can be used to optimize a function. Note that the factorial implementation shown is intentionally simplistic and uses recursion, which is not optimal for production code.
use likely;
To understand the specific effect of likely and unlikely, consider the following example:
use likely;
This produces the following x86-64 assembly:
example::example::h8ce045666cbb1dd5:
mov eax, edi
mov edi, 123
test eax, eax
je .LBB0_1
jmp qword ptr [rip + example::tracker::h1c31dda456fa4d53@GOTPCREL]
.LBB0_1:
mov edi, 255
jmp qword ptr [rip + example::tracker::h1c31dda456fa4d53@GOTPCREL]
Now, if we replace likely(unknown) with unlikely(unknown):
example::example::h8ce045666cbb1dd5:
test edi, edi
jne .LBB0_1
mov edi, 255
jmp qword ptr [rip + example::tracker::h1c31dda456fa4d53@GOTPCREL]
.LBB0_1:
mov edi, 123
jmp qword ptr [rip + example::tracker::h1c31dda456fa4d53@GOTPCREL]
As shown by the swapped positions of the code handling 123 and 255, the compiler eliminates the unconditional jump in the likely path (or places the jump in the unlikely path). This straight-line execution in the expected branch allows the likely path to run faster.
Prefetch example
Loop manual prefetch example:
use ;
By correctly using the functions provided by branches, you can achieve a 10-20% improvement in the performance of your algorithms.
License
branches is licensed under the MIT license. See the LICENSE file for more information.