diff options
| author | Markus Everling <markuseverling@gmail.com> | 2023-05-06 17:31:51 +0000 |
|---|---|---|
| committer | Markus Everling <markuseverling@gmail.com> | 2023-05-06 17:31:51 +0000 |
| commit | b5ee324d79b310761b98173825895b16b859361b (patch) | |
| tree | bf9627fbace077fb46c6340cad3b10751720f4e7 | |
| parent | 333b920feeb136d35fac804d51310df1a35c399e (diff) | |
| download | rust-b5ee324d79b310761b98173825895b16b859361b.tar.gz rust-b5ee324d79b310761b98173825895b16b859361b.zip | |
Always const-eval the gcd in `slice::align_to_offsets`
| -rw-r--r-- | library/core/src/slice/mod.rs | 43 |
1 files changed, 6 insertions, 37 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d4981af90d1..28a6c05c383 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3474,44 +3474,13 @@ impl<T> [T] { // Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>) // // Luckily since all this is constant-evaluated... performance here matters not! - #[inline] - fn gcd(a: usize, b: usize) -> usize { - use crate::intrinsics; - // iterative stein’s algorithm - // We should still make this `const fn` (and revert to recursive algorithm if we do) - // because relying on llvm to consteval all this is… well, it makes me uncomfortable. - - // SAFETY: `a` and `b` are checked to be non-zero values. - let (ctz_a, mut ctz_b) = unsafe { - if a == 0 { - return b; - } - if b == 0 { - return a; - } - (intrinsics::cttz_nonzero(a), intrinsics::cttz_nonzero(b)) - }; - let k = ctz_a.min(ctz_b); - let mut a = a >> ctz_a; - let mut b = b; - loop { - // remove all factors of 2 from b - b >>= ctz_b; - if a > b { - mem::swap(&mut a, &mut b); - } - b = b - a; - // SAFETY: `b` is checked to be non-zero. - unsafe { - if b == 0 { - break; - } - ctz_b = intrinsics::cttz_nonzero(b); - } - } - a << k + const fn gcd(a: usize, b: usize) -> usize { + if b == 0 { a } else { gcd(b, a % b) } } - let gcd: usize = gcd(mem::size_of::<T>(), mem::size_of::<U>()); + + // Explicitly wrap the function call in a const block so it gets + // constant-evaluated even in debug mode. + let gcd: usize = const { gcd(mem::size_of::<T>(), mem::size_of::<U>()) }; let ts: usize = mem::size_of::<U>() / gcd; let us: usize = mem::size_of::<T>() / gcd; |
