From 6960c519f143ad68a690fbb3e0ef94b685fdcbbc Mon Sep 17 00:00:00 2001 From: rymnc <43716372+rymnc@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:48:45 +0530 Subject: [PATCH] test: conditionally use simd variant --- fuel-vm/src/interpreter/memory.rs | 98 +++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 30 deletions(-) diff --git a/fuel-vm/src/interpreter/memory.rs b/fuel-vm/src/interpreter/memory.rs index 9472547dc..d997313d8 100644 --- a/fuel-vm/src/interpreter/memory.rs +++ b/fuel-vm/src/interpreter/memory.rs @@ -1,7 +1,7 @@ #![cfg(feature = "alloc")] #[cfg(feature = "experimental")] -use core::simd::u8x16; +use core::simd::{u8x16, u8x32, u8x64}; use super::{ internal::inc_pc, @@ -1040,37 +1040,75 @@ fn slice_eq(a: &[u8], b: &[u8]) -> bool { return false; } - // because we're using simd, we can parallelize by a factor of 4 - let mut res_a = false; - let mut res_b = false; - let mut res_c = false; - let mut res_d = false; - - let chunks_a = a.chunks_exact(16); - let chunks_b = b.chunks_exact(16); - let remainder_a = chunks_a.remainder(); - let remainder_b = chunks_b.remainder(); - - for i in (0..chunks_a.len()).step_by(4) { - let simd_a = u8x16::from_slice(&a[i..i + 16]); - let simd_b = u8x16::from_slice(&b[i..i + 16]); - res_a |= simd_a != simd_b; - - let simd_a = u8x16::from_slice(&a[i + 16..i + 32]); - let simd_b = u8x16::from_slice(&b[i + 16..i + 32]); - res_b |= simd_a != simd_b; - - let simd_a = u8x16::from_slice(&a[i + 32..i + 48]); - let simd_b = u8x16::from_slice(&b[i + 32..i + 48]); - res_c |= simd_a != simd_b; - - let simd_a = u8x16::from_slice(&a[i + 48..i + 64]); - let simd_b = u8x16::from_slice(&b[i + 48..i + 64]); - res_d |= simd_a != simd_b; + enum SimdVariant { + U8x16, + U8x32, + U8x64, } - // check the remainder - remainder_a == remainder_b && res_a && res_b && res_c && res_d + impl SimdVariant { + fn chunk_size(&self) -> usize{ + match &self { + SimdVariant::U8x16 => 16, + SimdVariant::U8x32 => 32, + SimdVariant::U8x64 => 64, + } + } + } + + // we check if the number of bytes is divisible by 16, 32, 64. + // we choose the largest number that has the smallest remainder + + let remainder_16 = a.len() % 16; + let remainder_32 = a.len() % 32; + let remainder_64 = a.len() % 64; + + // based on the smallest remainder, we then use the appropriate simd instruction + // to compare the slices + let variant = if remainder_16 < remainder_32 { + if remainder_16 < remainder_64 { + SimdVariant::U8x16 + } else { + SimdVariant::U8x64 + } + } else { + if remainder_32 < remainder_64 { + SimdVariant::U8x32 + } else { + SimdVariant::U8x64 + } + }; + + let chunks = a.chunks_exact(variant.chunk_size()); + let remainder = chunks.remainder(); + + for (chunk_a, chunk_b) in chunks.zip(b.chunks_exact(variant.chunk_size())) { + match variant { + SimdVariant::U8x16 => { + let simd_a = u8x16::from_slice(chunk_a); + let simd_b = u8x16::from_slice(chunk_b); + if simd_a != simd_b { + return false; + } + } + SimdVariant::U8x32 => { + let simd_a = u8x32::from_slice(chunk_a); + let simd_b = u8x32::from_slice(chunk_b); + if simd_a != simd_b { + return false; + } + } + SimdVariant::U8x64 => { + let simd_a = u8x64::from_slice(chunk_a); + let simd_b = u8x64::from_slice(chunk_b); + if simd_a != simd_b { + return false; + } + } + } + } + + remainder == &b[a.len() - remainder.len()..] } #[cfg(not(feature = "experimental"))] {