LCOV - code coverage report
Current view: top level - util/bits - fd_bits_find_msb.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 66 66 100.0 %
Date: 2024-11-13 11:58:15 Functions: 44 6550 0.7 %

          Line data    Source code
       1             : /* Included by fd_bits.h */
       2             : /* DO NOT INCLUDE DIRECTLY */
       3             : 
       4         108 : FD_FN_CONST static inline int fd_uchar_find_msb ( uchar  x ) { return 31 - __builtin_clz ( (uint)x ); }
       5         408 : FD_FN_CONST static inline int fd_ushort_find_msb( ushort x ) { return 31 - __builtin_clz ( (uint)x ); }
       6 18446064069 : FD_FN_CONST static inline int fd_uint_find_msb  ( uint   x ) { return 31 - __builtin_clz (       x ); }
       7 27090132995 : FD_FN_CONST static inline int fd_ulong_find_msb ( ulong  x ) { return 63 - __builtin_clzl(       x ); }
       8             : 
       9             : #if FD_HAS_INT128
      10             : 
      11             : #if FD_HAS_X86
      12             : 
      13             : FD_FN_CONST static inline int
      14       24768 : fd_uint128_find_msb( uint128 x ) {
      15       24768 :   ulong xl = (ulong) x;
      16       24768 :   ulong xh = (ulong)(x>>64);
      17       24768 :   int   _0 = 0;
      18       24768 :   int   c  = 64;
      19       24768 :   __asm__( "testq %1, %1   # cc.zf = !xh;\n\t"
      20       24768 :            "cmovz %3, %0   # if( !xh ) c = 0;\n\t"
      21       24768 :            "cmovz %2, %1   # if( !xh ) xh = xl;"
      22       24768 :          : "+&r" (c), "+&r" (xh) : "r" (xl), "r" (_0) : "cc" );
      23       24768 :   return c + fd_ulong_find_msb( xh );
      24       24768 : }
      25             : 
      26             : #else /* other architectures */
      27             : 
      28             : FD_FN_CONST static inline int
      29             : fd_uint128_find_msb( uint128 x ) {
      30             :   ulong xl = (ulong) x;
      31             :   ulong xh = (ulong)(x>>64);
      32             :   int   c  = !xh;
      33             :   return (127-((c)<<6)) - __builtin_clzl( fd_ulong_if( c, xl, xh ) );
      34             : }
      35             : 
      36             : #endif
      37             : 
      38             : #endif
      39             : 
      40             : /* find_msb_w_default */
      41             : 
      42             : #if FD_HAS_X86
      43             : 
      44             : /* find_msb_w_default has been optimized for both lzcnt and bsr.  Note
      45             :    that in older Intel architectures (before Skylake) lzcnt has a false
      46             :    dependency on the destination register (this is true for bsr, but
      47             :    should not be the case for lzcnt).  Instead of using the typical xor
      48             :    operation on the output register (to break the dependency), the code
      49             :    below reuses the input register to that end, without affecting the
      50             :    performance on newer architectures. */
      51             : 
      52             : FD_FN_CONST static inline int
      53             : fd_uchar_find_msb_w_default( uchar x,
      54         111 :                              int   d ) {
      55         111 :   union { int i; uint u; } r, c;
      56         111 : # if __LZCNT__
      57         111 :   c.i = 31-d;
      58         111 :   r.u = (uint)x;
      59         111 :   __asm__( " lzcnt %0, %0 # cc.cf = !x;\n\t"
      60         111 :            " cmovb %1, %0 # move if cf is set;"
      61         111 :            : "+&r" (r.u) : "r" (c.u) : "cc" );
      62         111 :   return 31 - r.i;
      63             : # else
      64             :   c.i = d;
      65             :   r.u = (uint)x;
      66             :   __asm__( " bsr   %0, %0 # cc.zf = !x;\n\t"
      67             :            " cmovz %1, %0 # move if zf is set;"
      68             :            : "+&r" (r.u) : "r" (c.u) : "cc" );
      69             :   return r.i;
      70             : # endif
      71         111 : }
      72             : 
      73             : FD_FN_CONST static inline int
      74             : fd_ushort_find_msb_w_default( ushort x,
      75         411 :                               int    d ) {
      76         411 :   union { int i; uint u; } r, c;
      77         411 : # if __LZCNT__
      78         411 :   c.i = 31-d;
      79         411 :   r.u = (uint)x;
      80         411 :   __asm__( " lzcnt %0, %0 # cc.cf = !x;\n\t"
      81         411 :            " cmovb %1, %0 # move if cf is set;"
      82         411 :            : "+&r" (r.u) : "r" (c.u) : "cc" );
      83         411 :   return 31 - r.i;
      84             : # else
      85             :   c.i = d;
      86             :   r.u = (uint)x;
      87             :   __asm__( " bsr   %0, %0 # cc.zf = !x;\n\t"
      88             :            " cmovz %1, %0 # move if zf is set;"
      89             :            : "+&r" (r.u) : "r" (c.u) : "cc" );
      90             :   return r.i;
      91             : # endif
      92         411 : }
      93             : 
      94             : FD_FN_CONST static inline int
      95             : fd_uint_find_msb_w_default( uint x,
      96        1587 :                             int  d ) {
      97        1587 :   union { int i; uint u; } r, c;
      98        1587 : # if __LZCNT__
      99        1587 :   c.i = 31-d;
     100        1587 :   r.u = x;
     101        1587 :   __asm__( " lzcnt %0, %0 # cc.cf = !x;\n\t"
     102        1587 :            " cmovb %1, %0 # move if cf is set;"
     103        1587 :            : "+&r" (r.u) : "r" (c.u) : "cc" );
     104        1587 :   return 31 - r.i;
     105             : # else
     106             :   c.i = d;
     107             :   r.u = x;
     108             :   __asm__( " bsr   %0, %0 # cc.zf = !x;\n\t"
     109             :            " cmovz %1, %0 # move if zf is set;"
     110             :            : "+&r" (r.u) : "r" (c.u) : "cc" );
     111             :   return r.i;
     112             : # endif
     113        1587 : }
     114             : 
     115             : FD_FN_CONST static inline int
     116             : fd_ulong_find_msb_w_default( ulong x,
     117    84385308 :                              int   d ) {
     118    84385308 :   union { long l; ulong u; } r, c;
     119    84385308 : # if __LZCNT__
     120    84385308 :   c.l = (long)(63L-d);
     121    84385308 :   r.u = x;
     122    84385308 :   __asm__( " lzcnt %0, %0 # cc.cf = !x;\n\t"
     123    84385308 :            " cmovb %1, %0 # move if cf is set;"
     124    84385308 :            : "+&r" (r.u) : "r" (c.u) : "cc" );
     125    84385308 :   return (int) (63L - r.l);
     126             : # else
     127             :   c.l = (long)d;
     128             :   r.u = x;
     129             :   __asm__( " bsr   %0, %0 # cc.zf = !x;\n\t"
     130             :            " cmovz %1, %0 # move if zf is set;"
     131             :            : "+&r" (r.u) : "r" (c.u) : "cc" );
     132             :   return (int)r.l;
     133             : # endif
     134    84385308 : }
     135             : 
     136             : #else /* other architectures */
     137             : 
     138             : FD_FN_CONST static inline int fd_uchar_find_msb_w_default ( uchar  x, int d ) { return (!x) ? d : fd_uchar_find_msb  ( x ); }
     139             : FD_FN_CONST static inline int fd_ushort_find_msb_w_default( ushort x, int d ) { return (!x) ? d : fd_ushort_find_msb ( x ); }
     140             : FD_FN_CONST static inline int fd_uint_find_msb_w_default  ( uint   x, int d ) { return (!x) ? d : fd_uint_find_msb   ( x ); }
     141             : FD_FN_CONST static inline int fd_ulong_find_msb_w_default ( ulong  x, int d ) { return (!x) ? d : fd_ulong_find_msb  ( x ); }
     142             : 
     143             : #endif
     144             : 
     145             : #if FD_HAS_INT128
     146             : 
     147             : #if FD_HAS_X86
     148             : 
     149             : FD_FN_CONST static inline int
     150             : fd_uint128_find_msb_w_default( uint128 x,
     151       24771 :                                int     d ) {
     152       24771 :   ulong xl = (ulong) x;
     153       24771 :   ulong xh = (ulong)(x>>64);
     154       24771 :   int   c  = 64;
     155       24771 :   int   _0 = 0;
     156       24771 :   __asm__( "testq %2, %2   # cc.zf = !xh;\n\t"
     157       24771 :            "cmovz %3, %0   # if( !xh ) c = 0;\n\t"
     158       24771 :            "cmovnz %2, %1  # if(!!xh ) xl = xh;"
     159       24771 :            : "+&r" (c), "+&r" (xl) : "r" (xh), "r" (_0) : "cc" );
     160       24771 :   return c + fd_ulong_find_msb_w_default( xl, d );
     161       24771 : }
     162             : 
     163             : #else /* other architectures */
     164             : 
     165             : FD_FN_CONST static inline int fd_uint128_find_msb_w_default( uint128 x, int d ) { return (!x) ? d : fd_uint128_find_msb( x ); }
     166             : 
     167             : #endif
     168             : 
     169             : #endif
     170             : 

Generated by: LCOV version 1.14