hashbrown/control/group/
neon.rs1use super::super::{BitMask, Tag};
2use core::arch::aarch64 as neon;
3use core::mem;
4use core::num::NonZeroU64;
5
6pub(crate) type BitMaskWord = u64;
7pub(crate) type NonZeroBitMaskWord = NonZeroU64;
8pub(crate) const BITMASK_STRIDE: usize = 8;
9pub(crate) const BITMASK_ITER_MASK: BitMaskWord = 0x8080_8080_8080_8080;
10
11#[derive(Copy, Clone)]
16pub(crate) struct Group(neon::uint8x8_t);
17
18#[expect(clippy::use_self)]
19impl Group {
20 pub(crate) const WIDTH: usize = mem::size_of::<Self>();
22
23 #[inline]
28 pub(crate) const fn static_empty() -> &'static [Tag; Group::WIDTH] {
29 #[repr(C)]
30 struct AlignedTags {
31 _align: [Group; 0],
32 tags: [Tag; Group::WIDTH],
33 }
34 const ALIGNED_TAGS: AlignedTags = AlignedTags {
35 _align: [],
36 tags: [Tag::EMPTY; Group::WIDTH],
37 };
38 &ALIGNED_TAGS.tags
39 }
40
41 #[inline]
43 pub(crate) unsafe fn load(ptr: *const Tag) -> Self {
44 unsafe { Group(neon::vld1_u8(ptr.cast())) }
45 }
46
47 #[inline]
50 pub(crate) unsafe fn load_aligned(ptr: *const Tag) -> Self {
51 debug_assert_eq!(ptr.align_offset(mem::align_of::<Self>()), 0);
52 unsafe { Group(neon::vld1_u8(ptr.cast())) }
53 }
54
55 #[inline]
58 pub(crate) unsafe fn store_aligned(self, ptr: *mut Tag) {
59 debug_assert_eq!(ptr.align_offset(mem::align_of::<Self>()), 0);
60 unsafe {
61 neon::vst1_u8(ptr.cast(), self.0);
62 }
63 }
64
65 #[inline]
68 pub(crate) fn match_tag(self, tag: Tag) -> BitMask {
69 unsafe {
70 let cmp = neon::vceq_u8(self.0, neon::vdup_n_u8(tag.0));
71 BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
72 }
73 }
74
75 #[inline]
78 pub(crate) fn match_empty(self) -> BitMask {
79 self.match_tag(Tag::EMPTY)
80 }
81
82 #[inline]
85 pub(crate) fn match_empty_or_deleted(self) -> BitMask {
86 unsafe {
87 let cmp = neon::vcltz_s8(neon::vreinterpret_s8_u8(self.0));
88 BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
89 }
90 }
91
92 #[inline]
94 pub(crate) fn match_full(self) -> BitMask {
95 unsafe {
96 let cmp = neon::vcgez_s8(neon::vreinterpret_s8_u8(self.0));
97 BitMask(neon::vget_lane_u64(neon::vreinterpret_u64_u8(cmp), 0))
98 }
99 }
100
101 #[inline]
106 pub(crate) fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
107 unsafe {
115 let special = neon::vcltz_s8(neon::vreinterpret_s8_u8(self.0));
116 Group(neon::vorr_u8(special, neon::vdup_n_u8(0x80)))
117 }
118 }
119}