77#pragma once
88#include < arm_neon.h>
99#include < torchao/experimental/kernels/cpu/aarch64/bitpacking/macro.h>
10+ #include < torchao/experimental/kernels/cpu/aarch64/bitpacking/uint2.h>
1011#include < torchao/experimental/kernels/cpu/aarch64/bitpacking/uint3.h>
1112#include < torchao/experimental/kernels/cpu/aarch64/bitpacking/uint4.h>
1213#include < cassert>
@@ -15,6 +16,30 @@ namespace torchao {
1516namespace bitpacking {
1617
1718namespace internal {
19+ TORCHAO_ALWAYS_INLINE inline void vec_store_32_uint8_values (
20+ uint8_t * dest,
21+ const uint8x8_t & vec0,
22+ const uint8x8_t & vec1,
23+ const uint8x8_t & vec2,
24+ const uint8x8_t & vec3) {
25+ vst1_u8 (dest, vec0);
26+ vst1_u8 (dest + 8 , vec1);
27+ vst1_u8 (dest + 16 , vec2);
28+ vst1_u8 (dest + 24 , vec3);
29+ }
30+
31+ TORCHAO_ALWAYS_INLINE inline void vec_load_32_uint8_values (
32+ uint8x8_t & vec0,
33+ uint8x8_t & vec1,
34+ uint8x8_t & vec2,
35+ uint8x8_t & vec3,
36+ const uint8_t * src) {
37+ vec0 = vld1_u8 (src);
38+ vec1 = vld1_u8 (src + 8 );
39+ vec2 = vld1_u8 (src + 16 );
40+ vec3 = vld1_u8 (src + 24 );
41+ }
42+
1843TORCHAO_ALWAYS_INLINE inline void vec_store_64_uint8_values (
1944 uint8_t * dest,
2045 const uint8x16_t & vec0,
@@ -49,7 +74,7 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_32_lowbit_values(
4974 static_assert (nbit >= 2 );
5075
5176 // Currently supported values
52- static_assert (nbit >= 3 );
77+ static_assert (nbit >= 2 );
5378 static_assert (nbit <= 4 );
5479
5580 // Shift unpacked values to nonnegative range
@@ -58,6 +83,13 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_32_lowbit_values(
5883 uint8x16_t shifted1 = vreinterpretq_u8_s8 (vaddq_s8 (unpacked1, shift));
5984
6085 switch (nbit) {
86+ case 2 :
87+ torchao::bitpacking::internal::vec_pack_32_uint2_values (
88+ packed,
89+ vget_low_u8 (shifted0),
90+ vget_high_u8 (shifted0),
91+ vget_low_u8 (shifted1),
92+ vget_high_u8 (shifted1));
6193 case 3 :
6294 uint8_t buffer[32 ];
6395 vst1q_u8 (buffer, shifted0);
@@ -89,13 +121,22 @@ TORCHAO_ALWAYS_INLINE inline void vec_unpack_32_lowbit_values(
89121 static_assert (nbit >= 2 );
90122
91123 // Currently supported values
92- static_assert (nbit >= 3 );
124+ static_assert (nbit >= 2 );
93125 static_assert (nbit <= 4 );
94126
95127 uint8x16_t shifted0;
96128 uint8x16_t shifted1;
97129
98130 switch (nbit) {
131+ case 2 :
132+ uint8x8_t shifted0_low;
133+ uint8x8_t shifted0_high;
134+ uint8x8_t shifted1_low;
135+ uint8x8_t shifted1_high;
136+ torchao::bitpacking::internal::vec_unpack_32_uint2_values (
137+ shifted0_low, shifted0_high, shifted1_low, shifted1_high, packed);
138+ shifted0 = vcombine_u8 (shifted0_low, shifted0_high);
139+ shifted1 = vcombine_u8 (shifted1_low, shifted1_high);
99140 case 3 :
100141 uint8_t buffer[32 ];
101142 torchao::bitpacking::internal::unpack_8_uint3_values (buffer, packed);
@@ -133,7 +174,7 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_64_lowbit_values(
133174 static_assert (nbit >= 2 );
134175
135176 // Currently supported values
136- static_assert (nbit >= 3 );
177+ static_assert (nbit >= 2 );
137178 static_assert (nbit <= 4 );
138179
139180 // Shift unpacked values to nonnegative range
@@ -144,6 +185,10 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_64_lowbit_values(
144185 uint8x16_t shifted3 = vreinterpretq_u8_s8 (vaddq_s8 (unpacked3, shift));
145186
146187 switch (nbit) {
188+ case 2 :
189+ torchao::bitpacking::internal::vec_pack_64_uint2_values (
190+ packed, shifted0, shifted1, shifted2, shifted3);
191+ break ;
147192 case 3 :
148193 torchao::bitpacking::internal::vec_pack_64_uint3_values (
149194 packed, shifted0, shifted1, shifted2, shifted3);
@@ -170,7 +215,7 @@ TORCHAO_ALWAYS_INLINE inline void vec_unpack_64_lowbit_values(
170215 static_assert (nbit >= 2 );
171216
172217 // Currently supported values
173- static_assert (nbit >= 3 );
218+ static_assert (nbit >= 2 );
174219 static_assert (nbit <= 4 );
175220
176221 uint8x16_t shifted0;
@@ -179,6 +224,10 @@ TORCHAO_ALWAYS_INLINE inline void vec_unpack_64_lowbit_values(
179224 uint8x16_t shifted3;
180225
181226 switch (nbit) {
227+ case 2 :
228+ torchao::bitpacking::internal::vec_unpack_64_uint2_values (
229+ shifted0, shifted1, shifted2, shifted3, packed);
230+ break ;
182231 case 3 :
183232 torchao::bitpacking::internal::vec_unpack_64_uint3_values (
184233 shifted0, shifted1, shifted2, shifted3, packed);
@@ -216,7 +265,7 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_128_lowbit_values(
216265 static_assert (nbit >= 2 );
217266
218267 // Currently supported values
219- static_assert (nbit >= 3 );
268+ static_assert (nbit >= 2 );
220269 static_assert (nbit <= 4 );
221270
222271 // Shift unpacked values to nonnegative range
@@ -231,6 +280,12 @@ TORCHAO_ALWAYS_INLINE inline void vec_pack_128_lowbit_values(
231280 uint8x16_t shifted7 = vreinterpretq_u8_s8 (vaddq_s8 (unpacked7, shift));
232281
233282 switch (nbit) {
283+ case 2 :
284+ torchao::bitpacking::internal::vec_pack_64_uint2_values (
285+ packed, shifted0, shifted1, shifted2, shifted3);
286+ torchao::bitpacking::internal::vec_pack_64_uint2_values (
287+ packed + 16 , shifted4, shifted5, shifted6, shifted7);
288+ break ;
234289 case 3 :
235290 torchao::bitpacking::internal::vec_pack_128_uint3_values (
236291 packed,
@@ -273,7 +328,7 @@ TORCHAO_ALWAYS_INLINE inline void vec_unpack_128_lowbit_values(
273328 static_assert (nbit >= 2 );
274329
275330 // Currently supported values
276- static_assert (nbit >= 3 );
331+ static_assert (nbit >= 2 );
277332 static_assert (nbit <= 4 );
278333
279334 uint8x16_t shifted0;
@@ -286,6 +341,12 @@ TORCHAO_ALWAYS_INLINE inline void vec_unpack_128_lowbit_values(
286341 uint8x16_t shifted7;
287342
288343 switch (nbit) {
344+ case 2 :
345+ torchao::bitpacking::internal::vec_unpack_64_uint2_values (
346+ shifted0, shifted1, shifted2, shifted3, packed);
347+ torchao::bitpacking::internal::vec_unpack_64_uint2_values (
348+ shifted4, shifted5, shifted6, shifted7, packed + 16 );
349+ break ;
289350 case 3 :
290351 torchao::bitpacking::internal::vec_unpack_128_uint3_values (
291352 shifted0,
0 commit comments