https://gcc.gnu.org/g:3d381dc818f09fb4e36fe842090fba9306865569

commit 3d381dc818f09fb4e36fe842090fba9306865569
Author: Daniel Barboza <[email protected]>
Date:   Wed Jan 7 07:17:26 2026 -0700

    [PATCH v3] match.pd: popcount(X & -X) -> -X != 0 [PR102486]
    
    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 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.
    
    Signed-off-by: Daniel Barboza <[email protected]>
    (cherry picked from commit f26f5e3a4c42e50a34cb2d3e5f02a70a8faa596f)

Diff:
---
 gcc/match.pd                             | 14 ++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr102486.c | 14 ++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index f3f93c993dca..c1998752365d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -10083,6 +10083,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 000000000000..aa454d91fae0
--- /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" } } */

Reply via email to