On Mon, Jan 5, 2026 at 2:23 PM Daniel Barboza
<[email protected]> wrote:
>
> The initial idea of this optimization was to reduce it to "X != 0",
> checking for either X being an unsigned or a truncating conversion.
> Then we discussed reducing it to "(X & -X) != 0" instead. This form
> would avoid the potential trapping problems (like -ftrapv) that might
> happen in case X is not an unsigned type.
>
> Then, as suggested by Roger Sayle in bugzilla, we could reduce to just
> "-X != 0". Keeping the negated value in the pattern preserves any trapping
> or UBs to be handled by other match.pd patterns that are more able to do
> the conversion to "X != 0" when applicable. This would also spare us from
> a TYPE_UNSIGNED check.
>
>         PR 102486
PR tree-optimization/102486
>
> gcc/ChangeLog:
>
>          * match.pd (`popcount (X & -X) -> -X != 0`): New pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/pr102486.c: New test.

Ok. When I get some time I will push this change.

Thanks,
Andrew

>
> Signed-off-by: Daniel Barboza <[email protected]>
> ---
>
> Changes from v2:
> - changed pattern result from "(X & -X) != 0" to "-X != 0";
> - dropped TYPE_UNSIGNED check;
> - added a brief history in the commit msg explaining where did this
>   pattern come from;
> - v2 link: https://gcc.gnu.org/pipermail/gcc-patches/2025-December/704632.html
>
>
>  gcc/match.pd                             | 14 ++++++++++++++
>  gcc/testsuite/gcc.dg/tree-ssa/pr102486.c | 14 ++++++++++++++
>  2 files changed, 28 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102486.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index ccdc1129e23..d72a3d75b86 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -10558,6 +10558,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>               (popcount:s @1))
>        (popcount (log2 @0 @1)))))
>
> +/* popcount (X & -X) is -X != 0.  */
> +(simplify
> +  (POPCOUNT (convert?@2 (bit_and:c @0 (negate@1 @0))))
> +    (with { tree type0 = TREE_TYPE (@0);
> +           tree type2 = TREE_TYPE (@2); }
> +      (if (INTEGRAL_TYPE_P (type0)
> +          && TYPE_PRECISION (type2) <= TYPE_PRECISION (type0))
> +       /* 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:type
> +         (ne:boolean_type_node
> +           (convert:type2 @1) { build_zero_cst (type2); })))))
> +
>  #if GIMPLE
>  /* popcount(zext(X)) == popcount(X).  */
>  (simplify
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102486.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr102486.c
> new file mode 100644
> index 00000000000..aa454d91fae
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102486.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized" } */
> +
> +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
>

Reply via email to