Skip to content

Commit c029b14

Browse files
committed
Auto merge of #111113 - scottmcm:assume-align-offset, r=thomcc
`assume` the runtime range of `align_offset` Found when I saw code with `align_to` having extraneous checks. Demo that LLVM can't do this today: <https://rust.godbolt.org/z/6dnG749bq> (It's filed as llvm/llvm-project#62502.)
2 parents 664d5b0 + ad1645f commit c029b14

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
#![feature(const_arguments_as_str)]
108108
#![feature(const_array_from_ref)]
109109
#![feature(const_array_into_iter_constructors)]
110+
#![feature(const_assume)]
110111
#![feature(const_bigint_helper_methods)]
111112
#![feature(const_black_box)]
112113
#![feature(const_caller_location)]

core/src/ptr/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,8 +1632,8 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
16321632
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
16331633
// 1, where the method versions of these operations are not inlined.
16341634
use intrinsics::{
1635-
cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, unchecked_shr,
1636-
unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub,
1635+
assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl,
1636+
unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub,
16371637
};
16381638

16391639
/// Calculate multiplicative modular inverse of `x` modulo `m`.
@@ -1724,12 +1724,18 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
17241724
// in a branch-free way and then bitwise-OR it with whatever result the `-p mod a`
17251725
// computation produces.
17261726

1727+
let aligned_address = wrapping_add(addr, a_minus_one) & wrapping_sub(0, a);
1728+
let byte_offset = wrapping_sub(aligned_address, addr);
1729+
// FIXME: Remove the assume after <https://github.com/llvm/llvm-project/issues/62502>
1730+
// SAFETY: Masking by `-a` can only affect the low bits, and thus cannot have reduced
1731+
// the value by more than `a-1`, so even though the intermediate values might have
1732+
// wrapped, the byte_offset is always in `[0, a)`.
1733+
unsafe { assume(byte_offset < a) };
1734+
17271735
// SAFETY: `stride == 0` case has been handled by the special case above.
17281736
let addr_mod_stride = unsafe { unchecked_rem(addr, stride) };
17291737

17301738
return if addr_mod_stride == 0 {
1731-
let aligned_address = wrapping_add(addr, a_minus_one) & wrapping_sub(0, a);
1732-
let byte_offset = wrapping_sub(aligned_address, addr);
17331739
// SAFETY: `stride` is non-zero. This is guaranteed to divide exactly as well, because
17341740
// addr has been verified to be aligned to the original type’s alignment requirements.
17351741
unsafe { exact_div(byte_offset, stride) }

0 commit comments

Comments
 (0)