Make checked
ops emit *unchecked* LLVM operations where feasible
For things with easily pre-checked overflow conditions -- shifts and unsigned subtraction -- write then checked methods in such a way that we stop emitting wrapping versions of them. For example, today <https://rust.godbolt.org/z/qM9YK8Txb> neither ```rust a.checked_sub(b).unwrap() ``` nor ```rust a.checked_sub(b).unwrap_unchecked() ``` actually optimizes to `sub nuw`. After this PR they do.
This commit is contained in:
parent
e3181b091e
commit
986d9f104b
6 changed files with 160 additions and 91 deletions
|
@ -1163,12 +1163,19 @@ macro_rules! int_impl {
|
|||
/// ```
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
|
||||
// We could always go back to wrapping
|
||||
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shl(rhs);
|
||||
if unlikely!(b) { None } else { Some(a) }
|
||||
// Not using overflowing_shl as that's a wrapping shift
|
||||
if rhs < Self::BITS {
|
||||
// SAFETY: just checked the RHS is in-range
|
||||
Some(unsafe { self.unchecked_shl(rhs) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger
|
||||
|
@ -1254,12 +1261,19 @@ macro_rules! int_impl {
|
|||
/// ```
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")]
|
||||
// We could always go back to wrapping
|
||||
#[rustc_allow_const_fn_unstable(unchecked_shifts)]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shr(rhs);
|
||||
if unlikely!(b) { None } else { Some(a) }
|
||||
// Not using overflowing_shr as that's a wrapping shift
|
||||
if rhs < Self::BITS {
|
||||
// SAFETY: just checked the RHS is in-range
|
||||
Some(unsafe { self.unchecked_shr(rhs) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Strict shift right. Computes `self >> rhs`, panicking `rhs` is
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue