On 14/03/2024 12:03 pm, Andreas Schwab wrote: > On Mär 14 2024, Andrew Cooper via Gcc wrote: > >> so any known-constant value can be folded. What I'm dealing with is the >> remainder of the cases. > Which cases remain?
None, thanks to the answers on this thread. The overall structure I've got now is: unsigned int ffs(unsigned int x) { if ( __builtin_constant_p(x) ) return __builtin_ffs(x); // Allows constant folding #ifndef arch_ffs #define arch_ffs __builtin_ffs #endif return arch_ffs(x); } And for x86's arch_ffs(), unsigned int arch_ffs(unsigned int x) { unsigned int res; if ( __builtin_constant_p(x > 0) && x > 0 ) { // Well defined when x is known non-zero asm("bsf %1, %0" : "=r"(res) : "rm"(x)); } else { // The architects say this is safe even for 0. res = -1; asm("bsf %1, %0" : "+r"(res) : "rm"(x)); } return res + 1; } This gives the same code gen as before (give or take some register shuffling), without having to rely on the programmer to remember to get their ffs()'s separated from their __ffs()'s as it pertains to undefined input. The other architectures which have better-defined instructions don't need any of these games to retain the same good code-gen that is currently expressed with a maze of subtly-different functions. ~Andrew