Skip to content

Commit b5ee324

Browse files
committed
Always const-eval the gcd in slice::align_to_offsets
1 parent 333b920 commit b5ee324

File tree

1 file changed

+6
-37
lines changed

1 file changed

+6
-37
lines changed

library/core/src/slice/mod.rs

+6-37
Original file line numberDiff line numberDiff line change
@@ -3474,44 +3474,13 @@ impl<T> [T] {
34743474
// Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>)
34753475
//
34763476
// Luckily since all this is constant-evaluated... performance here matters not!
3477-
#[inline]
3478-
fn gcd(a: usize, b: usize) -> usize {
3479-
use crate::intrinsics;
3480-
// iterative stein’s algorithm
3481-
// We should still make this `const fn` (and revert to recursive algorithm if we do)
3482-
// because relying on llvm to consteval all this is… well, it makes me uncomfortable.
3483-
3484-
// SAFETY: `a` and `b` are checked to be non-zero values.
3485-
let (ctz_a, mut ctz_b) = unsafe {
3486-
if a == 0 {
3487-
return b;
3488-
}
3489-
if b == 0 {
3490-
return a;
3491-
}
3492-
(intrinsics::cttz_nonzero(a), intrinsics::cttz_nonzero(b))
3493-
};
3494-
let k = ctz_a.min(ctz_b);
3495-
let mut a = a >> ctz_a;
3496-
let mut b = b;
3497-
loop {
3498-
// remove all factors of 2 from b
3499-
b >>= ctz_b;
3500-
if a > b {
3501-
mem::swap(&mut a, &mut b);
3502-
}
3503-
b = b - a;
3504-
// SAFETY: `b` is checked to be non-zero.
3505-
unsafe {
3506-
if b == 0 {
3507-
break;
3508-
}
3509-
ctz_b = intrinsics::cttz_nonzero(b);
3510-
}
3511-
}
3512-
a << k
3477+
const fn gcd(a: usize, b: usize) -> usize {
3478+
if b == 0 { a } else { gcd(b, a % b) }
35133479
}
3514-
let gcd: usize = gcd(mem::size_of::<T>(), mem::size_of::<U>());
3480+
3481+
// Explicitly wrap the function call in a const block so it gets
3482+
// constant-evaluated even in debug mode.
3483+
let gcd: usize = const { gcd(mem::size_of::<T>(), mem::size_of::<U>()) };
35153484
let ts: usize = mem::size_of::<U>() / gcd;
35163485
let us: usize = mem::size_of::<T>() / gcd;
35173486

0 commit comments

Comments
 (0)