Skip to content

Rollup of 10 pull requests #139746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Apr 13, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0acac2c
std: Fix build for NuttX targets
thaliaarchi Mar 26, 2025
15e1a66
Use -C target-cpu=z13 on s390x vector test
fneddy Mar 31, 2025
44d1d86
libtest: Pass the test's panic payload as Option instead of Result
Zalathar Apr 8, 2025
7711688
update miniz_oxide to 0.8.8
oyvindln Apr 9, 2025
0ca3127
compiletest: Make `SUGGESTION` annotations viral
petrochenkov Apr 10, 2025
909b6c9
compiletest: Turn `TestProps::require_annotations` into a set
petrochenkov Apr 10, 2025
ad72ba2
dev-guide: Document `dont-require-annotations`
petrochenkov Apr 10, 2025
06dd9e2
compiletest: Trim the value of `dont-require-annotations`
petrochenkov Apr 10, 2025
dc0fbca
Fix profiler_builtins build script to handle full path to profiler lib
Apr 11, 2025
b613e97
Use with_native_path for Windows
ChrisDenton Apr 11, 2025
6ffebb6
Move args into std::sys
thaliaarchi Apr 12, 2025
e014fd6
Use unsupported args for espidf and vita
thaliaarchi Apr 12, 2025
bea2022
Unify owned Args types between platforms
thaliaarchi Apr 12, 2025
6ba9649
End all lines in src/stage0 with trailing newline
dtolnay Apr 12, 2025
5d90ccb
Move `select_unpredictable` to the `hint` module
Amanieu Apr 12, 2025
9d2d6a0
Rollup merge of #138972 - thaliaarchi:nuttx-build, r=Mark-Simulacrum
ChrisDenton Apr 13, 2025
f1b31ae
Rollup merge of #139177 - fneddy:fix_s390x_codegen_bswap, r=Mark-Simu…
ChrisDenton Apr 13, 2025
bde65bd
Rollup merge of #139511 - Zalathar:panic-payload, r=Mark-Simulacrum
ChrisDenton Apr 13, 2025
cc9420f
Rollup merge of #139605 - oyvindln:update_miniz_oxide_0_8, r=Mark-Sim…
ChrisDenton Apr 13, 2025
423e7b8
Rollup merge of #139618 - petrochenkov:virsugg, r=jieyouxu
ChrisDenton Apr 13, 2025
f2a2135
Rollup merge of #139677 - jchecahi:profiler-builtin-rtlib-path-fix, r…
ChrisDenton Apr 13, 2025
8a6d6f5
Rollup merge of #139683 - ChrisDenton:windows-with-native, r=tgross35…
ChrisDenton Apr 13, 2025
daed9e2
Rollup merge of #139710 - thaliaarchi:move-args-pal, r=joboet
ChrisDenton Apr 13, 2025
54aff1f
Rollup merge of #139721 - dtolnay:stage0newline, r=onur-ozkan
ChrisDenton Apr 13, 2025
f1d0b9c
Rollup merge of #139726 - Amanieu:select_unpredictable_hint, r=dtolnay
ChrisDenton Apr 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move select_unpredictable to the hint module
  • Loading branch information
Amanieu committed Apr 13, 2025
commit 5d90ccb0fa2e9d2bb0146de225921ebc260b30bb
48 changes: 0 additions & 48 deletions library/core/src/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,52 +61,4 @@ impl bool {
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }
}

