]> git.lizzy.rs Git - rust.git/blob - src/libcore/hint.rs
Auto merge of #66603 - Nadrieril:fix-65413, r=varkor
[rust.git] / src / libcore / hint.rs
1 #![stable(feature = "core_hint", since = "1.27.0")]
2
3 //! Hints to compiler that affects how code should be emitted or optimized.
4
5 // ignore-tidy-undocumented-unsafe
6
7 use crate::intrinsics;
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 ///
19 /// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
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.
26 /// Otherwise, consider using the [`unreachable!`] macro, which does not allow
27 /// optimizations but will panic when executed.
28 ///
29 /// [`unreachable!`]: ../macro.unreachable.html
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),
38 ///     // hence `checked_div` will never return `None`.
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")]
50 pub unsafe fn unreachable_unchecked() -> ! {
51     intrinsics::unreachable()
52 }
53
54 /// Emits a machine instruction hinting to the processor that it is running in busy-wait
55 /// spin-loop ("spin lock").
56 ///
57 /// For a discussion of different locking strategies and their trade-offs, see
58 /// [`core::sync::atomic::spin_loop_hint`].
59 ///
60 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
61 /// do anything at all.
62 ///
63 /// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
64 #[inline]
65 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
66 pub fn spin_loop() {
67     #[cfg(
68         all(
69             any(target_arch = "x86", target_arch = "x86_64"),
70             target_feature = "sse2"
71         )
72     )] {
73         #[cfg(target_arch = "x86")] {
74             unsafe { crate::arch::x86::_mm_pause() };
75         }
76
77         #[cfg(target_arch = "x86_64")] {
78             unsafe { crate::arch::x86_64::_mm_pause() };
79         }
80     }
81
82     #[cfg(
83         any(
84             target_arch = "aarch64",
85             all(target_arch = "arm", target_feature = "v6")
86         )
87     )] {
88         #[cfg(target_arch = "aarch64")] {
89             unsafe { crate::arch::aarch64::__yield() };
90         }
91         #[cfg(target_arch = "arm")] {
92             unsafe { crate::arch::arm::__yield() };
93         }
94     }
95 }
96
97 /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
98 /// `black_box` could do.
99 ///
100 /// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
101 ///
102 /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
103 /// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
104 /// behavior in the calling code. This property makes `black_box` useful for writing code in which
105 /// certain optimizations are not desired, such as benchmarks.
106 ///
107 /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
108 /// extent to which it can block optimisations may vary depending upon the platform and code-gen
109 /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
110 #[inline]
111 #[unstable(feature = "test", issue = "50297")]
112 #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
113 pub fn black_box<T>(dummy: T) -> T {
114     // We need to "use" the argument in some way LLVM can't introspect, and on
115     // targets that support it we can typically leverage inline assembly to do
116     // this. LLVM's interpretation of inline assembly is that it's, well, a black
117     // box. This isn't the greatest implementation since it probably deoptimizes
118     // more than we want, but it's so far good enough.
119     unsafe {
120         asm!("" : : "r"(&dummy));
121         return dummy;
122     }
123 }