about summary refs log tree commit diff
path: root/library/core/src/hint.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/hint.rs')
-rw-r--r--library/core/src/hint.rs127
1 files changed, 127 insertions, 0 deletions
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
new file mode 100644
index 00000000000..3116815f5d6
--- /dev/null
+++ b/library/core/src/hint.rs
@@ -0,0 +1,127 @@
+#![stable(feature = "core_hint", since = "1.27.0")]
+
+//! Hints to compiler that affects how code should be emitted or optimized.
+
+use crate::intrinsics;
+
+/// Informs the compiler that this point in the code is not reachable, enabling
+/// further optimizations.
+///
+/// # Safety
+///
+/// Reaching this function is completely *undefined behavior* (UB). In
+/// particular, the compiler assumes that all UB must never happen, and
+/// therefore will eliminate all branches that reach to a call to
+/// `unreachable_unchecked()`.
+///
+/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
+/// `unreachable_unchecked()` call is actually reachable among all possible
+/// control flow, the compiler will apply the wrong optimization strategy, and
+/// may sometimes even corrupt seemingly unrelated code, causing
+/// difficult-to-debug problems.
+///
+/// Use this function only when you can prove that the code will never call it.
+/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
+/// optimizations but will panic when executed.
+///
+/// [`unreachable!`]: ../macro.unreachable.html
+///
+/// # Example
+///
+/// ```
+/// fn div_1(a: u32, b: u32) -> u32 {
+///     use std::hint::unreachable_unchecked;
+///
+///     // `b.saturating_add(1)` is always positive (not zero),
+///     // hence `checked_div` will never return `None`.
+///     // Therefore, the else branch is unreachable.
+///     a.checked_div(b.saturating_add(1))
+///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
+/// }
+///
+/// assert_eq!(div_1(7, 0), 7);
+/// assert_eq!(div_1(9, 1), 4);
+/// assert_eq!(div_1(11, u32::MAX), 0);
+/// ```
+#[inline]
+#[stable(feature = "unreachable", since = "1.27.0")]
+#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
+pub const unsafe fn unreachable_unchecked() -> ! {
+    // SAFETY: the safety contract for `intrinsics::unreachable` must
+    // be upheld by the caller.
+    unsafe { intrinsics::unreachable() }
+}
+
+/// Emits a machine instruction hinting to the processor that it is running in busy-wait
+/// spin-loop ("spin lock").
+///
+/// For a discussion of different locking strategies and their trade-offs, see
+/// [`core::sync::atomic::spin_loop_hint`].
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
+/// do anything at all.
+///
+/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
+#[inline]
+#[unstable(feature = "renamed_spin_loop", issue = "55002")]
+pub fn spin_loop() {
+    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
+    {
+        #[cfg(target_arch = "x86")]
+        {
+            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
+            unsafe { crate::arch::x86::_mm_pause() };
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
+            unsafe { crate::arch::x86_64::_mm_pause() };
+        }
+    }
+
+    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
+    {
+        #[cfg(target_arch = "aarch64")]
+        {
+            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
+            unsafe { crate::arch::aarch64::__yield() };
+        }
+        #[cfg(target_arch = "arm")]
+        {
+            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
+            // with support for the v6 feature.
+            unsafe { crate::arch::arm::__yield() };
+        }
+    }
+}
+
+/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
+/// `black_box` could do.
+///
+/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
+///
+/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
+/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
+/// behavior in the calling code. This property makes `black_box` useful for writing code in which
+/// certain optimizations are not desired, such as benchmarks.
+///
+/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
+/// extent to which it can block optimisations may vary depending upon the platform and code-gen
+/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
+#[inline]
+#[unstable(feature = "test", issue = "50297")]
+#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
+pub fn black_box<T>(dummy: T) -> T {
+    // We need to "use" the argument in some way LLVM can't introspect, and on
+    // targets that support it we can typically leverage inline assembly to do
+    // this. LLVM's interpretation of inline assembly is that it's, well, a black
+    // box. This isn't the greatest implementation since it probably deoptimizes
+    // more than we want, but it's so far good enough.
+
+    // SAFETY: the inline assembly is a no-op.
+    unsafe {
+        llvm_asm!("" : : "r"(&dummy));
+        dummy
+    }
+}