From 10e0481cfbfe0eaf04761a7f89daffe76ec68125 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Mon, 27 Jul 2020 20:55:57 -0400 Subject: [PATCH 1/2] New name for hint::black_box: pretend_used The current name is a legacy from before RFC 2360. The RFC calls the method `bench_black_box`, though acknowledges that this name is not be ideal either. The main objection to the name during and since the RFC is that it is not truly a black box to the compiler. Instead, the hint only encourages the compiler to consider the passed-in value used. This in the hope that the compiler will materialize that value somewhere, such as in memory or in a register, and not eliminate the input as dead code. This PR proposes to rename the method to `pretend_used`. This clearly indicates the precise semantics the hint conveys to the compiler, without suggesting that it disables further compiler optimizations. The name also reads straightforwardly in code: `hint::pretend_used(x)` hints to the compiler that it should pretend that `x` is used in some arbitrary way. `pretend_used` also rectifies the secondary naming concern the RFC raised with the names `black_box` and `bench_black_box`; the potential confusion with "boxed" values. If this change lands, it completes the naming portion of #64102. --- library/core/src/hint.rs | 22 ++++++++++++---------- library/test/src/bench.rs | 2 +- src/test/ui/sanitize/address.rs | 4 ++-- src/test/ui/sanitize/leak.rs | 4 ++-- src/test/ui/sanitize/memory.rs | 4 ++-- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 3116815f5d655..0995fd3a104ef 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -96,23 +96,25 @@ pub fn spin_loop() { } } -/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what -/// `black_box` could do. +/// An identity function that suggests to the compiler that the given value is used in some +/// arbitrary, unspecified way. /// /// [`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. +/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `pretend_used` +/// may use `x` in any possible valid way that Rust code is allowed to without introducing +/// undefined behavior in the calling code. This property makes `pretend_used` useful for writing +/// code in which certain optimizations are not desired, such as benchmarks. For example, if an +/// expression whose value is never used is passed through `pretend_used`, the compiler is +/// encouraged to compute the value of that expression rather than eliminate it as dead code. /// -/// 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. +/// Note however, that `pretend_used` 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 `pretend_used` 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(dummy: T) -> T { +pub fn pretend_used(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 diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs index e92e5b9829ec2..e1fce5e2a307b 100644 --- a/library/test/src/bench.rs +++ b/library/test/src/bench.rs @@ -1,5 +1,5 @@ //! Benchmarking module. -pub use std::hint::black_box; +pub use std::hint::pretend_used as black_box; use super::{ event::CompletedTest, helpers::sink::Sink, options::BenchMode, test_result::TestResult, diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs index cee73b0425ad5..8e21e1181fb12 100644 --- a/src/test/ui/sanitize/address.rs +++ b/src/test/ui/sanitize/address.rs @@ -9,12 +9,12 @@ #![feature(test)] -use std::hint::black_box; +use std::hint::pretend_used; fn main() { let xs = [0, 1, 2, 3]; // Avoid optimizing everything out. - let xs = black_box(xs.as_ptr()); + let xs = pretend_used(xs.as_ptr()); let code = unsafe { *xs.offset(4) }; std::process::exit(code); } diff --git a/src/test/ui/sanitize/leak.rs b/src/test/ui/sanitize/leak.rs index c9f10fe4f467e..2f5ffe1ce000e 100644 --- a/src/test/ui/sanitize/leak.rs +++ b/src/test/ui/sanitize/leak.rs @@ -8,14 +8,14 @@ #![feature(test)] -use std::hint::black_box; +use std::hint::pretend_used; use std::mem; fn main() { for _ in 0..10 { let xs = vec![1, 2, 3]; // Prevent compiler from removing the memory allocation. - let xs = black_box(xs); + let xs = pretend_used(xs); mem::forget(xs); } } diff --git a/src/test/ui/sanitize/memory.rs b/src/test/ui/sanitize/memory.rs index a26649a580013..91d55316aa082 100644 --- a/src/test/ui/sanitize/memory.rs +++ b/src/test/ui/sanitize/memory.rs @@ -15,7 +15,7 @@ #![feature(start)] #![feature(test)] -use std::hint::black_box; +use std::hint::pretend_used; use std::mem::MaybeUninit; #[inline(never)] @@ -23,7 +23,7 @@ use std::mem::MaybeUninit; fn random() -> [isize; 32] { let r = unsafe { MaybeUninit::uninit().assume_init() }; // Avoid optimizing everything out. - black_box(r) + pretend_used(r) } #[inline(never)] From 940e7be763a36ead6fad6dc89e53f4e5269f7ccf Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 29 Jul 2020 09:10:27 -0400 Subject: [PATCH 2/2] Tweak docs a little --- library/core/src/hint.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 0995fd3a104ef..634232d94b708 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -96,10 +96,8 @@ pub fn spin_loop() { } } -/// An identity function that suggests to the compiler that the given value is used in some -/// arbitrary, unspecified way. -/// -/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html +/// An identity function that asks the compiler to pretend that the given value is used in some +/// arbitrary but valid way. /// /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `pretend_used` /// may use `x` in any possible valid way that Rust code is allowed to without introducing @@ -111,6 +109,8 @@ pub fn spin_loop() { /// Note however, that `pretend_used` 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 `pretend_used` for *correctness* in any way. +/// +/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html #[inline] #[unstable(feature = "test", issue = "50297")] #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.