/// Returns either `true_val` or `false_val` depending on the value of
/// `self`, with a hint to the compiler that `self` is unlikely
/// to be correctly predicted by a CPU’s branch predictor.
///
/// This method is functionally equivalent to
/// ```ignore (this is just for illustrative purposes)
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
/// if b { true_val } else { false_val }
/// }
/// ```
/// but might generate different assembly. In particular, on platforms with
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
/// on ARM) the optimizer might use these instructions to avoid branches,
/// which can benefit performance if the branch predictor is struggling
/// with predicting `condition`, such as in an implementation of binary
/// search.
///
/// Note however that this lowering is not guaranteed (on any platform) and
/// should not be relied upon when trying to write constant-time code. Also
/// be aware that this lowering might *decrease* performance if `condition`
/// is well-predictable. It is advisable to perform benchmarks to tell if
/// this function is useful.
///
/// # Examples
///
/// Distribute values evenly between two buckets:
/// ```
/// #![feature(select_unpredictable)]
///
/// use std::hash::BuildHasher;
///
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
/// let hash = hasher.hash_one(&v);
/// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two);
/// bucket.push(v);
/// }
/// # let hasher = std::collections::hash_map::RandomState::new();
/// # let mut bucket_one = Vec::new();
/// # let mut bucket_two = Vec::new();
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
/// ```
#[inline(always)]
#[unstable(feature = "select_unpredictable", issue = "133962")]
pub fn select_unpredictable<T>(self, true_val: T, false_val: T) -> T {
crate::intrinsics::select_unpredictable(self, true_val, false_val)
}
}
49 changes: 49 additions & 0 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,52 @@ pub const fn unlikely(b: bool) -> bool {
pub const fn cold_path() {
crate::intrinsics::cold_path()
}

/// Returns either `true_val` or `false_val` depending on the value of `b`,
/// with a hint to the compiler that `b` is unlikely to be correctly
/// predicted by a CPU’s branch predictor.
///
/// This method is functionally equivalent to
/// ```ignore (this is just for illustrative purposes)
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
/// if b { true_val } else { false_val }
/// }
/// ```
/// but might generate different assembly. In particular, on platforms with
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
/// on ARM) the optimizer might use these instructions to avoid branches,
/// which can benefit performance if the branch predictor is struggling
/// with predicting `condition`, such as in an implementation of binary
/// search.
///
/// Note however that this lowering is not guaranteed (on any platform) and
/// should not be relied upon when trying to write constant-time code. Also
/// be aware that this lowering might *decrease* performance if `condition`
/// is well-predictable. It is advisable to perform benchmarks to tell if
/// this function is useful.
///
/// # Examples
///
/// Distribute values evenly between two buckets:
/// ```
/// #![feature(select_unpredictable)]
///
/// use std::hash::BuildHasher;
/// use std::hint;
///
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
/// let hash = hasher.hash_one(&v);
/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two);
/// bucket.push(v);
/// }
/// # let hasher = std::collections::hash_map::RandomState::new();
/// # let mut bucket_one = Vec::new();
/// # let mut bucket_two = Vec::new();
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
/// ```
#[inline(always)]
#[unstable(feature = "select_unpredictable", issue = "133962")]
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
crate::intrinsics::select_unpredictable(b, true_val, false_val)
}
2 changes: 1 addition & 1 deletion library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,7 @@ pub const fn unlikely(b: bool) -> bool {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The public form of this instrinsic is [`bool::select_unpredictable`].
/// The public form of this instrinsic is [`core::hint::select_unpredictable`].
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_nounwind]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2828,7 +2828,7 @@ impl<T> [T] {
// Binary search interacts poorly with branch prediction, so force
// the compiler to use conditional moves if supported by the target
// architecture.
base = (cmp == Greater).select_unpredictable(base, mid);
base = hint::select_unpredictable(cmp == Greater, base, mid);

// This is imprecise in the case where `size` is odd and the
// comparison returns Greater: the mid element still gets included
Expand Down
18 changes: 9 additions & 9 deletions library/core/src/slice/sort/shared/smallsort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::mem::{self, ManuallyDrop, MaybeUninit};
use crate::slice::sort::shared::FreezeMarker;
use crate::{intrinsics, ptr, slice};
use crate::{hint, intrinsics, ptr, slice};

// It's important to differentiate between SMALL_SORT_THRESHOLD performance for
// small slices and small-sort performance sorting small sub-slices as part of
Expand Down Expand Up @@ -408,8 +408,8 @@ where
// }

// The goal is to generate cmov instructions here.
let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
let v_a_swap = hint::select_unpredictable(should_swap, v_b, v_a);
let v_b_swap = hint::select_unpredictable(should_swap, v_a, v_b);

let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
ptr::copy(v_a_swap, v_a, 1);
Expand Down Expand Up @@ -640,15 +640,15 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
// 1, 1 | c b a d
let c3 = is_less(&*c, &*a);
let c4 = is_less(&*d, &*b);
let min = c3.select_unpredictable(c, a);
let max = c4.select_unpredictable(b, d);
let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
let min = hint::select_unpredictable(c3, c, a);
let max = hint::select_unpredictable(c4, b, d);
let unknown_left = hint::select_unpredictable(c3, a, hint::select_unpredictable(c4, c, b));
let unknown_right = hint::select_unpredictable(c4, d, hint::select_unpredictable(c3, b, c));

// Sort the last two unknown elements.
let c5 = is_less(&*unknown_right, &*unknown_left);
let lo = c5.select_unpredictable(unknown_right, unknown_left);
let hi = c5.select_unpredictable(unknown_left, unknown_right);
let lo = hint::select_unpredictable(c5, unknown_right, unknown_left);
let hi = hint::select_unpredictable(c5, unknown_left, unknown_right);

ptr::copy_nonoverlapping(min, dst, 1);
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
Expand Down
8 changes: 4 additions & 4 deletions tests/codegen/intrinsics/select_unpredictable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,27 @@ pub fn test_zst(p: bool, a: (), b: ()) -> () {
pub fn test_int2(p: bool, a: u64, b: u64) -> u64 {
// CHECK-LABEL: define{{.*}} @test_int2
// CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable
p.select_unpredictable(a, b)
core::hint::select_unpredictable(p, a, b)
}

#[no_mangle]
pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) {
// CHECK-LABEL: define{{.*}} @test_pair2
// CHECK: select i1 %p, {{.*}}, !unpredictable
p.select_unpredictable(a, b)
core::hint::select_unpredictable(p, a, b)
}

#[no_mangle]
pub fn test_struct2(p: bool, a: Large, b: Large) -> Large {
// CHECK-LABEL: define{{.*}} @test_struct2
// CHECK: select i1 %p, {{.*}}, !unpredictable
p.select_unpredictable(a, b)
core::hint::select_unpredictable(p, a, b)
}

#[no_mangle]
pub fn test_zst2(p: bool, a: (), b: ()) -> () {
// CHECK-LABEL: define{{.*}} @test_zst2
// CHECK-NEXT: start:
// CHECK-NEXT: ret void
p.select_unpredictable(a, b)
core::hint::select_unpredictable(p, a, b)
}
Loading