Skip to content

Commit

Permalink
Force LLVM to use CMOV for binary search
Browse files Browse the repository at this point in the history
Since https://reviews.llvm.org/D118118, LLVM will no longer turn CMOVs
into branches if it comes from a `select` marked with an `unpredictable`
metadata attribute.

This PR introduces `core::intrinsics::select_unpredictable` which emits
such a `select` and uses it in the implementation of `binary_search_by`.
  • Loading branch information
Amanieu committed Jul 28, 2024
1 parent a152820 commit 5119266
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,34 @@ pub const fn unlikely(b: bool) -> bool {
b
}

/// Returns either `true_val` or `false_val` depending on condition `b` with a
/// hint to the compiler that this condition is unlikely to be correctly
/// predicted by a CPU's branch predictor (e.g. a binary search).
///
/// This is otherwise functionally equivalent to `if b { true_val } else { false_val }`.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// This intrinsic does not have a stable counterpart.
#[cfg(not(bootstrap))]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_nounwind]
#[miri::intrinsic_fallback_is_spec]
#[inline]
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
if b { true_val } else { false_val }
}

#[cfg(bootstrap)]
#[inline]
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
if b { true_val } else { false_val }
}

extern "rust-intrinsic" {
/// Executes a breakpoint trap, for inspection by a debugger.
///
Expand Down

0 comments on commit 5119266

Please sign in to comment.