Line data Source code
1 :
2 : // Source originally from https://github.com/BLAKE3-team/BLAKE3
3 : // From commit: 64747d48ffe9d1fbf4b71e94cabeb8a211461081
4 :
5 : #include "fd_blake3.h"
6 : #include "fd_blake3_private.h"
7 : #include "../../util/simd/fd_avx.h"
8 :
9 7872527376 : #define wu_rot16 wb_exch_adj_pair
10 :
11 : static inline __attribute__((always_inline)) wu_t
12 7872527376 : wu_rot12( wu_t x ) {
13 7872527376 : return wu_ror( x, 12 );
14 7872527376 : }
15 :
16 : static inline __attribute__((always_inline)) wu_t
17 7872527376 : wu_rot8( wu_t x ) {
18 7872527376 : wb_t const mask =
19 7872527376 : wb( 1,2,3,0, 5,6,7,4, 9,10,11,8, 13,14,15,12,
20 7872527376 : 1,2,3,0, 5,6,7,4, 9,10,11,8, 13,14,15,12 );
21 7872527376 : return _mm256_shuffle_epi8( x, mask );
22 7872527376 : }
23 :
24 : static inline __attribute__((always_inline)) wu_t
25 7872527376 : wu_rot7( wu_t x ) {
26 7872527376 : return wu_ror( x, 7 );
27 7872527376 : }
28 :
29 : static inline __attribute__((always_inline)) void
30 : round_fn8( wu_t v[16],
31 : wu_t m[16],
32 984065922 : ulong r ) {
33 984065922 : v[ 0] = wu_add(v[0], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][0]]);
34 984065922 : v[ 1] = wu_add(v[1], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][2]]);
35 984065922 : v[ 2] = wu_add(v[2], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][4]]);
36 984065922 : v[ 3] = wu_add(v[3], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][6]]);
37 984065922 : v[ 0] = wu_add(v[0], v[4]);
38 984065922 : v[ 1] = wu_add(v[1], v[5]);
39 984065922 : v[ 2] = wu_add(v[2], v[6]);
40 984065922 : v[ 3] = wu_add(v[3], v[7]);
41 984065922 : v[12] = wu_xor(v[12], v[0]);
42 984065922 : v[13] = wu_xor(v[13], v[1]);
43 984065922 : v[14] = wu_xor(v[14], v[2]);
44 984065922 : v[15] = wu_xor(v[15], v[3]);
45 984065922 : v[12] = wu_rot16(v[12]);
46 984065922 : v[13] = wu_rot16(v[13]);
47 984065922 : v[14] = wu_rot16(v[14]);
48 984065922 : v[15] = wu_rot16(v[15]);
49 984065922 : v[ 8] = wu_add(v[8], v[12]);
50 984065922 : v[ 9] = wu_add(v[9], v[13]);
51 984065922 : v[10] = wu_add(v[10], v[14]);
52 984065922 : v[11] = wu_add(v[11], v[15]);
53 984065922 : v[ 4] = wu_xor(v[4], v[8]);
54 984065922 : v[ 5] = wu_xor(v[5], v[9]);
55 984065922 : v[ 6] = wu_xor(v[6], v[10]);
56 984065922 : v[ 7] = wu_xor(v[7], v[11]);
57 984065922 : v[ 4] = wu_rot12(v[4]);
58 984065922 : v[ 5] = wu_rot12(v[5]);
59 984065922 : v[ 6] = wu_rot12(v[6]);
60 984065922 : v[ 7] = wu_rot12(v[7]);
61 984065922 : v[ 0] = wu_add(v[0], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][1]]);
62 984065922 : v[ 1] = wu_add(v[1], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][3]]);
63 984065922 : v[ 2] = wu_add(v[2], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][5]]);
64 984065922 : v[ 3] = wu_add(v[3], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][7]]);
65 984065922 : v[ 0] = wu_add(v[0], v[4]);
66 984065922 : v[ 1] = wu_add(v[1], v[5]);
67 984065922 : v[ 2] = wu_add(v[2], v[6]);
68 984065922 : v[ 3] = wu_add(v[3], v[7]);
69 984065922 : v[12] = wu_xor(v[12], v[0]);
70 984065922 : v[13] = wu_xor(v[13], v[1]);
71 984065922 : v[14] = wu_xor(v[14], v[2]);
72 984065922 : v[15] = wu_xor(v[15], v[3]);
73 984065922 : v[12] = wu_rot8(v[12]);
74 984065922 : v[13] = wu_rot8(v[13]);
75 984065922 : v[14] = wu_rot8(v[14]);
76 984065922 : v[15] = wu_rot8(v[15]);
77 984065922 : v[ 8] = wu_add(v[8], v[12]);
78 984065922 : v[ 9] = wu_add(v[9], v[13]);
79 984065922 : v[10] = wu_add(v[10], v[14]);
80 984065922 : v[11] = wu_add(v[11], v[15]);
81 984065922 : v[ 4] = wu_xor(v[4], v[8]);
82 984065922 : v[ 5] = wu_xor(v[5], v[9]);
83 984065922 : v[ 6] = wu_xor(v[6], v[10]);
84 984065922 : v[ 7] = wu_xor(v[7], v[11]);
85 984065922 : v[ 4] = wu_rot7(v[4]);
86 984065922 : v[ 5] = wu_rot7(v[5]);
87 984065922 : v[ 6] = wu_rot7(v[6]);
88 984065922 : v[ 7] = wu_rot7(v[7]);
89 :
90 984065922 : v[ 0] = wu_add(v[0], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][8]]);
91 984065922 : v[ 1] = wu_add(v[1], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][10]]);
92 984065922 : v[ 2] = wu_add(v[2], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][12]]);
93 984065922 : v[ 3] = wu_add(v[3], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][14]]);
94 984065922 : v[ 0] = wu_add(v[0], v[5]);
95 984065922 : v[ 1] = wu_add(v[1], v[6]);
96 984065922 : v[ 2] = wu_add(v[2], v[7]);
97 984065922 : v[ 3] = wu_add(v[3], v[4]);
98 984065922 : v[15] = wu_xor(v[15], v[0]);
99 984065922 : v[12] = wu_xor(v[12], v[1]);
100 984065922 : v[13] = wu_xor(v[13], v[2]);
101 984065922 : v[14] = wu_xor(v[14], v[3]);
102 984065922 : v[15] = wu_rot16(v[15]);
103 984065922 : v[12] = wu_rot16(v[12]);
104 984065922 : v[13] = wu_rot16(v[13]);
105 984065922 : v[14] = wu_rot16(v[14]);
106 984065922 : v[10] = wu_add(v[10], v[15]);
107 984065922 : v[11] = wu_add(v[11], v[12]);
108 984065922 : v[ 8] = wu_add(v[8], v[13]);
109 984065922 : v[ 9] = wu_add(v[9], v[14]);
110 984065922 : v[ 5] = wu_xor(v[5], v[10]);
111 984065922 : v[ 6] = wu_xor(v[6], v[11]);
112 984065922 : v[ 7] = wu_xor(v[7], v[8]);
113 984065922 : v[ 4] = wu_xor(v[4], v[9]);
114 984065922 : v[ 5] = wu_rot12(v[5]);
115 984065922 : v[ 6] = wu_rot12(v[6]);
116 984065922 : v[ 7] = wu_rot12(v[7]);
117 984065922 : v[ 4] = wu_rot12(v[4]);
118 984065922 : v[ 0] = wu_add(v[0], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][9]]);
119 984065922 : v[ 1] = wu_add(v[1], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][11]]);
120 984065922 : v[ 2] = wu_add(v[2], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][13]]);
121 984065922 : v[ 3] = wu_add(v[3], m[(ulong)FD_BLAKE3_MSG_SCHEDULE[r][15]]);
122 984065922 : v[ 0] = wu_add(v[0], v[5]);
123 984065922 : v[ 1] = wu_add(v[1], v[6]);
124 984065922 : v[ 2] = wu_add(v[2], v[7]);
125 984065922 : v[ 3] = wu_add(v[3], v[4]);
126 984065922 : v[15] = wu_xor(v[15], v[0]);
127 984065922 : v[12] = wu_xor(v[12], v[1]);
128 984065922 : v[13] = wu_xor(v[13], v[2]);
129 984065922 : v[14] = wu_xor(v[14], v[3]);
130 984065922 : v[15] = wu_rot8(v[15]);
131 984065922 : v[12] = wu_rot8(v[12]);
132 984065922 : v[13] = wu_rot8(v[13]);
133 984065922 : v[14] = wu_rot8(v[14]);
134 984065922 : v[10] = wu_add(v[10], v[15]);
135 984065922 : v[11] = wu_add(v[11], v[12]);
136 984065922 : v[ 8] = wu_add(v[8], v[13]);
137 984065922 : v[ 9] = wu_add(v[9], v[14]);
138 984065922 : v[ 5] = wu_xor(v[5], v[10]);
139 984065922 : v[ 6] = wu_xor(v[6], v[11]);
140 984065922 : v[ 7] = wu_xor(v[7], v[8]);
141 984065922 : v[ 4] = wu_xor(v[4], v[9]);
142 984065922 : v[ 5] = wu_rot7(v[5]);
143 984065922 : v[ 6] = wu_rot7(v[6]);
144 984065922 : v[ 7] = wu_rot7(v[7]);
145 984065922 : v[ 4] = wu_rot7(v[4]);
146 984065922 : }
147 :
148 : void
149 : fd_blake3_avx_compress8( ulong batch_cnt,
150 : void const * restrict _batch_data,
151 : uint const * restrict batch_sz,
152 : ulong const * restrict ctr_vec,
153 : uint const * restrict batch_flags,
154 : void * const * restrict _batch_hash,
155 : ushort * restrict lthash,
156 : uint out_sz,
157 27827250 : void const * restrict batch_cv ) {
158 27827250 : if( FD_UNLIKELY( lthash && batch_cnt!=8 ) ) FD_LOG_ERR(( "Lane masking not supported for fd_blake3_avx_compress8 in LtHash mode" ));
159 27827250 : if( FD_UNLIKELY( batch_cnt==0 || batch_cnt>8 ) ) FD_LOG_ERR(( "Invalid batch_cnt %lu", batch_cnt ));
160 :
161 27827250 : ulong const * batch_data = (ulong const *)_batch_data;
162 :
163 27827250 : if( FD_UNLIKELY( batch_cnt==1 ) ) {
164 380460 : fd_blake3_sse_compress1( (uchar *)(_batch_hash[0]),
165 380460 : (uchar const *)(batch_data[0]),
166 380460 : batch_sz[0],
167 380460 : ctr_vec[0],
168 380460 : batch_flags[0],
169 380460 : NULL,
170 380460 : NULL );
171 380460 : return;
172 380460 : }
173 :
174 : #if FD_BLAKE3_TRACING
175 : /* This log_line buffer is oversized by a fair bit (due to all the
176 : NULL terminators) but that's fine */
177 : char log_line[
178 : sizeof( "fd_blake3_avx_compress8" )+
179 : sizeof( "(batch_cnt=" )+21+
180 : sizeof( ",sz=[" )+(8*11)+sizeof( "]" )+
181 : sizeof( ",counter=[" )+(8*21)+sizeof( "]" )+
182 : sizeof( ",flags=[" )+(8* 2)+sizeof( "]" )+
183 : sizeof( ",custom_cv" )+
184 : sizeof( ",lthash" )+
185 : sizeof( ")" ) ];
186 :
187 : char * p = fd_cstr_init( log_line );
188 : p = fd_cstr_append_text( p, "fd_blake3_avx_compress8(batch_cnt=", 34UL );
189 : p = fd_cstr_append_ulong_as_text( p, 0, 0, batch_cnt, fd_uchar_base10_dig_cnt( (uchar)batch_cnt ) );
190 : p = fd_cstr_append_text( p, ",sz=[", 5UL );
191 : for( ulong i=0UL; i<batch_cnt; i++ ) {
192 : p = fd_cstr_append_uint_as_text( p, ' ', 0, batch_sz[ i ], fd_uint_base10_dig_cnt( batch_sz[ i ] ) );
193 : if( i+1<batch_cnt ) p = fd_cstr_append_char( p, ',' );
194 : }
195 : p = fd_cstr_append_text( p, "],counter=[", 11UL );
196 : for( ulong i=0UL; i<batch_cnt; i++ ) {
197 : p = fd_cstr_append_ulong_as_text( p, ' ', 0, ctr_vec[ i ], fd_ulong_base10_dig_cnt( ctr_vec[ i ] ) );
198 : if( i+1<batch_cnt ) p = fd_cstr_append_char( p, ',' );
199 : }
200 : p = fd_cstr_append_text( p, "],flags=[", 9UL );
201 : for( ulong i=0UL; i<batch_cnt; i++ ) {
202 : static char const hex_lut[ 16 ] = {
203 : '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
204 : };
205 : p = fd_cstr_append_char( p, hex_lut[ batch_flags[ i ]&0xf ] );
206 : if( i+1<batch_cnt ) p = fd_cstr_append_char( p, ',' );
207 : }
208 : p = fd_cstr_append_char( p, ']' );
209 : if( batch_cv ) p = fd_cstr_append_text( p, ",custom_cv", 10UL );
210 : if( lthash ) p = fd_cstr_append_text( p, ",lthash", 7UL );
211 : p = fd_cstr_append_char( p, ')' );
212 : ulong line_len = (ulong)( p-log_line );
213 : fd_cstr_fini( p );
214 :
215 : FD_BLAKE3_TRACE(( "%.*s", (int)line_len, log_line ));
216 : #endif
217 :
218 : /* We can only process input blocks of 64 bytes, but message data size
219 : is not necessarily a multiple of 64. We compute the tail block of
220 : each message here. We then process complete blocks of the original
221 : message in place, switching to processing to these tail blocks in
222 : the same pass toward the end. */
223 :
224 27446790 : ulong batch_tail_data[ 8 ] __attribute__((aligned(32)));
225 27446790 : ulong batch_tail_rem [ 8 ] __attribute__((aligned(32)));
226 :
227 27446790 : uchar scratch[ 8*FD_BLAKE3_BLOCK_SZ ] __attribute__((aligned(128)));
228 27446790 : do {
229 27446790 : ulong scratch_free = (ulong)scratch;
230 :
231 27446790 : wv_t zero = wv_zero();
232 :
233 242448516 : for( ulong batch_idx=0UL; batch_idx<batch_cnt; batch_idx++ ) {
234 :
235 : /* Allocate the tail blocks for this message */
236 :
237 215001726 : ulong data = batch_data[ batch_idx ];
238 215001726 : ulong sz = batch_sz [ batch_idx ];
239 :
240 215001726 : ulong tail_data = scratch_free;
241 215001726 : ulong tail_data_sz = sz & (FD_BLAKE3_BLOCK_SZ-1UL);
242 215001726 : ulong tail_data_off = fd_ulong_align_dn( sz, FD_BLAKE3_BLOCK_SZ );
243 :
244 215001726 : batch_tail_data[ batch_idx ] = tail_data;
245 215001726 : batch_tail_rem [ batch_idx ] = (ulong)( (!!tail_data_sz) ^ (!sz) ); /* (hash 1 tail block if 0 sz) */
246 :
247 215001726 : scratch_free += FD_BLAKE3_BLOCK_SZ;
248 :
249 : /* Populate the tail blocks. We first clear the blocks. Then we
250 : copy any straggler data bytes into the tail. */
251 :
252 215001726 : wv_st( (ulong *) tail_data, zero );
253 215001726 : wv_st( (ulong *)(tail_data+32), zero );
254 :
255 215001726 : # if 1
256 : /* See fd_sha256_private_batch_avx */
257 215001726 : ulong src = (ulong)data + tail_data_off;
258 215001726 : ulong dst = tail_data;
259 215001726 : ulong rem = tail_data_sz;
260 242101894 : while( rem>=32UL ) { wv_st( (ulong *)dst, wv_ldu( (ulong const *)src ) ); dst += 32UL; src += 32UL; rem -= 32UL; }
261 296221108 : while( rem>= 8UL ) { *(ulong *)dst = FD_LOAD( ulong, src ); dst += 8UL; src += 8UL; rem -= 8UL; }
262 215001726 : if ( rem>= 4UL ) { *(uint *)dst = FD_LOAD( uint, src ); dst += 4UL; src += 4UL; rem -= 4UL; }
263 215001726 : if ( rem>= 2UL ) { *(ushort *)dst = FD_LOAD( ushort, src ); dst += 2UL; src += 2UL; rem -= 2UL; }
264 215001726 : if ( rem ) { *(uchar *)dst = FD_LOAD( uchar, src ); dst++; }
265 : # else
266 : fd_memcpy( (void *)tail_data, (void const *)(data + tail_data_off), tail_data_sz );
267 : # endif
268 215001726 : }
269 27446790 : } while(0);
270 :
271 :
272 27446790 : wu_t const iv0 = wu_bcast( FD_BLAKE3_IV[0] );
273 27446790 : wu_t const iv1 = wu_bcast( FD_BLAKE3_IV[1] );
274 27446790 : wu_t const iv2 = wu_bcast( FD_BLAKE3_IV[2] );
275 27446790 : wu_t const iv3 = wu_bcast( FD_BLAKE3_IV[3] );
276 27446790 : wu_t const iv4 = wu_bcast( FD_BLAKE3_IV[4] );
277 27446790 : wu_t const iv5 = wu_bcast( FD_BLAKE3_IV[5] );
278 27446790 : wu_t const iv6 = wu_bcast( FD_BLAKE3_IV[6] );
279 27446790 : wu_t const iv7 = wu_bcast( FD_BLAKE3_IV[7] );
280 :
281 27446790 : wu_t h0=iv0; wu_t h1=iv1; wu_t h2=iv2; wu_t h3=iv3;
282 27446790 : wu_t h4=iv4; wu_t h5=iv5; wu_t h6=iv6; wu_t h7=iv7;
283 27446790 : if( FD_UNLIKELY( batch_cv ) ) {
284 : /* If the input chaining value is overridden, transpose the input to
285 : AVX representation (8x8 transpose). */
286 24776984 : __m256i const ** cv_vec = (__m256i const **)batch_cv;
287 24776984 : wu_t cv[8];
288 222992856 : for( ulong i=0UL; i<8UL; i++ ) cv[i] = _mm256_loadu_si256( cv_vec[ i ] );
289 24776984 : wu_transpose_8x8( cv[0], cv[1], cv[2], cv[3], cv[4], cv[5], cv[6], cv[7],
290 24776984 : h0, h1, h2, h3, h4, h5, h6, h7 );
291 24776984 : }
292 :
293 27446790 : wu_t ctr_lo = wu( ctr_vec[0], ctr_vec[1], ctr_vec[2], ctr_vec[3],
294 27446790 : ctr_vec[4], ctr_vec[5], ctr_vec[6], ctr_vec[7] );
295 27446790 : wu_t ctr_hi = wu( ctr_vec[0]>>32, ctr_vec[1]>>32, ctr_vec[2]>>32, ctr_vec[3]>>32,
296 27446790 : ctr_vec[4]>>32, ctr_vec[5]>>32, ctr_vec[6]>>32, ctr_vec[7]>>32 );
297 27446790 : wu_t flags = wu_ldu( batch_flags );
298 27446790 : wu_t off = wu_zero();
299 27446790 : wu_t sz = wu_ldu( batch_sz );
300 :
301 27446790 : wv_t wv_64 = wv_bcast( FD_BLAKE3_BLOCK_SZ );
302 27446790 : wv_t W_sentinel = wv_bcast( (ulong)scratch );
303 27446790 : wc_t batch_lane = wc_unpack( (1<<batch_cnt)-1 );
304 :
305 27446790 : wv_t tail_lo = wv_ld( batch_tail_data );
306 27446790 : wv_t tail_hi = wv_ld( batch_tail_data+4 );
307 :
308 27446790 : wv_t tail_rem_lo = wv_ld( batch_tail_rem );
309 27446790 : wv_t tail_rem_hi = wv_ld( batch_tail_rem+4 );
310 :
311 27446790 : wv_t W_lo = wv_ld( batch_data );
312 27446790 : wv_t W_hi = wv_ld( batch_data+4 );
313 :
314 27446790 : wv_t batch_sz_lo = _mm256_cvtepi32_epi64( _mm256_extractf128_si256( sz, 0 ) );
315 27446790 : wv_t batch_sz_hi = _mm256_cvtepi32_epi64( _mm256_extractf128_si256( sz, 1 ) );
316 :
317 27446790 : wv_t block_rem_lo = wv_notczero( wc_expand( batch_lane, 0 ),
318 27446790 : wv_add( wv_shr( batch_sz_lo, FD_BLAKE3_BLOCK_LG_SZ ), tail_rem_lo ) );
319 27446790 : wv_t block_rem_hi = wv_notczero( wc_expand( batch_lane, 1 ),
320 27446790 : wv_add( wv_shr( batch_sz_hi, FD_BLAKE3_BLOCK_LG_SZ ), tail_rem_hi ) );
321 :
322 : /* Upper half of the compression function output.
323 : Usually thrown away, but kept in the final compression round if
324 : out_sz==64. */
325 27446790 : wu_t hu[8] = {0};
326 :
327 27446790 : ulong lthash_rem = lthash ? 32 : 0; /* Number of LtHash (XOF) blocks remaining */
328 27446790 : int compress_done = 0;
329 61513180 : for(;;) {
330 : /* Switch lanes that have hit the end of their in-place bulk
331 : processing to their out-of-place scratch tail regions as
332 : necessary. */
333 :
334 61513180 : W_lo = wv_if( wv_eq( block_rem_lo, tail_rem_lo ), tail_lo, W_lo );
335 61513180 : W_hi = wv_if( wv_eq( block_rem_hi, tail_rem_hi ), tail_hi, W_hi );
336 :
337 : /* Derive per-block flags and block sizes */
338 :
339 61513180 : wc_t block_first = wu_eq( off, wu_zero() );
340 61513180 : wc_t block_last = wi_lt( sz, wu_add( off, wu_bcast( FD_BLAKE3_BLOCK_SZ+1 ) ) );
341 :
342 : /* Suppress root flag unless last block */
343 :
344 61513180 : wu_t root_mask = wu_or( block_last, wu_bcast( ~FD_BLAKE3_FLAG_ROOT ) );
345 61513180 : wu_t block_flags = wu_and( flags, root_mask );
346 :
347 : /* LtHash mode ends compression one early */
348 :
349 61513180 : wc_t active_lane_lo;
350 61513180 : wc_t active_lane_hi;
351 61513180 : if( FD_UNLIKELY( lthash ) ) {
352 : /* Compress until root block */
353 6648896 : wu_t all_root = wu_bcast( FD_BLAKE3_FLAG_ROOT );
354 6648896 : wu_t not_root = wu_ne( wu_and( block_flags, all_root ), all_root );
355 6648896 : active_lane_lo = _mm256_cvtepi32_epi64( _mm256_extractf128_si256( not_root, 0 ) );
356 6648896 : active_lane_hi = _mm256_cvtepi32_epi64( _mm256_extractf128_si256( not_root, 1 ) );
357 56331946 : } else {
358 : /* Complete when there is no more input data */
359 54864284 : active_lane_lo = wv_to_wc( block_rem_lo );
360 54864284 : active_lane_hi = wv_to_wc( block_rem_hi );
361 54864284 : }
362 :
363 : /* Suppress CHUNK_{START,END} flags unless leaf node */
364 :
365 61513180 : wc_t is_parent = wu_shl( flags, 5 ); /* shift FLAG_PARENT into AVX condition bit */
366 61513180 : wu_t chunk_flags = wu_if( block_last, wu_bcast( FD_BLAKE3_FLAG_CHUNK_END ), wu_zero() );
367 61513180 : if( out_sz==32 ) {
368 : /* Hacky: out_sz==64 is only used for post-compress XOF hashing,
369 : so use that as a hint when to suppress the 'CHUNK_START' flag. */
370 11959212 : chunk_flags = wu_or( chunk_flags, wu_if( block_first, wu_bcast( FD_BLAKE3_FLAG_CHUNK_START ), wu_zero() ) );
371 11959212 : }
372 61513180 : wu_t block_sz = wu_min( wu_sub( sz, off ), wu_bcast( FD_BLAKE3_BLOCK_SZ ) );
373 61513180 : block_flags = wu_or( block_flags, wu_if( is_parent, wu_zero(), chunk_flags ) );
374 :
375 : /* Check if we are done compressing */
376 :
377 61513180 : compress_done |= !wc_any( wc_or( active_lane_lo, active_lane_hi ) );
378 61513180 : if( FD_UNLIKELY( compress_done ) ) {
379 27446790 : if( FD_UNLIKELY( !lthash_rem ) ) break;
380 1378478 : active_lane_lo = wc_bcast( INT_MAX );
381 1378478 : active_lane_hi = wc_bcast( INT_MAX );
382 : /* Load the next message block and fall through to XOF expansion */
383 1378478 : }
384 :
385 : /* At this point, we have at least 1 block in this message segment
386 : pass that has not been processed. Load the next 64 bytes of
387 : each unprocessed block. Inactive lanes (e.g. message segments
388 : in this pass for which we've already processed all the blocks)
389 : will load garbage from a sentinel location (and the result of
390 : the state computations for the inactive lane will be ignored). */
391 :
392 35444868 : wv_t W03 = wv_if( active_lane_lo, W_lo, W_sentinel );
393 35444868 : uchar const * W0 = (uchar const *)wv_extract( W03, 0 );
394 35444868 : uchar const * W1 = (uchar const *)wv_extract( W03, 1 );
395 35444868 : uchar const * W2 = (uchar const *)wv_extract( W03, 2 );
396 35444868 : uchar const * W3 = (uchar const *)wv_extract( W03, 3 );
397 :
398 35444868 : wv_t W47 = wv_if( active_lane_hi, W_hi, W_sentinel );
399 35444868 : uchar const * W4 = (uchar const *)wv_extract( W47, 0 );
400 35444868 : uchar const * W5 = (uchar const *)wv_extract( W47, 1 );
401 35444868 : uchar const * W6 = (uchar const *)wv_extract( W47, 2 );
402 35444868 : uchar const * W7 = (uchar const *)wv_extract( W47, 3 );
403 :
404 35444868 : wu_t m[16] = { wu_ldu( W0 ), wu_ldu( W1 ), wu_ldu( W2 ), wu_ldu( W3 ),
405 35444868 : wu_ldu( W4 ), wu_ldu( W5 ), wu_ldu( W6 ), wu_ldu( W7 ),
406 35444868 : wu_ldu( W0+32 ), wu_ldu( W1+32 ), wu_ldu( W2+32 ), wu_ldu( W3+32 ),
407 35444868 : wu_ldu( W4+32 ), wu_ldu( W5+32 ), wu_ldu( W6+32 ), wu_ldu( W7+32 ) };
408 :
409 35444868 : wu_transpose_8x8( m[0x0], m[0x1], m[0x2], m[0x3], m[0x4], m[0x5], m[0x6], m[0x7],
410 35444868 : m[0x0], m[0x1], m[0x2], m[0x3], m[0x4], m[0x5], m[0x6], m[0x7] );
411 35444868 : wu_transpose_8x8( m[0x8], m[0x9], m[0xa], m[0xb], m[0xc], m[0xd], m[0xe], m[0xf],
412 35444868 : m[0x8], m[0x9], m[0xa], m[0xb], m[0xc], m[0xd], m[0xe], m[0xf] );
413 :
414 : /* Compute the BLAKE3 compression function updates */
415 :
416 78177686 : compress: (void)0;
417 78177686 : wu_t v[16] = {
418 78177686 : h0, h1, h2, h3,
419 78177686 : h4, h5, h6, h7,
420 78177686 : iv0, iv1, iv2, iv3,
421 78177686 : ctr_lo, ctr_hi, block_sz, block_flags,
422 78177686 : };
423 :
424 : /* Debug utility */
425 78177686 : #define STATE_FMT "state[%u] =\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n %08x %08x %08x %08x"
426 78177686 : #define STATE_FMT_ARGS(v,i) (uint)i,\
427 78177686 : fd_uint_bswap(wu_extract(v[0x0],i)),fd_uint_bswap(wu_extract(v[0x1],i)),fd_uint_bswap(wu_extract(v[0x2],i)),fd_uint_bswap(wu_extract(v[0x3],i)),\
428 78177686 : fd_uint_bswap(wu_extract(v[0x4],i)),fd_uint_bswap(wu_extract(v[0x5],i)),fd_uint_bswap(wu_extract(v[0x6],i)),fd_uint_bswap(wu_extract(v[0x7],i)),\
429 78177686 : fd_uint_bswap(wu_extract(v[0x8],i)),fd_uint_bswap(wu_extract(v[0x9],i)),fd_uint_bswap(wu_extract(v[0xa],i)),fd_uint_bswap(wu_extract(v[0xb],i)),\
430 78177686 : fd_uint_bswap(wu_extract(v[0xc],i)),fd_uint_bswap(wu_extract(v[0xd],i)),fd_uint_bswap(wu_extract(v[0xe],i)),fd_uint_bswap(wu_extract(v[0xf],i))
431 :
432 : // FD_LOG_NOTICE(( STATE_FMT, STATE_FMT_ARGS(v,0) ));
433 78177686 : round_fn8( v, m, 0 );
434 78177686 : round_fn8( v, m, 1 );
435 78177686 : round_fn8( v, m, 2 );
436 78177686 : round_fn8( v, m, 3 );
437 78177686 : round_fn8( v, m, 4 );
438 78177686 : round_fn8( v, m, 5 );
439 78177686 : round_fn8( v, m, 6 );
440 : // FD_LOG_NOTICE(( STATE_FMT, STATE_FMT_ARGS(v,0) ));
441 :
442 78177686 : wu_t d[8] = {
443 78177686 : wu_xor( v[ 0], v[ 8] ), wu_xor( v[ 1], v[ 9] ),
444 78177686 : wu_xor( v[ 2], v[10] ), wu_xor( v[ 3], v[11] ),
445 78177686 : wu_xor( v[ 4], v[12] ), wu_xor( v[ 5], v[13] ),
446 78177686 : wu_xor( v[ 6], v[14] ), wu_xor( v[ 7], v[15] )
447 78177686 : };
448 :
449 78177686 : if( FD_LIKELY( !compress_done ) ) {
450 :
451 : /* Apply the state updates to the active lanes */
452 :
453 34066390 : wc_t active_lane = wc_narrow( active_lane_lo, active_lane_hi );
454 34066390 : if( FD_UNLIKELY( out_sz==64 ) ) {
455 : /* FIXME only export in the last iteration */
456 24776984 : hu[0] = wu_if( active_lane, wu_xor( h0, v[ 8] ), hu[0] );
457 24776984 : hu[1] = wu_if( active_lane, wu_xor( h1, v[ 9] ), hu[1] );
458 24776984 : hu[2] = wu_if( active_lane, wu_xor( h2, v[10] ), hu[2] );
459 24776984 : hu[3] = wu_if( active_lane, wu_xor( h3, v[11] ), hu[3] );
460 24776984 : hu[4] = wu_if( active_lane, wu_xor( h4, v[12] ), hu[4] );
461 24776984 : hu[5] = wu_if( active_lane, wu_xor( h5, v[13] ), hu[5] );
462 24776984 : hu[6] = wu_if( active_lane, wu_xor( h6, v[14] ), hu[6] );
463 24776984 : hu[7] = wu_if( active_lane, wu_xor( h7, v[15] ), hu[7] );
464 24776984 : }
465 34066390 : h0 = wu_if( active_lane, d[0], h0 );
466 34066390 : h1 = wu_if( active_lane, d[1], h1 );
467 34066390 : h2 = wu_if( active_lane, d[2], h2 );
468 34066390 : h3 = wu_if( active_lane, d[3], h3 );
469 34066390 : h4 = wu_if( active_lane, d[4], h4 );
470 34066390 : h5 = wu_if( active_lane, d[5], h5 );
471 34066390 : h6 = wu_if( active_lane, d[6], h6 );
472 34066390 : h7 = wu_if( active_lane, d[7], h7 );
473 :
474 : /* Advance to the next message segment blocks. In pseudo code,
475 : the below is:
476 :
477 : W += 64; if( block_rem ) block_rem--;
478 :
479 : Since wc_to_wv_raw(false/true) is 0UL/~0UL, we can use wv_add /
480 : wc_to_wv_raw instead of wv_sub / wc_to_wv to save some ops.
481 : (Consider conditional increment / decrement operations?)
482 :
483 : Also since we do not load anything at W(lane) above unless
484 : block_rem(lane) is non-zero, we can omit vector conditional
485 : operations for W(lane) below to save some additional ops. */
486 :
487 34066390 : W_lo = wv_add( W_lo, wv_if( active_lane_lo, wv_64, wv_zero() ) );
488 34066390 : W_hi = wv_add( W_hi, wv_if( active_lane_hi, wv_64, wv_zero() ) );
489 34066390 : off = wu_add( off, wu_if( active_lane, wu_bcast( FD_BLAKE3_BLOCK_SZ ), wv_zero() ) );
490 :
491 34066390 : block_rem_lo = wv_add( block_rem_lo, wv_if( active_lane_lo, wc_to_wv_raw( active_lane_lo ), wv_zero() ) );
492 34066390 : block_rem_hi = wv_add( block_rem_hi, wv_if( active_lane_hi, wc_to_wv_raw( active_lane_hi ), wv_zero() ) );
493 :
494 44111296 : } else { /* LtHash mode */
495 :
496 : /* d[i] contains output_off+(i*4) 32-bit words across output[0..8] */
497 44111296 : wu_t dh[ 8 ] = {
498 44111296 : wu_xor( h0, v[0x8] ),
499 44111296 : wu_xor( h1, v[0x9] ),
500 44111296 : wu_xor( h2, v[0xa] ),
501 44111296 : wu_xor( h3, v[0xb] ),
502 44111296 : wu_xor( h4, v[0xc] ),
503 44111296 : wu_xor( h5, v[0xd] ),
504 44111296 : wu_xor( h6, v[0xe] ),
505 44111296 : wu_xor( h7, v[0xf] )
506 44111296 : };
507 :
508 : /* Transpose outer 8x8 blocks */
509 44111296 : wu_transpose_8x8( d [0],d [1],d [2],d [3],d [4],d [5],d [6],d [7],
510 44111296 : d [0],d [1],d [2],d [3],d [4],d [5],d [6],d [7] );
511 44111296 : wu_transpose_8x8( dh[0],dh[1],dh[2],dh[3],dh[4],dh[5],dh[6],dh[7],
512 44111296 : dh[0],dh[1],dh[2],dh[3],dh[4],dh[5],dh[6],dh[7] );
513 :
514 : /* d[i] contains output[i]+out_off */
515 :
516 : /* Reduce-add into d[0] */
517 44111296 : d [0] = wh_add( d [0], d [1] ); /* sum(l[0 1]) */
518 44111296 : dh[0] = wh_add( dh[0], dh[1] ); /* sum(h[0 1]) */
519 44111296 : d [2] = wh_add( d [2], d [3] ); /* sum(l[2 3]) */
520 44111296 : dh[2] = wh_add( dh[2], dh[3] ); /* sum(h[2 3]) */
521 44111296 : d [4] = wh_add( d [4], d [5] ); /* sum(l[4 5])*/
522 44111296 : dh[4] = wh_add( dh[4], dh[5] ); /* sum(h[4 5]) */
523 44111296 : d [6] = wh_add( d [6], d [7] ); /* sum(l[6 7]) */
524 44111296 : dh[6] = wh_add( dh[6], dh[7] ); /* sum(h[6 7]) */
525 44111296 : d [0] = wh_add( d [0], d [2] ); /* sum(l[0 1 2 3]) */
526 44111296 : dh[0] = wh_add( dh[0], dh[2] ); /* sum(h[0 1 2 3]) */
527 44111296 : d [4] = wh_add( d [4], d [6] ); /* sum(l[4 5 6 7]) */
528 44111296 : dh[4] = wh_add( dh[4], dh[6] ); /* sum(h[4 5 6 7]) */
529 44111296 : d [0] = wh_add( d [0], d [4] ); /* sum(l[0 1 2 3 4 5 6 7]) */
530 44111296 : dh[0] = wh_add( dh[0], dh[4] ); /* sum(h[0 1 2 3 4 5 6 7]) */
531 44111296 : wh_st( lthash, d [0] );
532 44111296 : wh_st( lthash+16, dh[0] );
533 :
534 : /* Wind up for next iteration */
535 44111296 : lthash += 32;
536 44111296 : lthash_rem--;
537 44111296 : wu_t ctr_add = wu_bcast( 1 );
538 44111296 : /**/ ctr_lo = wu_add( ctr_lo, ctr_add );
539 44111296 : wu_t ctr_carry = wi_gt ( wu_xor( ctr_add, wu_bcast( 0x80000000 ) ),
540 44111296 : wu_xor( ctr_lo, wu_bcast( 0x80000000 ) ) );
541 44111296 : /**/ ctr_hi = wu_sub( ctr_hi, ctr_carry );
542 44111296 : if( FD_UNLIKELY( !lthash_rem ) ) {
543 1378478 : FD_BLAKE3_TRACE(( "fd_blake3_avx_compress8: done (lthash para)" ));
544 1378478 : return;
545 1378478 : }
546 42732818 : goto compress;
547 :
548 44111296 : # undef STATE_FMT
549 44111296 : # undef STATE_FMT_ARGS
550 44111296 : }
551 78177686 : }
552 :
553 : /* Store the results */
554 :
555 26068312 : wu_transpose_8x8( h0, h1, h2, h3, h4, h5, h6, h7,
556 26068312 : h0, h1, h2, h3, h4, h5, h6, h7 );
557 :
558 26068312 : uint * const * batch_hash = (uint * const *)__builtin_assume_aligned( _batch_hash, 32 );
559 26068312 : if( FD_LIKELY( out_sz==32 ) ) {
560 1291328 : switch( batch_cnt ) { /* application dependent prob */
561 176218 : case 8UL: wu_st( batch_hash[7], h7 ); __attribute__((fallthrough));
562 309838 : case 7UL: wu_st( batch_hash[6], h6 ); __attribute__((fallthrough));
563 443878 : case 6UL: wu_st( batch_hash[5], h5 ); __attribute__((fallthrough));
564 593404 : case 5UL: wu_st( batch_hash[4], h4 ); __attribute__((fallthrough));
565 731972 : case 4UL: wu_st( batch_hash[3], h3 ); __attribute__((fallthrough));
566 920064 : case 3UL: wu_st( batch_hash[2], h2 ); __attribute__((fallthrough));
567 1291328 : case 2UL: wu_st( batch_hash[1], h1 ); __attribute__((fallthrough));
568 1291328 : case 1UL: wu_st( batch_hash[0], h0 ); __attribute__((fallthrough));
569 1291328 : default: break;
570 1291328 : }
571 24776984 : } else if( out_sz==64 ) {
572 24776984 : wu_transpose_8x8( hu[0], hu[1], hu[2], hu[3], hu[4], hu[5], hu[6], hu[7],
573 24776984 : hu[0], hu[1], hu[2], hu[3], hu[4], hu[5], hu[6], hu[7] );
574 24776984 : switch( batch_cnt ) { /* application dependent prob */
575 24776984 : case 8UL: wu_st( batch_hash[7], h7 );
576 24776984 : wu_st( batch_hash[7]+8, hu[7] ); __attribute__((fallthrough));
577 24776984 : case 7UL: wu_st( batch_hash[6], h6 );
578 24776984 : wu_st( batch_hash[6]+8, hu[6] ); __attribute__((fallthrough));
579 24776984 : case 6UL: wu_st( batch_hash[5], h5 );
580 24776984 : wu_st( batch_hash[5]+8, hu[5] ); __attribute__((fallthrough));
581 24776984 : case 5UL: wu_st( batch_hash[4], h4 );
582 24776984 : wu_st( batch_hash[4]+8, hu[4] ); __attribute__((fallthrough));
583 24776984 : case 4UL: wu_st( batch_hash[3], h3 );
584 24776984 : wu_st( batch_hash[3]+8, hu[3] ); __attribute__((fallthrough));
585 24776984 : case 3UL: wu_st( batch_hash[2], h2 );
586 24776984 : wu_st( batch_hash[2]+8, hu[2] ); __attribute__((fallthrough));
587 24776984 : case 2UL: wu_st( batch_hash[1], h1 );
588 24776984 : wu_st( batch_hash[1]+8, hu[1] ); __attribute__((fallthrough));
589 24776984 : case 1UL: wu_st( batch_hash[0], h0 );
590 24776984 : wu_st( batch_hash[0]+8, hu[0] ); __attribute__((fallthrough));
591 24776984 : default: break;
592 24776984 : }
593 24776984 : } else {
594 0 : FD_LOG_ERR(( "Invalid out_sz %u", out_sz ));
595 0 : }
596 26068312 : }
597 :
598 : void
599 : fd_blake3_avx_compress8_fast( uchar const * restrict msg,
600 : uchar * restrict _out,
601 : ulong counter,
602 6825580 : uchar flags ) {
603 6825580 : FD_BLAKE3_TRACE(( "fd_blake3_avx_compress8_fast(msg=%p,out=%p,counter=%lu,flags=%02x)", (void *)msg, (void *)_out, counter, flags ));
604 :
605 6825580 : uchar * restrict out = __builtin_assume_aligned( _out, 32 );
606 :
607 6825580 : int parent = flags & FD_BLAKE3_FLAG_PARENT;
608 6825580 : int lg_sz = fd_int_if( parent, FD_BLAKE3_OUTCHAIN_LG_SZ+1, FD_BLAKE3_CHUNK_LG_SZ );
609 6825580 : ulong sz = 1UL<<lg_sz;
610 :
611 : /* counters stay the same for each block. Across chunks, they
612 : increment if we are hashing leaves. Otherwise, they are zero. */
613 :
614 6825580 : wu_t ctr_add = wu_and( wu_bcast( parent ? 0 : UINT_MAX ),
615 6825580 : wu( 0, 1, 2, 3, 4, 5, 6, 7 ) );
616 6825580 : wu_t ctr_lo = wu_add( wu_bcast( counter ), ctr_add );
617 6825580 : wu_t ctr_carry = wi_gt ( wu_xor( ctr_add, wu_bcast( 0x80000000 ) ),
618 6825580 : wu_xor( ctr_lo, wu_bcast( 0x80000000 ) ) );
619 6825580 : wu_t ctr_hi = wu_sub( wu_bcast( counter>>32 ), ctr_carry );
620 6825580 : wu_t sz_vec = wu_bcast( FD_BLAKE3_BLOCK_SZ );
621 :
622 6825580 : wu_t const iv0 = wu_bcast( FD_BLAKE3_IV[0] );
623 6825580 : wu_t const iv1 = wu_bcast( FD_BLAKE3_IV[1] );
624 6825580 : wu_t const iv2 = wu_bcast( FD_BLAKE3_IV[2] );
625 6825580 : wu_t const iv3 = wu_bcast( FD_BLAKE3_IV[3] );
626 6825580 : wu_t const iv4 = wu_bcast( FD_BLAKE3_IV[4] );
627 6825580 : wu_t const iv5 = wu_bcast( FD_BLAKE3_IV[5] );
628 6825580 : wu_t const iv6 = wu_bcast( FD_BLAKE3_IV[6] );
629 6825580 : wu_t const iv7 = wu_bcast( FD_BLAKE3_IV[7] );
630 :
631 6825580 : wu_t h0=iv0; wu_t h1=iv1; wu_t h2=iv2; wu_t h3=iv3;
632 6825580 : wu_t h4=iv4; wu_t h5=iv5; wu_t h6=iv6; wu_t h7=iv7;
633 :
634 6825580 : ulong off = 0UL;
635 62403160 : do {
636 62403160 : ulong const off_next = off+FD_BLAKE3_BLOCK_SZ;
637 62403160 : uint chunk_flags =
638 62403160 : ( off ==0UL ? FD_BLAKE3_FLAG_CHUNK_START : 0u ) |
639 62403160 : ( off_next==sz ? FD_BLAKE3_FLAG_CHUNK_END : 0u );
640 62403160 : uint flags_ = flags | fd_uint_if( parent, 0, chunk_flags );
641 62403160 : wu_t flags_vec = wu_bcast( flags_ );
642 :
643 62403160 : wu_t m[16];
644 62403160 : m[ 0] = wu_ldu( msg + (0<<lg_sz) + off );
645 62403160 : m[ 1] = wu_ldu( msg + (1<<lg_sz) + off );
646 62403160 : m[ 2] = wu_ldu( msg + (2<<lg_sz) + off );
647 62403160 : m[ 3] = wu_ldu( msg + (3<<lg_sz) + off );
648 62403160 : m[ 4] = wu_ldu( msg + (4<<lg_sz) + off );
649 62403160 : m[ 5] = wu_ldu( msg + (5<<lg_sz) + off );
650 62403160 : m[ 6] = wu_ldu( msg + (6<<lg_sz) + off );
651 62403160 : m[ 7] = wu_ldu( msg + (7<<lg_sz) + off );
652 62403160 : m[ 8] = wu_ldu( msg + (0<<lg_sz) + off + 32 );
653 62403160 : m[ 9] = wu_ldu( msg + (1<<lg_sz) + off + 32 );
654 62403160 : m[10] = wu_ldu( msg + (2<<lg_sz) + off + 32 );
655 62403160 : m[11] = wu_ldu( msg + (3<<lg_sz) + off + 32 );
656 62403160 : m[12] = wu_ldu( msg + (4<<lg_sz) + off + 32 );
657 62403160 : m[13] = wu_ldu( msg + (5<<lg_sz) + off + 32 );
658 62403160 : m[14] = wu_ldu( msg + (6<<lg_sz) + off + 32 );
659 62403160 : m[15] = wu_ldu( msg + (7<<lg_sz) + off + 32 );
660 :
661 62403160 : wu_transpose_8x8( m[0x0], m[0x1], m[0x2], m[0x3], m[0x4], m[0x5], m[0x6], m[0x7],
662 62403160 : m[0x0], m[0x1], m[0x2], m[0x3], m[0x4], m[0x5], m[0x6], m[0x7] );
663 62403160 : wu_transpose_8x8( m[0x8], m[0x9], m[0xa], m[0xb], m[0xc], m[0xd], m[0xe], m[0xf],
664 62403160 : m[0x8], m[0x9], m[0xa], m[0xb], m[0xc], m[0xd], m[0xe], m[0xf] );
665 :
666 62403160 : wu_t v[16] = {
667 62403160 : h0, h1, h2, h3,
668 62403160 : h4, h5, h6, h7,
669 62403160 : iv0, iv1, iv2, iv3,
670 62403160 : ctr_lo, ctr_hi, sz_vec, flags_vec,
671 62403160 : };
672 :
673 62403160 : round_fn8( v, m, 0 );
674 62403160 : round_fn8( v, m, 1 );
675 62403160 : round_fn8( v, m, 2 );
676 62403160 : round_fn8( v, m, 3 );
677 62403160 : round_fn8( v, m, 4 );
678 62403160 : round_fn8( v, m, 5 );
679 62403160 : round_fn8( v, m, 6 );
680 :
681 62403160 : h0 = wu_xor( v[ 0], v[ 8] );
682 62403160 : h1 = wu_xor( v[ 1], v[ 9] );
683 62403160 : h2 = wu_xor( v[ 2], v[10] );
684 62403160 : h3 = wu_xor( v[ 3], v[11] );
685 62403160 : h4 = wu_xor( v[ 4], v[12] );
686 62403160 : h5 = wu_xor( v[ 5], v[13] );
687 62403160 : h6 = wu_xor( v[ 6], v[14] );
688 62403160 : h7 = wu_xor( v[ 7], v[15] );
689 :
690 62403160 : off = off_next;
691 62403160 : } while( off!=sz );
692 :
693 6825580 : wu_transpose_8x8( h0, h1, h2, h3, h4, h5, h6, h7,
694 6825580 : h0, h1, h2, h3, h4, h5, h6, h7 );
695 :
696 6825580 : wu_st( (uint *)( out + (0UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h0 );
697 6825580 : wu_st( (uint *)( out + (1UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h1 );
698 6825580 : wu_st( (uint *)( out + (2UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h2 );
699 6825580 : wu_st( (uint *)( out + (3UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h3 );
700 6825580 : wu_st( (uint *)( out + (4UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h4 );
701 6825580 : wu_st( (uint *)( out + (5UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h5 );
702 6825580 : wu_st( (uint *)( out + (6UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h6 );
703 6825580 : wu_st( (uint *)( out + (7UL<<FD_BLAKE3_OUTCHAIN_LG_SZ) ), h7 );
704 6825580 : }
|