On 14/03/2024 6:04 am, Alexander Monakov wrote: > On Thu, 14 Mar 2024, Andrew Cooper via Gcc wrote: > >> I suppose that what I'm looking for is something a little like >> __builtin_constant_p() which can either be used in a straight if(), or >> in a __builtin_choose_expr(). >> >> Anyway - is there a way of doing this that I've managed to overlook? > I am missing what is lacking for you with __builtin_constant_p, I would > do it like this: > > unsigned ffs(unsigned x) > { > unsigned res; > unsigned nonzero = x != 0; > if (__builtin_constant_p(nonzero) && nonzero) > asm("bsf %1, %0" : "=r"(res) : "rm"(x)); > else { > res = -1; > asm("bsf %1, %0" : "+r"(res) : "rm"(x)); > } > return res; > }
Oh - so it does. I'd not considered that expressing it like that would still work. > > or with handling known-zero-input case like this: > > unsigned ffs(unsigned x) > { > unsigned res; > unsigned nonzero = x != 0; > if (!__builtin_constant_p(nonzero)) { > res = -1; > asm("bsf %1, %0" : "+r"(res) : "rm"(x)); > } else if (nonzero) { > asm("bsf %1, %0" : "=r"(res) : "rm"(x)); > } else { > res = -1; > } > return res; > } > > > Does it work for you? I simplified things when asking the question. The real implementation has a general if (__builtin_constant_p(x)) return __builtin_ffs(x); so any known-constant value can be folded. What I'm dealing with is the remainder of the cases. Anyway - thankyou for your help. ~Andrew