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