8080 } )
8181 } else {
8282 #[ cfg( target_arch = "x86_64" ) ]
83- #[ target_feature( enable = "avx2" ) ]
8483 if let Some ( taken) = avx2:: take ( bits, indices, None ) {
8584 return taken;
8685 }
9897 } ;
9998
10099 #[ cfg( target_arch = "x86_64" ) ]
101- #[ target_feature( enable = "avx2" ) ]
102100 if let Some ( taken) = avx2:: take ( bits, indices, None ) {
103101 return taken;
104102 }
@@ -111,7 +109,7 @@ where
111109 // SAFETY: we're already iterating over every index, a bound
112110 // is excessive
113111 let idx = unsafe { indices. get_unchecked ( i) . as_ ( ) } ;
114- // SAFETY: we're verified validity has same size as indices before
112+ // SAFETY: we've verified validity has same size as indices before
115113 let mask_idx: usize = unsafe { get_bit_unchecked ( ptr, offset + i) } . as_ ( ) ;
116114 bools[ idx & mask_idx. wrapping_neg ( ) ]
117115 } ) ;
@@ -124,7 +122,7 @@ where
124122 // SAFETY: we're already iterating over every index, a bound
125123 // is excessive
126124 let idx = unsafe { indices. get_unchecked ( i) . as_ ( ) } ;
127- // SAFETY: we're verified validity has same size as indices before
125+ // SAFETY: we've verified validity has same size as indices before
128126 let mask_idx: usize = unsafe { get_bit_unchecked ( ptr, validity_offset + i) } . as_ ( ) ;
129127 let masked_idx = idx & mask_idx. wrapping_neg ( ) ;
130128 get_bit ( buf, bits_offset + masked_idx)
@@ -145,10 +143,7 @@ fn first_unset(bits: BitBufferView<'_>) -> Option<usize> {
145143}
146144
147145#[ cfg( target_arch = "x86_64" ) ]
148- #[ target_feature( enable = "avx2" ) ]
149146mod avx2 {
150- use super :: index_at;
151- use super :: keep_mask;
152147 use crate :: BitBuffer ;
153148 use crate :: BitBufferView ;
154149 use crate :: BufferMut ;
@@ -186,43 +181,43 @@ mod avx2 {
186181 return None ;
187182 }
188183
184+ if size_of :: < I > ( ) != size_of :: < u16 > ( ) && size_of :: < I > ( ) != size_of :: < u32 > ( ) {
185+ return None ;
186+ }
187+
188+ // SAFETY: the feature detection above guarantees avx2 is present.
189+ Some ( unsafe { run ( bits, indices, validity) } )
190+ }
191+
192+ #[ target_feature( enable = "avx2" ) ]
193+ unsafe fn run < I : AsPrimitive < usize > > (
194+ bits : BitBufferView < ' _ > ,
195+ indices : & [ I ] ,
196+ validity : Option < BitBufferView < ' _ > > ,
197+ ) -> BitBuffer {
189198 if size_of :: < I > ( ) == size_of :: < u16 > ( ) {
190199 // SAFETY: u16 or i16 can be reinterpreted as u16 since we guarantee
191200 // no negative indices
192201 let indices = unsafe { from_raw_parts ( indices. as_ptr ( ) . cast :: < u16 > ( ) , indices. len ( ) ) } ;
193- return Some ( unsafe { take_u16 ( bits, indices, validity) } ) ;
194- } else if size_of :: < I > == size_of :: < u32 > ( ) {
202+ let ptr = indices. as_ptr ( ) ;
203+ // SAFETY: avx2 is enabled for this function.
204+ unsafe {
205+ take_lanes ( bits, indices, validity, |group| {
206+ _mm256_cvtepu16_epi32 ( _mm_loadu_si128 ( ptr. add ( group * 8 ) . cast ( ) ) )
207+ } )
208+ }
209+ } else {
195210 // SAFETY: u32 or i32 can be reinterpreted as u32 since we guarantee
196211 // no negative indices
197212 let indices = unsafe { from_raw_parts ( indices. as_ptr ( ) . cast :: < u32 > ( ) , indices. len ( ) ) } ;
198- return Some ( unsafe { take_u32 ( bits, indices, validity) } ) ;
213+ let ptr = indices. as_ptr ( ) ;
214+ // SAFETY: avx2 is enabled for this function.
215+ unsafe { take_lanes ( bits, indices, validity, |group| _mm256_loadu_si256 ( ptr. add ( group * 8 ) . cast ( ) ) ) }
199216 }
200- None
201- }
202-
203- unsafe fn take_u16 (
204- bits : BitBufferView < ' _ > ,
205- indices : & [ u16 ] ,
206- validity : Option < BitBufferView < ' _ > > ,
207- ) -> BitBuffer {
208- let ptr = indices. as_ptr ( ) ;
209- take_lanes ( bits, indices, validity, |group| {
210- _mm256_cvtepu16_epi32 ( _mm_loadu_si128 ( ptr. add ( group * 8 ) . cast ( ) ) )
211- } )
212- }
213-
214- unsafe fn take_u32 (
215- bits : BitBufferView < ' _ > ,
216- indices : & [ u32 ] ,
217- validity : Option < BitBufferView < ' _ > > ,
218- ) -> BitBuffer {
219- let ptr = indices. as_ptr ( ) ;
220- take_lanes ( bits, indices, validity, |group| {
221- _mm256_loadu_si256 ( ptr. add ( group * 8 ) . cast ( ) )
222- } )
223217 }
224218
225219 #[ expect( clippy:: cast_possible_truncation) ]
220+ #[ target_feature( enable = "avx2" ) ]
226221 unsafe fn take_lanes < I > (
227222 bits : BitBufferView < ' _ > ,
228223 indices : & [ I ] ,
@@ -271,10 +266,12 @@ mod avx2 {
271266 let start = full_groups * 8 ;
272267 let mut byte = 0u8 ;
273268 for bit in 0 ..tail {
269+ let pos = start + bit;
274270 let keep = validity. map_or ( usize:: MAX , |( valid_bytes, valid_offset) | {
275- keep_mask ( valid_bytes. as_ptr ( ) , valid_offset, start + bit)
271+ ( unsafe { get_bit_unchecked ( valid_bytes. as_ptr ( ) , valid_offset + pos) } as usize )
272+ . wrapping_neg ( )
276273 } ) ;
277- let idx = index_at ( indices , start + bit ) & keep;
274+ let idx = unsafe { indices . get_unchecked ( pos ) } . as_ ( ) & keep;
278275 let value = unsafe { get_bit_unchecked ( base, bits. offset ( ) + idx) } ;
279276 byte |= ( value as u8 ) << bit;
280277 }
0 commit comments