-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make saturating_add
and saturating_sub
const
functions
#58030
Comments
I'd really like to do this! |
It's all yours! If anything is unclear, don't hesitate to ask. |
Thanks! I have some questions, please let me know if I'm misunderstanding anything... Is it correct that the point of this ticket is to avoid code generation (LLVM intrinsics) by evaluating during compilation (const eval intrinsics), where previously LLVM branching code was generated? Is there already compiler logic to detect non immediate arguments/terms so that the LLVM code is generated even after the functions are whitelisted as const? I can't find any compiler code where calls to n.saturating_add(m) are wrapped in unsafe blocks, and why would they be? Also, are the implementation guidelines saying that all functions with calls to these two functions can be marked as const? Why would that be, irregardless of other statements in the function? |
Not quite. For normal code, the LLVM intrinsics will still be generated (at which point LLVM may evaluate them during optimization, but that's a different matter). Making the intrinsics const just means that they can be used in contexts where the result must be evaluated during compilation. It allows you to write something like
You need to separate two things here: The
This refers to the functions that call the intrinsics, which should just be the |
No. This is to make the CTFE engine in Rust support these intrinsics. When you write fn main() {
const x: u8 = 13u8.saturating_sub(66);
} CTFE is very different from const propagation, which is an optimization that opportunistically will try to evaluate code at compile-time. Const propagation is performed by LLVM, rustc does not have to do anything for it to happen. |
Thanks for the help guys. Currently the num module saturating_add() wrapper only uses the intrinsic for stage 1+, so the function can't just be marked as const because of the non const checked_add() call in the stage 0 compiler. Looks like other intrinsic calls don't need the stage guards so not sure what the issue is. Does this need to wait for the bootstrapping compile version to advance or something? Also not sure about the special // ~> comments... |
@pmccarter I believe the way to handle this would be to move the cfg to cover the whole function. You'd have a stage0 variant that is non-const and also uses the old checked_add based implementation, and you'd have a not(stage0) variant that is const and uses the saturating_add intrinsic based implementation. So basically instead of pub fn saturating_add(self, rhs: Self) -> Self {
#[cfg(stage0)]
match self.checked_add(rhs) {
Some(x) => x,
None => Self::max_value(),
}
#[cfg(not(stage0))]
{
intrinsics::saturating_add(self, rhs)
}
} you'd have #[cfg(stage0)]
pub fn saturating_add(self, rhs: Self) -> Self {
match self.checked_add(rhs) {
Some(x) => x,
None => Self::max_value(),
}
}
#[cfg(not(stage0))]
pub const fn saturating_add(self, rhs: Self) -> Self {
intrinsics::saturating_add(self, rhs)
} |
Make `saturating_add` and `saturating_sub` `const` functions Fixes #58030
Make `saturating_add` and `saturating_sub` `const` functions Fixes #58030
These used to require
if
to work, but are forwarded to llvm intrinsics nowadays (#58003). We can now implement them as const eval intrinsics, too.Impl instructions:
rust/src/librustc_mir/transform/qualify_min_const_fn.rs
Line 371 in 0c0c585
unsafe
for calls to the intrinsicrust/src/librustc_mir/transform/qualify_consts.rs
Line 820 in 51cc3cd
const fn
rust/src/librustc_mir/interpret/intrinsics.rs
Line 102 in 79d8a0f
read_immediate
calls, a call tobinary_op_imm
with arguments similar to the other add/sub intrinsics, in case the overflow bool in the return value is false, write the actual value to the destination like inrust/src/librustc_mir/interpret/operator.rs
Line 36 in 79d8a0f
rust/src/librustc_mir/interpret/operator.rs
Line 217 in 79d8a0f
dest
.The text was updated successfully, but these errors were encountered: