Skip to content

Commit dea5d1d

Browse files
committed
fix
1 parent 6d023db commit dea5d1d

1 file changed

Lines changed: 32 additions & 35 deletions

File tree

‎vortex-buffer/src/bit/take.rs‎

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ where
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
}
@@ -98,7 +97,6 @@ where
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")]
149146
mod 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

Comments
 (0)