dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 100.0% 35 / 0 / 35
Functions: 100.0% 12 / 0 / 12
Branches: 100.0% 8 / 8 / 16

src/util/bit.h
Line Branch Exec Source
1 #ifndef UTIL_BIT_H
2 #define UTIL_BIT_H
3
4 #include <stddef.h>
5 #include <stdint.h>
6 #include "debug.h"
7 #include "macros.h"
8
9 /*
10 * The default C compiler on FreeBSD 14.1 (Clang 18.1.5) accepts the
11 * -std=gnu23 command-line option and then defines __STDC_VERSION__ as
12 * 202311L, while not actually providing a C23 conforming libc (the
13 * <stdbit.h> header is missing). This guard condition originally used
14 * `||` instead of `&&`, but it was changed so as to work around this
15 * disregard for standards. Fortunately this doesn't really have any
16 * downsides for other platforms, since __has_include() is also part
17 * of C23.
18 */
19 #if __STDC_VERSION__ >= 202311L && HAS_INCLUDE(<stdbit.h>)
20 #include <stdbit.h>
21 #define USE_STDBIT(fn, arg) return fn(arg)
22 #else
23 #define USE_STDBIT(fn, arg)
24 #endif
25
26 #ifdef HAS_BUILTIN_TYPES_COMPATIBLE_P
27 #define HAS_COMPATIBLE_BUILTIN(arg, type, fn) \
28 (GNUC_AT_LEAST(3, 4) || HAS_BUILTIN(__builtin_ ## fn)) \
29 && __builtin_types_compatible_p(__typeof__(arg), type)
30
31 // If there's an appropriate built-in function for `arg`, emit
32 // a call to it (and eliminate everything below it as dead code)
33 #define USE_BUILTIN(fn, arg) \
34 if (HAS_COMPATIBLE_BUILTIN(arg, unsigned long long, fn ## ll)) { \
35 return __builtin_ ## fn ## ll(arg); \
36 } else if (HAS_COMPATIBLE_BUILTIN(arg, unsigned long, fn ## l)) { \
37 return __builtin_ ## fn ## l(arg); \
38 } else if (HAS_COMPATIBLE_BUILTIN(arg, unsigned int, fn)) { \
39 return __builtin_ ## fn(arg); \
40 }
41 #else
42 #define USE_BUILTIN(fn, arg)
43 #endif
44
45 // Population count (cardinality) of set bits
46 212 static inline unsigned int u64_popcount(uint64_t n)
47 {
48 212 USE_STDBIT(stdc_count_ones, n);
49 USE_BUILTIN(popcount, n);
50 n -= ((n >> 1) & 0x5555555555555555ULL);
51 n = (n & 0x3333333333333333ULL) + ((n >> 2) & 0x3333333333333333ULL);
52 n = (n + (n >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
53 return (n * 0x0101010101010101ULL) >> 56;
54 }
55
56 3848 static inline unsigned int u32_popcount(uint32_t n)
57 {
58 3848 USE_STDBIT(stdc_count_ones, n);
59 USE_BUILTIN(popcount, n);
60 n -= ((n >> 1) & 0x55555555UL);
61 n = (n & 0x33333333UL) + ((n >> 2) & 0x33333333UL);
62 n = (n + (n >> 4)) & 0x0F0F0F0FUL;
63 return (n * 0x01010101UL) >> 24;
64 }
65
66 // Count trailing zeros
67 172 static inline unsigned int u32_ctz(uint32_t n)
68 {
69 172 BUG_ON(n == 0);
70 172 USE_STDBIT(stdc_trailing_zeros, n);
71 USE_BUILTIN(ctz, n);
72 return u32_popcount(~n & (n - 1));
73 }
74
75 30 static inline unsigned int umax_ctz(uintmax_t n)
76 {
77 30 BUG_ON(n == 0);
78 30 USE_STDBIT(stdc_trailing_zeros, n);
79 USE_BUILTIN(ctz, n);
80
81 unsigned int count = 0;
82 while (n) {
83 uint32_t part = (uint32_t)(n & 0xFFFFFFFFUL);
84 count += part ? u32_ctz(part) : 32;
85 n >>= 32;
86 }
87
88 return count;
89 }
90
91 // Find position of first (least significant) set bit (starting at 1)
92 12 static inline unsigned int u32_ffs(uint32_t n)
93 {
94 12 USE_BUILTIN(ffs, n);
95 return n ? u32_ctz(n) + 1 : 0;
96 }
97
98 // Extract (isolate) least significant set bit
99 83 static inline uint32_t u32_lsbit(uint32_t x)
100 {
101 83 return x & -x;
102 }
103
104 // Extract (isolate) most significant set bit (logâ‚‚ x)
105 560 static inline size_t size_msbit(size_t x)
106 {
107 560 const size_t nbits = BITSIZE(x);
108 560 size_t i = 1;
109
110 #if HAS_BUILTIN(__builtin_clzg)
111
2/2
✓ Branch 2 → 3 taken 558 times.
✓ Branch 2 → 4 taken 2 times.
560 return x ? i << ((nbits - __builtin_clzg(x)) - 1) : 0;
112 #endif
113
114 UNROLL_LOOP(8)
115 while (i < nbits) {
116 x |= x >> i;
117 i <<= 1;
118 }
119
120 return x ^ (x >> 1);
121 }
122
123 // Return the smallest power of 2 greater than or equal to `x`, or 0 if `x`
124 // is greater than the largest size_t power of 2. This is mostly the same
125 // as C23 stdc_bit_ceil(), except for the `x > max_pow2` case noted above.
126 475 static inline size_t next_pow2(size_t x)
127 {
128 475 size_t msbit = size_msbit(x);
129
4/4
✓ Branch 2 → 3 taken 474 times.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 3 → 4 taken 274 times.
✓ Branch 3 → 5 taken 200 times.
475 size_t shift = !IS_POWER_OF_2(x);
130 475 return (msbit << shift) + !x;
131 }
132
133 // Count leading zeros
134 9 static inline unsigned int u64_clz(uint64_t x)
135 {
136 9 BUG_ON(x == 0);
137 9 USE_STDBIT(stdc_leading_zeros, x);
138 USE_BUILTIN(clz, x);
139 x |= x >> 1;
140 x |= x >> 2;
141 x |= x >> 4;
142 x |= x >> 8;
143 x |= x >> 16;
144 x |= x >> 32;
145 return u64_popcount(~x);
146 }
147
148 // Round x up to a multiple of r (which *must* be a power of 2)
149 34212 static inline size_t next_multiple(size_t x, size_t r)
150 DIAGNOSE_IF(!IS_POWER_OF_2(r))
151 {
152 34212 r--;
153 34212 return (x + r) & ~r;
154 }
155
156 // Calculate the number of significant bits in `x` (the minimum number
157 // of base 2 digits needed to represent it). Note that this returns 0
158 // for x=0, but see umax_count_base16_digits() (below) for an example
159 // of how that can be special cased.
160 114 static inline unsigned int umax_bitwidth(uintmax_t x)
161 {
162
2/2
✓ Branch 2 → 3 taken 107 times.
✓ Branch 2 → 4 taken 7 times.
114 USE_STDBIT(stdc_bit_width, x);
163
164 #if HAS_BUILTIN(__builtin_stdc_bit_width)
165 return __builtin_stdc_bit_width(x);
166 #endif
167
168 if (BITSIZE(x) == 64) {
169 return x ? 64u - u64_clz(x) : 0;
170 }
171
172 unsigned int width = 0;
173 while (x) {
174 x >>= 1;
175 width++;
176 }
177 return width;
178 }
179
180 // Calculate the number of hexadecimal digits (0-F) needed to represent
181 // `x` as a string (which is 1 in the case of x=0)
182 37 static inline size_t umax_count_base16_digits(uintmax_t x)
183 {
184 37 unsigned int bit_width = umax_bitwidth(x);
185
186 // `bit_width` can only be 0 when `x` is 0, so this simply ensures
187 // 1 is returned in that case
188 37 BUG_ON(!bit_width != !x); // Improves code gen
189 37 unsigned int base2_digits = bit_width + !x;
190
191 // This is equivalent to `(base2_digits >> 2) + !!(base2_digits & 3)`,
192 // but GCC seems to generate slightly better code when done this way
193 37 return next_multiple(base2_digits, 4) / 4;
194 }
195
196 #endif
197