#![cfg_attr(not(feature = "std"), no_std)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, missing_debug_implementations)]
#![cfg_attr(branches_nightly, feature(core_intrinsics))]
#![cfg_attr(branches_nightly, allow(internal_features))]
#[cfg(all(branches_stable, not(rustc_ge_1_95_0)))]
#[inline(never)]
#[cold]
const fn cold_and_empty() {}
#[cfg(all(branches_stable, rustc_ge_1_95_0))]
use core::hint::cold_path as cold_and_empty;
#[cold]
pub extern "C" fn abort() -> ! {
#[cfg(feature = "std")]
std::process::abort();
#[cfg(all(not(feature = "std"), branches_nightly))]
core::intrinsics::abort();
#[cfg(all(not(feature = "std"), branches_stable))]
panic!("branches::abort() called");
}
#[inline(always)]
pub unsafe fn assume(b: bool) {
#[cfg(branches_stable)]
{
#[cfg(rustc_ge_1_81_0)]
{
core::hint::assert_unchecked(b)
}
#[cfg(not(rustc_ge_1_81_0))]
{
if !b {
core::hint::unreachable_unchecked()
}
}
}
#[cfg(branches_nightly)]
core::intrinsics::assume(b)
}
#[must_use = "the hint only takes effect when the returned value is used as a branch condition"]
#[inline(always)]
pub fn likely(b: bool) -> bool {
#[cfg(branches_stable)]
{
if !b {
cold_and_empty();
}
b
}
#[cfg(branches_nightly)]
core::intrinsics::likely(b)
}
#[cfg(not(rustc_ge_1_95_0))]
#[cold]
#[inline(never)]
pub const fn mark_unlikely() {}
#[cfg(rustc_ge_1_95_0)]
pub use core::hint::cold_path as mark_unlikely;
#[must_use = "the hint only takes effect when the returned value is used as a branch condition"]
#[inline(always)]
pub fn unlikely(b: bool) -> bool {
#[cfg(branches_stable)]
{
if b {
cold_and_empty();
}
b
}
#[cfg(branches_nightly)]
core::intrinsics::unlikely(b)
}
#[inline(always)]
#[cfg(feature = "prefetch")]
pub fn prefetch_read_data<T, const LOCALITY: i32>(addr: *const T) {
let _ = addr;
#[cfg(branches_stable)]
{
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "sse"
))]
unsafe {
match LOCALITY {
0 => core::arch::asm!(
"prefetcht0 [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 1 => core::arch::asm!(
"prefetcht1 [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 2 => core::arch::asm!(
"prefetcht2 [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), _ => core::arch::asm!(
"prefetchnta [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), }
}
#[cfg(target_arch = "aarch64")]
unsafe {
match LOCALITY {
0 => core::arch::asm!(
"prfm pldl1keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 1 => core::arch::asm!(
"prfm pldl2keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 2 => core::arch::asm!(
"prfm pldl3keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), _ => core::arch::asm!(
"prfm pldl1strm, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), }
}
#[cfg(all(target_arch = "riscv64", target_feature = "zicbop"))]
unsafe {
core::arch::asm!(
"prefetch.r 0({})",
in(reg) addr,
options(nostack, readonly, preserves_flags)
);
}
}
#[cfg(branches_nightly)]
{
match LOCALITY {
0 => core::intrinsics::prefetch_read_data::<_, 3>(addr),
1 => core::intrinsics::prefetch_read_data::<_, 2>(addr),
2 => core::intrinsics::prefetch_read_data::<_, 1>(addr),
_ => core::intrinsics::prefetch_read_data::<_, 0>(addr),
}
}
}
#[inline(always)]
#[cfg(feature = "prefetch")]
pub fn prefetch_write_data<T, const LOCALITY: i32>(addr: *const T) {
let _ = addr;
#[cfg(branches_stable)]
{
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::asm!(
"prefetchw [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
) }
#[cfg(all(target_arch = "x86", target_feature = "sse"))]
unsafe {
core::arch::asm!(
"prefetcht0 [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
)
}
#[cfg(target_arch = "aarch64")]
unsafe {
match LOCALITY {
0 => core::arch::asm!(
"prfm pstl1keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 1 => core::arch::asm!(
"prfm pstl2keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), 2 => core::arch::asm!(
"prfm pstl3keep, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), _ => core::arch::asm!(
"prfm pstl1strm, [{}]",
in(reg) addr,
options(nostack, readonly, preserves_flags)
), }
}
#[cfg(all(target_arch = "riscv64", target_feature = "zicbop"))]
unsafe {
core::arch::asm!(
"prefetch.w 0({})",
in(reg) addr,
options(nostack, readonly, preserves_flags)
);
}
}
#[cfg(branches_nightly)]
{
match LOCALITY {
0 => core::intrinsics::prefetch_write_data::<_, 3>(addr),
1 => core::intrinsics::prefetch_write_data::<_, 2>(addr),
2 => core::intrinsics::prefetch_write_data::<_, 1>(addr),
_ => core::intrinsics::prefetch_write_data::<_, 0>(addr),
}
}
}
#[cfg(branches_check_asm)]
#[doc(hidden)]
pub fn __branches_check_asm(addr: *const u8, cond: bool) -> bool {
let _ = addr;
#[cfg(feature = "prefetch")]
{
prefetch_read_data::<_, 0>(addr);
prefetch_read_data::<_, 1>(addr);
prefetch_read_data::<_, 2>(addr);
prefetch_read_data::<_, 3>(addr);
prefetch_read_data::<_, { -1 }>(addr);
prefetch_write_data::<_, 0>(addr);
prefetch_write_data::<_, 1>(addr);
prefetch_write_data::<_, 2>(addr);
prefetch_write_data::<_, 3>(addr);
prefetch_write_data::<_, { -1 }>(addr);
}
if unlikely(!cond) {
mark_unlikely();
}
likely(cond)
}