Re: [PATCH v3 00/16] Introduce and use generic parity16/32/64 helper
From: H. Peter Anvin
Date: Tue Mar 25 2025 - 15:48:05 EST
On 3/23/25 08:16, Kuan-Wei Chiu wrote:
Interface 3: Multiple Functions
Description: bool parity_odd8/16/32/64()
Pros: No need for explicit casting; easy to integrate
architecture-specific optimizations; except for parity8(), all
functions are one-liners with no significant code duplication
Cons: More functions may increase maintenance burden
Opinions: Only I support this approach
OK, so I responded to this but I can't find my reply or any of the
followups, so let me go again:
I prefer this option, because:
a. Virtually all uses of parity is done in contexts where the sizes of
the items for which parity is to be taken are well-defined, but it is
*really* easy for integer promotion to cause a value to be extended to
32 bits unnecessarily (sign or zero extend, although for parity it
doesn't make any difference -- if the compiler realizes it.)
b. It makes it easier to add arch-specific implementations, notably
using __builtin_parity on architectures where that is known to generate
good code.
c. For architectures where only *some* parity implementations are
fast/practical, the generic fallbacks will either naturally synthesize
them from components via shift-xor, or they can be defined to use a
larger version; the function prototype acts like a cast.
d. If there is a reason in the future to add a generic version, it is
really easy to do using the size-specific functions as components; this
is something we do literally all over the place, using a pattern so
common that it, itself, probably should be macroized:
#define parity(x) \
({ \
typeof(x) __x = (x); \
bool __y; \
switch (sizeof(__x)) { \
case 1: \
__y = parity8(__x); \
break; \
case 2: \
__y = parity16(__x); \
break; \
case 4: \
__y = parity32(__x); \
break; \
case 8: \
__y = parity64(__x); \
break; \
default: \
BUILD_BUG(); \
break; \
} \
__y; \
})