-
Notifications
You must be signed in to change notification settings - Fork 13.4k
unchecked_{shl|shr}
should use u32
as the RHS
#103456
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -757,10 +757,11 @@ macro_rules! int_impl { | |
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] | ||
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self { | ||
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_shl`. | ||
unsafe { intrinsics::unchecked_shl(self, rhs) } | ||
// Any legal shift amount is losslessly representable in the self type. | ||
unsafe { intrinsics::unchecked_shl(self, rhs.try_into().ok().unwrap_unchecked()) } | ||
} | ||
|
||
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is | ||
|
@@ -804,10 +805,11 @@ macro_rules! int_impl { | |
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")] | ||
#[inline(always)] | ||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | ||
pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self { | ||
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { | ||
// SAFETY: the caller must uphold the safety contract for | ||
// `unchecked_shr`. | ||
unsafe { intrinsics::unchecked_shr(self, rhs) } | ||
// Any legal shift amount is losslessly representable in the self type. | ||
unsafe { intrinsics::unchecked_shr(self, rhs.try_into().ok().unwrap_unchecked()) } | ||
} | ||
|
||
/// Checked absolute value. Computes `self.abs()`, returning `None` if | ||
|
@@ -1354,11 +1356,12 @@ macro_rules! int_impl { | |
#[must_use = "this returns the result of the operation, \ | ||
without modifying the original"] | ||
#[inline(always)] | ||
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)] | ||
pub const fn wrapping_shl(self, rhs: u32) -> Self { | ||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift | ||
// out of bounds | ||
unsafe { | ||
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) | ||
self.unchecked_shl(rhs & ($BITS - 1)) | ||
} | ||
} | ||
|
||
|
@@ -1383,11 +1386,12 @@ macro_rules! int_impl { | |
#[must_use = "this returns the result of the operation, \ | ||
without modifying the original"] | ||
#[inline(always)] | ||
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. annot: this was previously using the intrinsic on stable, so the |
||
pub const fn wrapping_shr(self, rhs: u32) -> Self { | ||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift | ||
// out of bounds | ||
unsafe { | ||
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) | ||
self.unchecked_shr(rhs & ($BITS - 1)) | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// compile-flags: -O | ||
// min-llvm-version: 15.0 (LLVM 13 in CI does this differently from submodule LLVM) | ||
// ignore-debug (because unchecked is checked in debug) | ||
|
||
#![crate_type = "lib"] | ||
#![feature(unchecked_math)] | ||
|
||
// CHECK-LABEL: @unchecked_shl_unsigned_same | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 { | ||
// CHECK-NOT: and i32 | ||
// CHECK: shl i32 %a, %b | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. annot: the LLVM instruction always gives poison by default for too-high shift amounts (https://llvm.org/docs/LangRef.html#shl-instruction), so no extra flags are expected in the IR. |
||
// CHECK-NOT: and i32 | ||
a.unchecked_shl(b) | ||
} | ||
|
||
// CHECK-LABEL: @unchecked_shl_unsigned_smaller | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { | ||
// This uses -DAG to avoid failing on irrelevant reorderings, | ||
// like emitting the truncation earlier. | ||
|
||
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 65536 | ||
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]]) | ||
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16 | ||
// CHECK-DAG: shl i16 %a, %[[TRUNC]] | ||
a.unchecked_shl(b) | ||
} | ||
|
||
// CHECK-LABEL: @unchecked_shl_unsigned_bigger | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { | ||
// CHECK: %[[EXT:.+]] = zext i32 %b to i64 | ||
// CHECK: shl i64 %a, %[[EXT]] | ||
a.unchecked_shl(b) | ||
} | ||
|
||
// CHECK-LABEL: @unchecked_shr_signed_same | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 { | ||
// CHECK-NOT: and i32 | ||
// CHECK: ashr i32 %a, %b | ||
// CHECK-NOT: and i32 | ||
a.unchecked_shr(b) | ||
} | ||
|
||
// CHECK-LABEL: @unchecked_shr_signed_smaller | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { | ||
// This uses -DAG to avoid failing on irrelevant reorderings, | ||
// like emitting the truncation earlier. | ||
|
||
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 32768 | ||
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]]) | ||
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16 | ||
// CHECK-DAG: ashr i16 %a, %[[TRUNC]] | ||
a.unchecked_shr(b) | ||
} | ||
|
||
// CHECK-LABEL: @unchecked_shr_signed_bigger | ||
#[no_mangle] | ||
pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { | ||
// CHECK: %[[EXT:.+]] = zext i32 %b to i64 | ||
// CHECK: ashr i64 %a, %[[EXT]] | ||
a.unchecked_shr(b) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
annot: the
.ok()
looks silly here, butResult::unwrap_unchecked
isn'tconst
, whereasOption::unwrap_unchecked
isconst
.