On Mon, Dec 29, 2025 at 12:14 PM Daniel Barboza
<[email protected]> wrote:
>
> PR 102486
>
> gcc/ChangeLog:
>
> * match.pd (`popcount (X & -X) -> (X & -X) != 0`): New pattern.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr102486.c: New test.
>
> Signed-off-by: Daniel Barboza <[email protected]>
> ---
> gcc/match.pd | 8 ++++++++
> gcc/testsuite/gcc.dg/torture/pr102486.c | 15 +++++++++++++++
> 2 files changed, 23 insertions(+)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr102486.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 45d96844673..6b01aaea9b6 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -10541,6 +10541,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (popcount:s @1))
> (popcount (log2 @0 @1)))))
>
> +/* popcount (X & -X) is (X & -X) != 0. */
> +(simplify
> + (POPCOUNT (convert?@1 (bit_and:c @0 (negate @0))))
> + /* Use an explicit bool conversion to avoid errors when the
> + POPCOUNT result is assigned to a type (e.g. int) that
> + will generate a "bogus comparison result type" error. */
> + (convert:boolean_type_node (ne @1 { build_zero_cst (TREE_TYPE (@1)); })))
Thinking about this pattern there is one problem with the optional
convert. If it is a sign extending convert we could go from one bit to
multiple if the bit that was set was the sign bit.
So you need a check for @0 being unsigned or a truncating convert.
Also the pattern result should be:
(convert:type (ne:boolean_type_node @1 { build_zero_cst (TREE_TYPE (@1)); })))
I had messed it up beforehand :).
that is the ne should be of type boolean_type_node and the converted into type.
Thanks,
Andrew
> +
> #if GIMPLE
> /* popcount(zext(X)) == popcount(X). */
> (simplify
> diff --git a/gcc/testsuite/gcc.dg/torture/pr102486.c
> b/gcc/testsuite/gcc.dg/torture/pr102486.c
> new file mode 100644
> index 00000000000..d900149e011
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr102486.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fdump-tree-optimized" } */
> +/* { dg-skip-if "" { *-*-* } { "-O0" "-fno-fat-lto-objects" } { "" } } */
> +
> +int f (unsigned y)
> +{
> + return __builtin_popcount (y & -y);
> +}
> +
> +int f2 (int y)
> +{
> + return __builtin_popcount (y & -y);
> +}
> +
> +/* { dg-final { scan-tree-dump-times "popcount" 0 "optimized" } } */
> --
> 2.43.0
>