From 85b9d63adfb329dd80ce1e3a7cbcd7fa94d0de05 Mon Sep 17 00:00:00 2001 From: junkui chen Date: Tue, 29 Sep 2026 11:39:35 +0800 Subject: [PATCH 1/5] [diskann-wide] Add word-to-byte SIMD reinterpretations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- diskann-wide/src/arch/x86_64/v3/conversion.rs | 23 ++++++++++- diskann-wide/src/arch/x86_64/v4/conversion.rs | 31 ++++++++++++++- diskann-wide/src/emulated.rs | 22 +++++++++++ diskann-wide/src/test_utils/ops.rs | 39 +++++++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/diskann-wide/src/arch/x86_64/v3/conversion.rs b/diskann-wide/src/arch/x86_64/v3/conversion.rs index ff991d4ce2..4c454da334 100644 --- a/diskann-wide/src/arch/x86_64/v3/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v3/conversion.rs @@ -6,7 +6,9 @@ // x86 intrinsics use std::arch::x86_64::*; -use super::{f16x8, f16x16, f32x8, f32x16, i8x16, i16x8, i16x16, i32x8, u8x16, u32x8}; +use super::{ + f16x8, f16x16, f32x8, f32x16, i8x16, i8x32, i16x8, i16x16, i32x8, u8x16, u8x32, u32x8, +}; use crate::{LoHi, SIMDCast, SIMDReinterpret, SplitJoin, helpers}; ///////////////// @@ -100,6 +102,18 @@ impl SIMDReinterpret for u32x8 { } } +impl SIMDReinterpret for u32x8 { + fn reinterpret_simd(self) -> u8x32 { + u8x32(self.0) + } +} + +impl SIMDReinterpret for u32x8 { + fn reinterpret_simd(self) -> i8x32 { + i8x32(self.0) + } +} + impl SIMDReinterpret for i16x8 { fn reinterpret_simd(self) -> u8x16 { u8x16(self.0) @@ -121,6 +135,13 @@ mod test_x86_conversions { use super::*; use crate::{arch::x86_64::V3, test_utils}; + test_utils::ops::test_reinterpret_bytes!( + u32x8 => u8x32, 0x69b42dafe0917358, V3::new_checked_uncached() + ); + test_utils::ops::test_reinterpret_bytes!( + u32x8 => i8x32, 0x69b42dafe0917358, V3::new_checked_uncached() + ); + // Lossless Conversions #[cfg(not(miri))] test_utils::ops::test_lossless_convert!( diff --git a/diskann-wide/src/arch/x86_64/v4/conversion.rs b/diskann-wide/src/arch/x86_64/v4/conversion.rs index 896dac76b5..d8e58740f8 100644 --- a/diskann-wide/src/arch/x86_64/v4/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v4/conversion.rs @@ -9,7 +9,7 @@ use std::arch::x86_64::*; use super::{ f16x8_::f16x8, f16x16_::f16x16, f32x8_::f32x8, f32x16_::f32x16, i8x16_::i8x16, i8x32_::i8x32, i8x64_::i8x64, i16x8_::i16x8, i16x16_::i16x16, i16x32_::i16x32, i32x8_::i32x8, u8x16_::u8x16, - u8x32_::u8x32, u8x64_::u8x64, u32x8_::u32x8, u32x16_::u32x16, + u8x32_::u8x32, u8x64_::u8x64, u32x8_::u32x8, u32x16_::u32x16, u64x8_::u64x8, }; use crate::{SIMDCast, SIMDReinterpret, SIMDVector, arch::x86_64::v3, helpers}; @@ -112,6 +112,18 @@ impl SIMDReinterpret for u32x16 { } } +impl SIMDReinterpret for u64x8 { + fn reinterpret_simd(self) -> u8x64 { + u8x64(self.0) + } +} + +impl SIMDReinterpret for u64x8 { + fn reinterpret_simd(self) -> i8x64 { + i8x64(self.0) + } +} + impl SIMDReinterpret for u8x64 { fn reinterpret_simd(self) -> u32x16 { u32x16(self.0) @@ -143,7 +155,22 @@ impl SIMDReinterpret for u8x16 { #[cfg(test)] mod test_x86_conversions { use super::*; - use crate::{arch::x86_64::V4, test_utils}; + use crate::{ + arch::x86_64::{ + V4, + v4::{i8x64, u8x64, u64x8}, + }, + test_utils, + }; + + test_utils::ops::test_reinterpret_bytes!( + u64x8 => u8x64, 0x891d3c75ef2064ba, + if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + ); + test_utils::ops::test_reinterpret_bytes!( + u64x8 => i8x64, 0x891d3c75ef2064ba, + if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + ); // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/emulated.rs b/diskann-wide/src/emulated.rs index df08821d6b..dbdd7bd635 100644 --- a/diskann-wide/src/emulated.rs +++ b/diskann-wide/src/emulated.rs @@ -631,6 +631,11 @@ impl_little_endian_transmute_cast!( => ); impl_little_endian_transmute_cast!( => ); impl_little_endian_transmute_cast!( => ); +impl_little_endian_transmute_cast!( => ); +impl_little_endian_transmute_cast!( => ); +impl_little_endian_transmute_cast!( => ); +impl_little_endian_transmute_cast!( => ); + impl_little_endian_transmute_cast!( => ); impl_little_endian_transmute_cast!( => ); @@ -1110,6 +1115,23 @@ mod test_emulated { Emulated => Emulated, 0x75929494c5d333d0, SC ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret_bytes!( + Emulated => Emulated, 0x69b42dafe0917358, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret_bytes!( + Emulated => Emulated, 0x69b42dafe0917358, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret_bytes!( + Emulated => Emulated, 0x891d3c75ef2064ba, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret_bytes!( + Emulated => Emulated, 0x891d3c75ef2064ba, SC + ); + /////////// // Casts // /////////// diff --git a/diskann-wide/src/test_utils/ops.rs b/diskann-wide/src/test_utils/ops.rs index fc15661f1e..46a89dee87 100644 --- a/diskann-wide/src/test_utils/ops.rs +++ b/diskann-wide/src/test_utils/ops.rs @@ -532,6 +532,44 @@ macro_rules! test_cast { } } +macro_rules! test_reinterpret_bytes { + ( + $from:ident $(< $($fs:tt),+ >)? => $to:ident $(< $($ts:tt),+ >)?, + $seed:literal, + $arch:expr + ) => { + paste::paste! { + #[test] + fn []() { + use $crate::{SIMDReinterpret, SIMDVector}; + + type From = $from $(< $($fs),+>)?; + type To = $to $(< $($ts),+>)?; + + if let Some(arch) = $arch { + let f = move |input: &[::Scalar]| { + let got: To = From::from_array(arch, input.try_into().unwrap()) + .reinterpret_simd(); + let expected: Vec<_> = input.iter() + .flat_map(|x| x.to_le_bytes()) + .map(|x| x as ::Scalar) + .collect(); + assert_eq!(got.to_array().as_slice(), expected, "input: {input:?}"); + }; + + let input: Vec<_> = (0..From::LANES).map(|lane| { + ::Scalar::from_le_bytes(std::array::from_fn(|byte| { + [0x00, 0x7f, 0x80, 0xff, 0x01, 0x55, 0xaa, 0xfe][(lane + byte) % 8] + })) + }).collect(); + f(&input); + $crate::test_utils::driver::drive_unary(&f, From::LANES, $seed); + } + } + } + }; +} + macro_rules! test_abs { ($wide:ident $(< $($ps:tt),+ >)?, $seed:literal, $arch:expr) => { paste::paste! { @@ -1146,6 +1184,7 @@ pub(crate) use test_lossless_convert; pub(crate) use test_minmax; pub(crate) use test_mul; pub(crate) use test_popcount; +pub(crate) use test_reinterpret_bytes; pub(crate) use test_select; pub(crate) use test_splitjoin; pub(crate) use test_sub; From b35d4382640dbf10b3a15c0205d0aff0d4cd8527 Mon Sep 17 00:00:00 2001 From: junkui chen Date: Tue, 29 Sep 2026 11:58:38 +0800 Subject: [PATCH 2/5] [diskann-wide] Simplify reinterpretation tests Replace the test macro with explicit architecture-gated tests and an existing-helper-based byte comparison. Use distinct byte positions and signed-boundary offsets so fixed fixtures expose lane/byte transposition. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- diskann-wide/src/arch/x86_64/v3/conversion.rs | 13 ++-- diskann-wide/src/arch/x86_64/v4/conversion.rs | 20 +++--- diskann-wide/src/emulated.rs | 37 ++++++---- diskann-wide/src/test_utils/ops.rs | 71 +++++++++---------- 4 files changed, 75 insertions(+), 66 deletions(-) diff --git a/diskann-wide/src/arch/x86_64/v3/conversion.rs b/diskann-wide/src/arch/x86_64/v3/conversion.rs index 4c454da334..3f09f4c30c 100644 --- a/diskann-wide/src/arch/x86_64/v3/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v3/conversion.rs @@ -135,12 +135,13 @@ mod test_x86_conversions { use super::*; use crate::{arch::x86_64::V3, test_utils}; - test_utils::ops::test_reinterpret_bytes!( - u32x8 => u8x32, 0x69b42dafe0917358, V3::new_checked_uncached() - ); - test_utils::ops::test_reinterpret_bytes!( - u32x8 => i8x32, 0x69b42dafe0917358, V3::new_checked_uncached() - ); + #[test] + fn reinterpret_u32x8_to_bytes() { + if let Some(arch) = V3::new_checked_uncached() { + test_utils::ops::test_reinterpret::(arch, 0x69b42dafe0917358); + test_utils::ops::test_reinterpret::(arch, 0x69b42dafe0917358); + } + } // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/arch/x86_64/v4/conversion.rs b/diskann-wide/src/arch/x86_64/v4/conversion.rs index d8e58740f8..8ef6c6e45a 100644 --- a/diskann-wide/src/arch/x86_64/v4/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v4/conversion.rs @@ -163,14 +163,18 @@ mod test_x86_conversions { test_utils, }; - test_utils::ops::test_reinterpret_bytes!( - u64x8 => u8x64, 0x891d3c75ef2064ba, - if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } - ); - test_utils::ops::test_reinterpret_bytes!( - u64x8 => i8x64, 0x891d3c75ef2064ba, - if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } - ); + #[test] + fn reinterpret_u64x8_to_bytes() { + let arch = if cfg!(miri) { + V4::new_checked_miri() + } else { + V4::new_checked_uncached() + }; + if let Some(arch) = arch { + test_utils::ops::test_reinterpret::(arch, 0x891d3c75ef2064ba); + test_utils::ops::test_reinterpret::(arch, 0x891d3c75ef2064ba); + } + } // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/emulated.rs b/diskann-wide/src/emulated.rs index dbdd7bd635..b630c5b70f 100644 --- a/diskann-wide/src/emulated.rs +++ b/diskann-wide/src/emulated.rs @@ -1116,21 +1116,30 @@ mod test_emulated { ); #[cfg(target_endian = "little")] - test_utils::ops::test_reinterpret_bytes!( - Emulated => Emulated, 0x69b42dafe0917358, SC - ); - #[cfg(target_endian = "little")] - test_utils::ops::test_reinterpret_bytes!( - Emulated => Emulated, 0x69b42dafe0917358, SC - ); - #[cfg(target_endian = "little")] - test_utils::ops::test_reinterpret_bytes!( - Emulated => Emulated, 0x891d3c75ef2064ba, SC - ); + #[test] + fn reinterpret_u32x8_to_bytes() { + test_utils::ops::test_reinterpret::, Emulated, 8, 32>( + Scalar, + 0x69b42dafe0917358, + ); + test_utils::ops::test_reinterpret::, Emulated, 8, 32>( + Scalar, + 0x69b42dafe0917358, + ); + } + #[cfg(target_endian = "little")] - test_utils::ops::test_reinterpret_bytes!( - Emulated => Emulated, 0x891d3c75ef2064ba, SC - ); + #[test] + fn reinterpret_u64x8_to_bytes() { + test_utils::ops::test_reinterpret::, Emulated, 8, 64>( + Scalar, + 0x891d3c75ef2064ba, + ); + test_utils::ops::test_reinterpret::, Emulated, 8, 64>( + Scalar, + 0x891d3c75ef2064ba, + ); + } /////////// // Casts // diff --git a/diskann-wide/src/test_utils/ops.rs b/diskann-wide/src/test_utils/ops.rs index 46a89dee87..0699eed392 100644 --- a/diskann-wide/src/test_utils/ops.rs +++ b/diskann-wide/src/test_utils/ops.rs @@ -6,10 +6,13 @@ use std::fmt::Debug; // Common test traits. -use super::common::{self, ScalarTraits}; +use super::{ + common::{self, ScalarTraits}, + driver::{self, ScalarDriver}, +}; use crate::{ - BitMask, Const, SIMDMask, SIMDMinMax, SIMDPartialEq, SIMDPartialOrd, SIMDSumTree, SIMDVector, - SplitJoin, SupportedLaneCount, ZipUnzip, arch, + BitMask, Const, SIMDMask, SIMDMinMax, SIMDPartialEq, SIMDPartialOrd, SIMDReinterpret, + SIMDSumTree, SIMDVector, SplitJoin, SupportedLaneCount, ZipUnzip, arch, reference::{ReferenceIntegerOps, ReferenceScalarOps, TreeReduce}, }; @@ -532,42 +535,35 @@ macro_rules! test_cast { } } -macro_rules! test_reinterpret_bytes { - ( - $from:ident $(< $($fs:tt),+ >)? => $to:ident $(< $($ts:tt),+ >)?, - $seed:literal, - $arch:expr - ) => { - paste::paste! { - #[test] - fn []() { - use $crate::{SIMDReinterpret, SIMDVector}; - - type From = $from $(< $($fs),+>)?; - type To = $to $(< $($ts),+>)?; - - if let Some(arch) = $arch { - let f = move |input: &[::Scalar]| { - let got: To = From::from_array(arch, input.try_into().unwrap()) - .reinterpret_simd(); - let expected: Vec<_> = input.iter() - .flat_map(|x| x.to_le_bytes()) - .map(|x| x as ::Scalar) - .collect(); - assert_eq!(got.to_array().as_slice(), expected, "input: {input:?}"); - }; +pub(crate) fn test_reinterpret( + arch: From::Arch, + seed: u64, +) where + From: SIMDVector> + SIMDReinterpret, + To: SIMDVector>, + From::Scalar: ScalarDriver + bytemuck::Pod, + To::Scalar: bytemuck::Pod, + Const: SupportedLaneCount, + Const: SupportedLaneCount, +{ + let check = move |input: &[From::Scalar]| { + let got: To = From::from_array(arch, input.try_into().unwrap()).reinterpret_simd(); + assert_eq!( + common::bytes(&got.to_array()), + common::bytes(input), + "input: {input:?}" + ); + }; - let input: Vec<_> = (0..From::LANES).map(|lane| { - ::Scalar::from_le_bytes(std::array::from_fn(|byte| { - [0x00, 0x7f, 0x80, 0xff, 0x01, 0x55, 0xaa, 0xfe][(lane + byte) % 8] - })) - }).collect(); - f(&input); - $crate::test_utils::driver::drive_unary(&f, From::LANES, $seed); - } - } + // Distinct bytes expose lane/byte reordering; offsets exercise the signed-byte boundary. + let mut input = [From::Scalar::default(); N]; + for start in [0u8, 0x7f, 0x80, 0xff] { + for (i, byte) in common::bytes_mut(&mut input).iter_mut().enumerate() { + *byte = start.wrapping_add(i as u8); } - }; + check(&input); + } + driver::drive_unary(&check, N, seed); } macro_rules! test_abs { @@ -1184,7 +1180,6 @@ pub(crate) use test_lossless_convert; pub(crate) use test_minmax; pub(crate) use test_mul; pub(crate) use test_popcount; -pub(crate) use test_reinterpret_bytes; pub(crate) use test_select; pub(crate) use test_splitjoin; pub(crate) use test_sub; From fce399f5462daa5d123a07e43dea651864ce55dd Mon Sep 17 00:00:00 2001 From: junkui chen Date: Tue, 29 Sep 2026 12:02:24 +0800 Subject: [PATCH 3/5] [diskann-wide] Follow existing conversion test conventions Keep architecture-gated macro call sites and the unary test driver. Compare raw bytes and use distinct byte positions instead of a transpose-symmetric fixture. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- diskann-wide/src/arch/x86_64/v3/conversion.rs | 13 ++-- diskann-wide/src/arch/x86_64/v4/conversion.rs | 20 ++--- diskann-wide/src/emulated.rs | 37 ++++----- diskann-wide/src/test_utils/ops.rs | 75 +++++++++++-------- 4 files changed, 70 insertions(+), 75 deletions(-) diff --git a/diskann-wide/src/arch/x86_64/v3/conversion.rs b/diskann-wide/src/arch/x86_64/v3/conversion.rs index 3f09f4c30c..8d6aa205cd 100644 --- a/diskann-wide/src/arch/x86_64/v3/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v3/conversion.rs @@ -135,13 +135,12 @@ mod test_x86_conversions { use super::*; use crate::{arch::x86_64::V3, test_utils}; - #[test] - fn reinterpret_u32x8_to_bytes() { - if let Some(arch) = V3::new_checked_uncached() { - test_utils::ops::test_reinterpret::(arch, 0x69b42dafe0917358); - test_utils::ops::test_reinterpret::(arch, 0x69b42dafe0917358); - } - } + test_utils::ops::test_reinterpret!( + u32x8 => u8x32, 0x69b42dafe0917358, V3::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u32x8 => i8x32, 0x69b42dafe0917358, V3::new_checked_uncached() + ); // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/arch/x86_64/v4/conversion.rs b/diskann-wide/src/arch/x86_64/v4/conversion.rs index 8ef6c6e45a..2d30b2eb80 100644 --- a/diskann-wide/src/arch/x86_64/v4/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v4/conversion.rs @@ -163,18 +163,14 @@ mod test_x86_conversions { test_utils, }; - #[test] - fn reinterpret_u64x8_to_bytes() { - let arch = if cfg!(miri) { - V4::new_checked_miri() - } else { - V4::new_checked_uncached() - }; - if let Some(arch) = arch { - test_utils::ops::test_reinterpret::(arch, 0x891d3c75ef2064ba); - test_utils::ops::test_reinterpret::(arch, 0x891d3c75ef2064ba); - } - } + test_utils::ops::test_reinterpret!( + u64x8 => u8x64, 0x891d3c75ef2064ba, + if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + ); + test_utils::ops::test_reinterpret!( + u64x8 => i8x64, 0x891d3c75ef2064ba, + if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + ); // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/emulated.rs b/diskann-wide/src/emulated.rs index b630c5b70f..fd694a0426 100644 --- a/diskann-wide/src/emulated.rs +++ b/diskann-wide/src/emulated.rs @@ -1116,30 +1116,21 @@ mod test_emulated { ); #[cfg(target_endian = "little")] - #[test] - fn reinterpret_u32x8_to_bytes() { - test_utils::ops::test_reinterpret::, Emulated, 8, 32>( - Scalar, - 0x69b42dafe0917358, - ); - test_utils::ops::test_reinterpret::, Emulated, 8, 32>( - Scalar, - 0x69b42dafe0917358, - ); - } - + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x69b42dafe0917358, SC + ); #[cfg(target_endian = "little")] - #[test] - fn reinterpret_u64x8_to_bytes() { - test_utils::ops::test_reinterpret::, Emulated, 8, 64>( - Scalar, - 0x891d3c75ef2064ba, - ); - test_utils::ops::test_reinterpret::, Emulated, 8, 64>( - Scalar, - 0x891d3c75ef2064ba, - ); - } + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x69b42dafe0917358, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x891d3c75ef2064ba, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x891d3c75ef2064ba, SC + ); /////////// // Casts // diff --git a/diskann-wide/src/test_utils/ops.rs b/diskann-wide/src/test_utils/ops.rs index 0699eed392..f742dd6e3f 100644 --- a/diskann-wide/src/test_utils/ops.rs +++ b/diskann-wide/src/test_utils/ops.rs @@ -6,13 +6,10 @@ use std::fmt::Debug; // Common test traits. -use super::{ - common::{self, ScalarTraits}, - driver::{self, ScalarDriver}, -}; +use super::common::{self, ScalarTraits}; use crate::{ - BitMask, Const, SIMDMask, SIMDMinMax, SIMDPartialEq, SIMDPartialOrd, SIMDReinterpret, - SIMDSumTree, SIMDVector, SplitJoin, SupportedLaneCount, ZipUnzip, arch, + BitMask, Const, SIMDMask, SIMDMinMax, SIMDPartialEq, SIMDPartialOrd, SIMDSumTree, SIMDVector, + SplitJoin, SupportedLaneCount, ZipUnzip, arch, reference::{ReferenceIntegerOps, ReferenceScalarOps, TreeReduce}, }; @@ -535,35 +532,46 @@ macro_rules! test_cast { } } -pub(crate) fn test_reinterpret( - arch: From::Arch, - seed: u64, -) where - From: SIMDVector> + SIMDReinterpret, - To: SIMDVector>, - From::Scalar: ScalarDriver + bytemuck::Pod, - To::Scalar: bytemuck::Pod, - Const: SupportedLaneCount, - Const: SupportedLaneCount, -{ - let check = move |input: &[From::Scalar]| { - let got: To = From::from_array(arch, input.try_into().unwrap()).reinterpret_simd(); - assert_eq!( - common::bytes(&got.to_array()), - common::bytes(input), - "input: {input:?}" - ); - }; +macro_rules! test_reinterpret { + ( + $from:ident $(< $($fs:tt),+ >)? => $to:ident $(< $($ts:tt),+ >)?, + $seed:literal, + $arch:expr + ) => { + paste::paste! { + #[test] + fn []() { + use $crate::{SIMDReinterpret, SIMDVector}; - // Distinct bytes expose lane/byte reordering; offsets exercise the signed-byte boundary. - let mut input = [From::Scalar::default(); N]; - for start in [0u8, 0x7f, 0x80, 0xff] { - for (i, byte) in common::bytes_mut(&mut input).iter_mut().enumerate() { - *byte = start.wrapping_add(i as u8); + type From = $from $(< $($fs),+>)?; + type To = $to $(< $($ts),+>)?; + + if let Some(arch) = $arch { + let f = move |input: &[::Scalar]| { + let got: To = From::from_array(arch, input.try_into().unwrap()) + .reinterpret_simd(); + assert_eq!( + bytemuck::must_cast_slice::<_, u8>(&got.to_array()), + bytemuck::must_cast_slice::<_, u8>(input), + "input: {input:?}", + ); + }; + + // Distinct byte positions detect lane/byte reordering. + let mut input = [::Scalar::default(); From::LANES]; + for start in [0u8, 0x7f, 0x80, 0xff] { + for (i, byte) in bytemuck::must_cast_slice_mut::<_, u8>(&mut input) + .iter_mut().enumerate() + { + *byte = start.wrapping_add(i as u8); + } + f(&input); + } + $crate::test_utils::driver::drive_unary(&f, From::LANES, $seed); + } + } } - check(&input); - } - driver::drive_unary(&check, N, seed); + }; } macro_rules! test_abs { @@ -1180,6 +1188,7 @@ pub(crate) use test_lossless_convert; pub(crate) use test_minmax; pub(crate) use test_mul; pub(crate) use test_popcount; +pub(crate) use test_reinterpret; pub(crate) use test_select; pub(crate) use test_splitjoin; pub(crate) use test_sub; From 256b507e46bef6b072d6bf9b8ff5c7f01917e00e Mon Sep 17 00:00:00 2001 From: junkui chen Date: Tue, 29 Sep 2026 13:19:03 +0800 Subject: [PATCH 4/5] [diskann-wide] Match existing V4 conversion test gating Remove special Miri branching and alias imports from the V4 conversion tests. Keep scalar emulation coverage in emulated.rs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- diskann-wide/src/arch/x86_64/v4/conversion.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/diskann-wide/src/arch/x86_64/v4/conversion.rs b/diskann-wide/src/arch/x86_64/v4/conversion.rs index 2d30b2eb80..04998e152a 100644 --- a/diskann-wide/src/arch/x86_64/v4/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v4/conversion.rs @@ -155,21 +155,13 @@ impl SIMDReinterpret for u8x16 { #[cfg(test)] mod test_x86_conversions { use super::*; - use crate::{ - arch::x86_64::{ - V4, - v4::{i8x64, u8x64, u64x8}, - }, - test_utils, - }; + use crate::{arch::x86_64::V4, test_utils}; test_utils::ops::test_reinterpret!( - u64x8 => u8x64, 0x891d3c75ef2064ba, - if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + u64x8 => u8x64, 0x891d3c75ef2064ba, V4::new_checked_uncached() ); test_utils::ops::test_reinterpret!( - u64x8 => i8x64, 0x891d3c75ef2064ba, - if cfg!(miri) { V4::new_checked_miri() } else { V4::new_checked_uncached() } + u64x8 => i8x64, 0x891d3c75ef2064ba, V4::new_checked_uncached() ); // Lossless Conversions From 839cb7e1c52944429ba4c138808b96b276f0f86a Mon Sep 17 00:00:00 2001 From: junkui chen Date: Wed, 30 Sep 2026 10:10:25 +0800 Subject: [PATCH 5/5] [diskann-wide] Test all existing SIMD reinterpretations Address PR #1445 review feedback by covering every V3, V4 and Emulated reinterpretation with the existing test macro. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- diskann-wide/src/arch/x86_64/v3/conversion.rs | 9 ++++++ diskann-wide/src/arch/x86_64/v4/conversion.rs | 24 ++++++++++++++ diskann-wide/src/emulated.rs | 32 +++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/diskann-wide/src/arch/x86_64/v3/conversion.rs b/diskann-wide/src/arch/x86_64/v3/conversion.rs index 8d6aa205cd..a03ac92d66 100644 --- a/diskann-wide/src/arch/x86_64/v3/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v3/conversion.rs @@ -135,12 +135,21 @@ mod test_x86_conversions { use super::*; use crate::{arch::x86_64::V3, test_utils}; + test_utils::ops::test_reinterpret!( + u32x8 => i16x16, 0x763582a914ec0bfd, V3::new_checked_uncached() + ); test_utils::ops::test_reinterpret!( u32x8 => u8x32, 0x69b42dafe0917358, V3::new_checked_uncached() ); test_utils::ops::test_reinterpret!( u32x8 => i8x32, 0x69b42dafe0917358, V3::new_checked_uncached() ); + test_utils::ops::test_reinterpret!( + i16x8 => u8x16, 0x4b96d02e85f713ca, V3::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u8x16 => i16x8, 0xd5302e6b194a87fc, V3::new_checked_uncached() + ); // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/arch/x86_64/v4/conversion.rs b/diskann-wide/src/arch/x86_64/v4/conversion.rs index 04998e152a..16f679db69 100644 --- a/diskann-wide/src/arch/x86_64/v4/conversion.rs +++ b/diskann-wide/src/arch/x86_64/v4/conversion.rs @@ -157,12 +157,36 @@ mod test_x86_conversions { use super::*; use crate::{arch::x86_64::V4, test_utils}; + test_utils::ops::test_reinterpret!( + u32x8 => i16x16, 0x763582a914ec0bfd, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u32x16 => i16x32, 0xe96b52d0743af18c, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u32x16 => u8x64, 0x372ab891f06e5cd4, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u32x16 => i8x64, 0x951d80aefc476b23, V4::new_checked_uncached() + ); test_utils::ops::test_reinterpret!( u64x8 => u8x64, 0x891d3c75ef2064ba, V4::new_checked_uncached() ); test_utils::ops::test_reinterpret!( u64x8 => i8x64, 0x891d3c75ef2064ba, V4::new_checked_uncached() ); + test_utils::ops::test_reinterpret!( + u8x64 => u32x16, 0x28fc7d6140a953be, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + i8x64 => u32x16, 0xbf6308d2e471a59c, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + i16x8 => u8x16, 0x4b96d02e85f713ca, V4::new_checked_uncached() + ); + test_utils::ops::test_reinterpret!( + u8x16 => i16x8, 0xd5302e6b194a87fc, V4::new_checked_uncached() + ); // Lossless Conversions #[cfg(not(miri))] diff --git a/diskann-wide/src/emulated.rs b/diskann-wide/src/emulated.rs index fd694a0426..be12697949 100644 --- a/diskann-wide/src/emulated.rs +++ b/diskann-wide/src/emulated.rs @@ -1115,6 +1115,30 @@ mod test_emulated { Emulated => Emulated, 0x75929494c5d333d0, SC ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x763582a914ec0bfd, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0xe96b52d0743af18c, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x4b96d02e85f713ca, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0xd5302e6b194a87fc, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x372ab891f06e5cd4, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x951d80aefc476b23, SC + ); #[cfg(target_endian = "little")] test_utils::ops::test_reinterpret!( Emulated => Emulated, 0x69b42dafe0917358, SC @@ -1131,6 +1155,14 @@ mod test_emulated { test_utils::ops::test_reinterpret!( Emulated => Emulated, 0x891d3c75ef2064ba, SC ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0x28fc7d6140a953be, SC + ); + #[cfg(target_endian = "little")] + test_utils::ops::test_reinterpret!( + Emulated => Emulated, 0xbf6308d2e471a59c, SC + ); /////////// // Casts //