Skip to content

Commit 5119266

Browse files
committed
Force LLVM to use CMOV for binary search
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`.
1 parent a152820 commit 5119266

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

core/src/intrinsics.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,34 @@ pub const fn unlikely(b: bool) -> bool {
10101010
b
10111011
}
10121012

1013+
/// Returns either `true_val` or `false_val` depending on condition `b` with a
1014+
/// hint to the compiler that this condition is unlikely to be correctly
1015+
/// predicted by a CPU's branch predictor (e.g. a binary search).
1016+
///
1017+
/// This is otherwise functionally equivalent to `if b { true_val } else { false_val }`.
1018+
///
1019+
/// Note that, unlike most intrinsics, this is safe to call;
1020+
/// it does not require an `unsafe` block.
1021+
/// Therefore, implementations must not require the user to uphold
1022+
/// any safety invariants.
1023+
///
1024+
/// This intrinsic does not have a stable counterpart.
1025+
#[cfg(not(bootstrap))]
1026+
#[unstable(feature = "core_intrinsics", issue = "none")]
1027+
#[rustc_intrinsic]
1028+
#[rustc_nounwind]
1029+
#[miri::intrinsic_fallback_is_spec]
1030+
#[inline]
1031+
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
1032+
if b { true_val } else { false_val }
1033+
}
1034+
1035+
#[cfg(bootstrap)]
1036+
#[inline]
1037+
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
1038+
if b { true_val } else { false_val }
1039+
}
1040+
10131041
extern "rust-intrinsic" {
10141042
/// Executes a breakpoint trap, for inspection by a debugger.
10151043
///

0 commit comments

Comments
 (0)