]> git.proxmox.com Git - rustc.git/blame - src/libcore/hint.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libcore / hint.rs
CommitLineData
83c7162d
XL
1#![stable(feature = "core_hint", since = "1.27.0")]
2
3//! Hints to compiler that affects how code should be emitted or optimized.
4
60c5eb7d
XL
5// ignore-tidy-undocumented-unsafe
6
48663c56 7use crate::intrinsics;
83c7162d
XL
8
9/// Informs the compiler that this point in the code is not reachable, enabling
10/// further optimizations.
11///
12/// # Safety
13///
14/// Reaching this function is completely *undefined behavior* (UB). In
15/// particular, the compiler assumes that all UB must never happen, and
16/// therefore will eliminate all branches that reach to a call to
17/// `unreachable_unchecked()`.
18///
0731742a 19/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
83c7162d
XL
20/// `unreachable_unchecked()` call is actually reachable among all possible
21/// control flow, the compiler will apply the wrong optimization strategy, and
22/// may sometimes even corrupt seemingly unrelated code, causing
23/// difficult-to-debug problems.
24///
25/// Use this function only when you can prove that the code will never call it.
48663c56
XL
26/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
27/// optimizations but will panic when executed.
83c7162d 28///
48663c56 29/// [`unreachable!`]: ../macro.unreachable.html
83c7162d
XL
30///
31/// # Example
32///
33/// ```
34/// fn div_1(a: u32, b: u32) -> u32 {
35/// use std::hint::unreachable_unchecked;
36///
37/// // `b.saturating_add(1)` is always positive (not zero),
9fa01778 38/// // hence `checked_div` will never return `None`.
83c7162d
XL
39/// // Therefore, the else branch is unreachable.
40/// a.checked_div(b.saturating_add(1))
41/// .unwrap_or_else(|| unsafe { unreachable_unchecked() })
42/// }
43///
44/// assert_eq!(div_1(7, 0), 7);
45/// assert_eq!(div_1(9, 1), 4);
46/// assert_eq!(div_1(11, std::u32::MAX), 0);
47/// ```
48#[inline]
49#[stable(feature = "unreachable", since = "1.27.0")]
50pub unsafe fn unreachable_unchecked() -> ! {
51 intrinsics::unreachable()
52}
9fa01778 53
e1599b0c
XL
54/// Emits a machine instruction hinting to the processor that it is running in busy-wait
55/// spin-loop ("spin lock").
9fa01778 56///
e1599b0c
XL
57/// For a discussion of different locking strategies and their trade-offs, see
58/// [`core::sync::atomic::spin_loop_hint`].
532ac7d7
XL
59///
60/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
61/// do anything at all.
62///
e1599b0c 63/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
9fa01778
XL
64#[inline]
65#[unstable(feature = "renamed_spin_loop", issue = "55002")]
66pub fn spin_loop() {
60c5eb7d
XL
67 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
68 {
69 #[cfg(target_arch = "x86")]
70 {
532ac7d7
XL
71 unsafe { crate::arch::x86::_mm_pause() };
72 }
73
60c5eb7d
XL
74 #[cfg(target_arch = "x86_64")]
75 {
532ac7d7
XL
76 unsafe { crate::arch::x86_64::_mm_pause() };
77 }
9fa01778
XL
78 }
79
60c5eb7d
XL
80 #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
81 {
82 #[cfg(target_arch = "aarch64")]
83 {
532ac7d7
XL
84 unsafe { crate::arch::aarch64::__yield() };
85 }
60c5eb7d
XL
86 #[cfg(target_arch = "arm")]
87 {
532ac7d7
XL
88 unsafe { crate::arch::arm::__yield() };
89 }
90 }
91}
92
e1599b0c
XL
93/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
94/// `black_box` could do.
95///
96/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
97///
98/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
99/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
100/// behavior in the calling code. This property makes `black_box` useful for writing code in which
101/// certain optimizations are not desired, such as benchmarks.
532ac7d7 102///
e1599b0c
XL
103/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
104/// extent to which it can block optimisations may vary depending upon the platform and code-gen
105/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
532ac7d7 106#[inline]
416331ca 107#[unstable(feature = "test", issue = "50297")]
dc9dc135 108#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
532ac7d7 109pub fn black_box<T>(dummy: T) -> T {
dc9dc135
XL
110 // We need to "use" the argument in some way LLVM can't introspect, and on
111 // targets that support it we can typically leverage inline assembly to do
60c5eb7d 112 // this. LLVM's interpretation of inline assembly is that it's, well, a black
dc9dc135
XL
113 // box. This isn't the greatest implementation since it probably deoptimizes
114 // more than we want, but it's so far good enough.
dc9dc135
XL
115 unsafe {
116 asm!("" : : "r"(&dummy));
117 return dummy;
118 }
9fa01778 119}