https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118342

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Uroš Bizjak from comment #7)
> (In reply to Jakub Jelinek from comment #6)
> > Yes, so we can use it for a == 0 ? prec : __builtin_ctzll (a); but not say
> > (with small middle-end enhancements) for a == 0 ? -1 : __builtin_ctzll (a);
> > because on some CPUs that would yield -1LL and on others 0xffffffffULL.
> 
> As I read the footnote from the Comment #4, the problem would be with:
> 
> long long foo (int a)
> {
>   return a ? __builtin_ctz (a) : -1ll;
> }

Sure, but right now (except for large _BitInt which is lowered before it
reaches RTL)
in GIMPLE the situation is that __builtin_ctz* calls are always UB at 0 and
.CTZ ifn calls are UB at 0 if they have just one argument and well defined at 0
if it has 2 arguments.  The second argument has to be (at least right now) in
that case equal to CTZ_DEFINED_VALUE_AT_ZERO.
As that would be prec, we wouldn't match the above into just .CTZ.

Now, at the RTL level, for SImode it could certainly be
(set (match_operand:SI 0 "register_operand "=r")
     (if_then_else:SI (match_operand:SI 1 "register_operand "r")
                      (ctz:SI (match_dup 1))
                      (match_operand:SI 2 "register_operand "0")))
(still talking about !TARGET_BMI only), but how we represent the fact that it
can clear the upper 32 bits of the destination or might not, dunno, either
unspec, or just rely on us setting the value there to prec all the time during
expansion?

Reply via email to