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" } } */
