Skip to content

Commit 4d1253b

Browse files
committed
Auto merge of rust-lang#119911 - NCGThompson:is-statically-known, r=oli-obk
Replacement of rust-lang#114390: Add new intrinsic `is_var_statically_known` and optimize pow for powers of two This adds a new intrinsic `is_val_statically_known` that lowers to [``@llvm.is.constant.*`](https://llvm.org/docs/LangRef.html#llvm-is-constant-intrinsic).` It also applies the intrinsic in the int_pow methods to recognize and optimize the idiom `2isize.pow(x)`. See rust-lang#114390 for more discussion. While I have extended the scope of the power of two optimization from rust-lang#114390, I haven't added any new uses for the intrinsic. That can be done in later pull requests. Note: When testing or using the library, be sure to use `--stage 1` or higher. Otherwise, the intrinsic will be a noop and the doctests will be skipped. If you are trying out edits, you may be interested in [`--keep-stage 0`](https://rustc-dev-guide.rust-lang.org/building/suggested.html#faster-builds-with---keep-stage). Fixes rust-lang#47234 Resolves rust-lang#114390 `@Centri3`
2 parents 2d76d7a + 8fd21eb commit 4d1253b

File tree

4 files changed

+445
-149
lines changed

4 files changed

+445
-149
lines changed

core/src/intrinsics.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,6 +2517,66 @@ extern "rust-intrinsic" {
25172517
where
25182518
G: FnOnce<ARG, Output = RET>,
25192519
F: FnOnce<ARG, Output = RET>;
2520+
2521+
/// Returns whether the argument's value is statically known at
2522+
/// compile-time.
2523+
///
2524+
/// This is useful when there is a way of writing the code that will
2525+
/// be *faster* when some variables have known values, but *slower*
2526+
/// in the general case: an `if is_val_statically_known(var)` can be used
2527+
/// to select between these two variants. The `if` will be optimized away
2528+
/// and only the desired branch remains.
2529+
///
2530+
/// Formally speaking, this function non-deterministically returns `true`
2531+
/// or `false`, and the caller has to ensure sound behavior for both cases.
2532+
/// In other words, the following code has *Undefined Behavior*:
2533+
///
2534+
/// ```
2535+
/// #![feature(is_val_statically_known)]
2536+
/// #![feature(core_intrinsics)]
2537+
/// # #![allow(internal_features)]
2538+
/// use std::hint::unreachable_unchecked;
2539+
/// use std::intrinsics::is_val_statically_known;
2540+
///
2541+
/// unsafe {
2542+
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
2543+
/// }
2544+
/// ```
2545+
///
2546+
/// This also means that the following code's behavior is unspecified; it
2547+
/// may panic, or it may not:
2548+
///
2549+
/// ```no_run
2550+
/// #![feature(is_val_statically_known)]
2551+
/// #![feature(core_intrinsics)]
2552+
/// # #![allow(internal_features)]
2553+
/// use std::intrinsics::is_val_statically_known;
2554+
///
2555+
/// unsafe {
2556+
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
2557+
/// }
2558+
/// ```
2559+
///
2560+
/// Unsafe code may not rely on `is_val_statically_known` returning any
2561+
/// particular value, ever. However, the compiler will generally make it
2562+
/// return `true` only if the value of the argument is actually known.
2563+
///
2564+
/// When calling this in a `const fn`, both paths must be semantically
2565+
/// equivalent, that is, the result of the `true` branch and the `false`
2566+
/// branch must return the same value and have the same side-effects *no
2567+
/// matter what*.
2568+
#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")]
2569+
#[rustc_nounwind]
2570+
#[cfg(not(bootstrap))]
2571+
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
2572+
}
2573+
2574+
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
2575+
// and thus compiling stage0 core doesn't work.
2576+
#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")]
2577+
#[cfg(bootstrap)]
2578+
pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2579+
false
25202580
}
25212581

25222582
// Some functions are defined here because they accidentally got made

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@
200200
//
201201
// Language features:
202202
// tidy-alphabetical-start
203+
#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
203204
#![feature(abi_unadjusted)]
204205
#![feature(adt_const_params)]
205206
#![feature(allow_internal_unsafe)]

0 commit comments

Comments
 (0)