LCOV - code coverage report
Current view: top level - util - fd_hash.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 181 193 93.8 %
Date: 2026-09-17 04:28:31 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "fd_util_base.h"
       2             : #include "bits/fd_bits.h"
       3             : 
       4             : /* A cleaner implementation of xxhash-r39 (Open Source BSD licensed). */
       5             : #if FD_HAS_AVX512 && defined(__AVX512DQ__) && defined(__AVX512VL__)
       6             : #include "simd/fd_avx.h"
       7             : #endif
       8             : 
       9  5954502841 : #define ROTATE_LEFT(x,r) (((x)<<(r)) | ((x)>>(64-(r))))
      10  6759955183 : #define C1 (11400714785074694791UL)
      11  5727347137 : #define C2 (14029467366897019727UL)
      12   325037883 : #define C3 ( 1609587929392839161UL)
      13  1273741980 : #define C4 ( 9650029242287828579UL)
      14    64241217 : #define C5 ( 2870177450012600261UL)
      15             : 
      16             : static inline FD_FN_UNUSED FD_FN_PURE ulong
      17             : fd_hash_generic( ulong        seed,
      18             :                  void const * buf,
      19   200715590 :                  ulong        sz ) {
      20   200715590 :   uchar const * p    = ((uchar const *)buf);
      21   200715590 :   uchar const * stop = p + sz;
      22           0 : 
      23   200715590 :   ulong h;
      24           0 : 
      25   200715590 :   if( sz<32 ) h = seed + C5;
      26   199909086 :   else {
      27   199909086 :     uchar const * stop32 = stop - 32;
      28   199909086 :     ulong w = seed + (C1+C2);
      29   199909086 :     ulong x = seed + C2;
      30   199909086 :     ulong y = seed;
      31   199909086 :     ulong z = seed - C1;
      32           0 : 
      33   968139184 :     do { /* All complete blocks of 32 */
      34   968139184 :       w += FD_LOAD( ulong, p    )*C2; w = ROTATE_LEFT( w, 31 ); w *= C1;
      35   968139184 :       x += FD_LOAD( ulong, p+ 8 )*C2; x = ROTATE_LEFT( x, 31 ); x *= C1;
      36   968139184 :       y += FD_LOAD( ulong, p+16 )*C2; y = ROTATE_LEFT( y, 31 ); y *= C1;
      37   968139184 :       z += FD_LOAD( ulong, p+24 )*C2; z = ROTATE_LEFT( z, 31 ); z *= C1;
      38   968139184 :       p += 32;
      39   968139184 :     } while( p<=stop32 );
      40           0 : 
      41   199909086 :     h = ROTATE_LEFT( w, 1 ) + ROTATE_LEFT( x, 7 ) + ROTATE_LEFT( y, 12 ) + ROTATE_LEFT( z, 18 );
      42           0 : 
      43   199909086 :     w *= C2; w = ROTATE_LEFT( w, 31 ); w *= C1; h ^= w; h = h*C1 + C4;
      44   199909086 :     x *= C2; x = ROTATE_LEFT( x, 31 ); x *= C1; h ^= x; h = h*C1 + C4;
      45   199909086 :     y *= C2; y = ROTATE_LEFT( y, 31 ); y *= C1; h ^= y; h = h*C1 + C4;
      46   199909086 :     z *= C2; z = ROTATE_LEFT( z, 31 ); z *= C1; h ^= z; h = h*C1 + C4;
      47   199909086 :   }
      48           0 : 
      49   200715590 :   h += ((ulong)sz);
      50           0 : 
      51   239503576 :   while( (p+8)<=stop ) { /* Last 1 to 3 complete ulong's */
      52    38787986 :     ulong w = FD_LOAD( ulong, p );
      53    38787986 :     w *= C2; w = ROTATE_LEFT( w, 31 ); w *= C1; h ^= w; h = ROTATE_LEFT( h, 27 )*C1 + C4;
      54    38787986 :     p += 8;
      55    38787986 :   }
      56           0 : 
      57   200715590 :   if( (p+4)<=stop ) { /* Last complete uint */
      58    12977108 :     ulong w = ((ulong)FD_LOAD( uint, p ));
      59    12977108 :     w *= C1; h ^= w; h = ROTATE_LEFT( h, 23 )*C2 + C3;
      60    12977108 :     p += 4;
      61    12977108 :   }
      62           0 : 
      63   239677394 :   while( p<stop ) { /* Last 1 to 3 uchar's */
      64    38961804 :     ulong w = ((ulong)(p[0]));
      65    38961804 :     w *= C5; h ^= w; h = ROTATE_LEFT( h, 11 )*C1;
      66    38961804 :     p++;
      67    38961804 :   }
      68           0 : 
      69           0 :   /* Final avalanche */
      70   200715590 :   h ^= h >> 33;
      71   200715590 :   h *= C2;
      72   200715590 :   h ^= h >> 29;
      73   200715590 :   h *= C3;
      74   200715590 :   h ^= h >> 32;
      75           0 : 
      76   200715590 :   return h;
      77   200715590 : }
      78             : 
      79             : #if FD_HAS_AVX512 && defined(__AVX512DQ__) && defined(__AVX512VL__)
      80             : static inline FD_FN_UNUSED FD_FN_PURE ulong
      81             : fd_hash_avx512dq( ulong        seed,
      82             :                   void const * buf,
      83   100357798 :                   ulong        sz ) {
      84   100357798 :   uchar const * p    = ((uchar const *)buf);
      85   100357798 :   uchar const * stop = p + sz;
      86   100357798 :   ulong h;
      87             : 
      88   100357798 :   if( sz<32 ) h = seed + C5;
      89    99954546 :   else {
      90    99954546 :     uchar const * stop32 = stop - 32;
      91    99954546 :     ulong w, x, y, z;
      92    99954546 :     wv_t state_vec = wv_add( wv_bcast( seed ), wv( C1 + C2, C2, 0UL, 0UL - C1 ) );
      93    99954546 :     wv_t c1_vec = wv_bcast( C1 );
      94    99954546 :     wv_t c2_vec = wv_bcast( C2 );
      95   484069750 :     do { /* All complete blocks of 32 */
      96   484069750 :       wv_t input_vec = wv_ldu( p );
      97   484069750 :       input_vec = wv_mul( input_vec, c2_vec );
      98   484069750 :       state_vec = wv_add( state_vec, input_vec );
      99   484069750 :       state_vec = wv_rol( state_vec, 31 );
     100   484069750 :       state_vec = wv_mul( state_vec, c1_vec );
     101   484069750 :       p += 32;
     102   484069750 :     } while( p<=stop32 );
     103    99954546 :     wv_t h_vec = wv_rol_vector( state_vec, wv( 1UL, 7UL, 12UL, 18UL ) );
     104    99954546 :     h = wv_extract( h_vec, 0 )
     105    99954546 :       + wv_extract( h_vec, 1 )
     106    99954546 :       + wv_extract( h_vec, 2 )
     107    99954546 :       + wv_extract( h_vec, 3 );
     108    99954546 :     state_vec = wv_mul( state_vec, c2_vec );
     109    99954546 :     state_vec = wv_rol( state_vec, 31 );
     110    99954546 :     state_vec = wv_mul( state_vec, c1_vec );
     111    99954546 :     w = wv_extract( state_vec, 0 );
     112    99954546 :     x = wv_extract( state_vec, 1 );
     113    99954546 :     y = wv_extract( state_vec, 2 );
     114    99954546 :     z = wv_extract( state_vec, 3 );
     115    99954546 :     h ^= w; h = h*C1 + C4;
     116    99954546 :     h ^= x; h = h*C1 + C4;
     117    99954546 :     h ^= y; h = h*C1 + C4;
     118    99954546 :     h ^= z; h = h*C1 + C4;
     119    99954546 :   }
     120             : 
     121   100357798 :   h += sz;
     122             : 
     123   119751791 :   while( (p+8)<=stop ) { /* Last 1 to 3 complete ulong's */
     124    19393993 :     ulong w = FD_LOAD( ulong, p );
     125    19393993 :     w *= C2; w = ROTATE_LEFT( w, 31 ); w *= C1; h ^= w; h = ROTATE_LEFT( h, 27 )*C1 + C4;
     126    19393993 :     p += 8;
     127    19393993 :   }
     128             : 
     129   100357798 :   if( (p+4)<=stop ) { /* Last complete uint */
     130     6488554 :     ulong w = ((ulong)FD_LOAD( uint, p ));
     131     6488554 :     w *= C1; h ^= w; h = ROTATE_LEFT( h, 23 )*C2 + C3;
     132     6488554 :     p += 4;
     133     6488554 :   }
     134             : 
     135   119838700 :   while( p<stop ) { /* Last 1 to 3 uchar's */
     136    19480902 :     ulong w = ((ulong)(p[0]));
     137    19480902 :     w *= C5; h ^= w; h = ROTATE_LEFT( h, 11 )*C1;
     138    19480902 :     p++;
     139    19480902 :   }
     140             : 
     141             :   /* Final avalanche */
     142   100357798 :   h ^= h >> 33;
     143   100357798 :   h *= C2;
     144   100357798 :   h ^= h >> 29;
     145   100357798 :   h *= C3;
     146   100357798 :   h ^= h >> 32;
     147             : 
     148   100357798 :   return h;
     149   100357798 : }
     150             : #endif
     151             : 
     152             : ulong
     153             : fd_hash( ulong        seed,
     154             :          void const * buf,
     155   301073388 :          ulong        sz ) {
     156   100357798 : #if FD_HAS_AVX512 && defined(__AVX512DQ__) && defined(__AVX512VL__)
     157   100357798 :   return fd_hash_avx512dq( seed, buf, sz );
     158             : #else
     159   200715590 :   return fd_hash_generic( seed, buf, sz );
     160   200715590 : #endif
     161   301073388 : }
     162             : 
     163             : ulong
     164             : fd_hash_memcpy( ulong                    seed,
     165             :                 void *       FD_RESTRICT dst,
     166             :                 void const * FD_RESTRICT src,
     167     3000000 :                 ulong                    sz ) {
     168     3000000 :   uchar       * FD_RESTRICT q    = ((uchar       *)dst);
     169     3000000 :   uchar const * FD_RESTRICT p    = ((uchar const *)src);
     170     3000000 :   uchar const * FD_RESTRICT stop = p + sz;
     171             : 
     172     3000000 :   ulong h;
     173             : 
     174     3000000 :   if( sz<32 ) h = seed + C5;
     175     2907993 :   else {
     176     2907993 :     uchar const * FD_RESTRICT stop32 = stop - 32;
     177     2907993 :     ulong w = seed + (C1+C2);
     178     2907993 :     ulong x = seed + C2;
     179     2907993 :     ulong y = seed;
     180     2907993 :     ulong z = seed - C1;
     181             : 
     182    62548641 :     do { /* All complete blocks of 32 */
     183    62548641 :       ulong p0 = FD_LOAD( ulong, p    );
     184    62548641 :       ulong p1 = FD_LOAD( ulong, p+ 8 );
     185    62548641 :       ulong p2 = FD_LOAD( ulong, p+16 );
     186    62548641 :       ulong p3 = FD_LOAD( ulong, p+24 );
     187    62548641 :       w += p0*C2; w = ROTATE_LEFT( w, 31 ); w *= C1;
     188    62548641 :       x += p1*C2; x = ROTATE_LEFT( x, 31 ); x *= C1;
     189    62548641 :       y += p2*C2; y = ROTATE_LEFT( y, 31 ); y *= C1;
     190    62548641 :       z += p3*C2; z = ROTATE_LEFT( z, 31 ); z *= C1;
     191    62548641 :       FD_STORE( ulong, q,    p0 );
     192    62548641 :       FD_STORE( ulong, q+ 8, p1 );
     193    62548641 :       FD_STORE( ulong, q+16, p2 );
     194    62548641 :       FD_STORE( ulong, q+24, p3 );
     195    62548641 :       p += 32;
     196    62548641 :       q += 32;
     197    62548641 :     } while( p<=stop32 );
     198             : 
     199     2907993 :     h = ROTATE_LEFT( w, 1 ) + ROTATE_LEFT( x, 7 ) + ROTATE_LEFT( y, 12 ) + ROTATE_LEFT( z, 18 );
     200             : 
     201     2907993 :     w *= C2; w = ROTATE_LEFT( w, 31 ); w *= C1; h ^= w; h = h*C1 + C4;
     202     2907993 :     x *= C2; x = ROTATE_LEFT( x, 31 ); x *= C1; h ^= x; h = h*C1 + C4;
     203     2907993 :     y *= C2; y = ROTATE_LEFT( y, 31 ); y *= C1; h ^= y; h = h*C1 + C4;
     204     2907993 :     z *= C2; z = ROTATE_LEFT( z, 31 ); z *= C1; h ^= z; h = h*C1 + C4;
     205     2907993 :   }
     206             : 
     207     3000000 :   h += ((ulong)sz);
     208             : 
     209     7473501 :   while( (p+8)<=stop ) { /* Last 1 to 3 complete ulong's */
     210     4473501 :     ulong p0 = FD_LOAD( ulong, p );
     211     4473501 :     ulong w  = p0*C2; w = ROTATE_LEFT( w, 31 ); w *= C1; h ^= w; h = ROTATE_LEFT( h, 27 )*C1 + C4;
     212     4473501 :     FD_STORE( ulong, q, p0 );
     213     4473501 :     p += 8;
     214     4473501 :     q += 8;
     215     4473501 :   }
     216             : 
     217     3000000 :   if( (p+4)<=stop ) { /* Last complete uint */
     218     1498833 :     uint p0 = FD_LOAD( uint, p );
     219     1498833 :     ulong w = ((ulong)p0)*C1; h ^= w; h = ROTATE_LEFT( h, 23 )*C2 + C3;
     220     1498833 :     FD_STORE( uint, q, p0 );
     221     1498833 :     p += 4;
     222     1498833 :     q += 4;
     223     1498833 :   }
     224             : 
     225     7496748 :   while( p<stop ) { /* Last 1 to 3 uchar's */
     226     4496748 :     uchar p0 = p[0];
     227     4496748 :     ulong w  = ((ulong)p0)*C5; h ^= w; h = ROTATE_LEFT( h, 11 )*C1;
     228     4496748 :     q[0] = p0;
     229     4496748 :     p++;
     230     4496748 :     q++;
     231     4496748 :   }
     232             : 
     233             :   /* Final avalanche */
     234     3000000 :   h ^= h >> 33;
     235     3000000 :   h *= C2;
     236     3000000 :   h ^= h >> 29;
     237     3000000 :   h *= C3;
     238     3000000 :   h ^= h >> 32;
     239             : 
     240     3000000 :   return h;
     241     3000000 : }
     242             : 
     243             : #undef C5
     244             : #undef C4
     245             : #undef C3
     246             : #undef C2
     247             : #undef C1
     248             : #undef ROTATE_LEFT

Generated by: LCOV version 1.14