[range-op] Take known set bits into account in popcount [PR107053]

This patch teaches popcount about known set bits which are now
available in the irange.

	PR tree-optimization/107053

gcc/ChangeLog:

	* gimple-range-op.cc (cfn_popcount): Use known set bits.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/pr107053.c: New test.
This commit is contained in:
Aldy Hernandez 2023-06-30 20:40:02 +02:00
parent d6384ad1a9
commit 137fb7077f
2 changed files with 20 additions and 4 deletions

View file

@ -880,17 +880,20 @@ public:
if (lh.undefined_p ())
return false;
unsigned prec = TYPE_PRECISION (type);
wide_int nz = lh.get_nonzero_bits ();
wide_int pop = wi::shwi (wi::popcount (nz), prec);
irange_bitmask bm = lh.get_bitmask ();
wide_int nz = bm.get_nonzero_bits ();
wide_int high = wi::shwi (wi::popcount (nz), prec);
// Calculating the popcount of a singleton is trivial.
if (lh.singleton_p ())
{
r.set (type, pop, pop);
r.set (type, high, high);
return true;
}
if (cfn_ffs::fold_range (r, type, lh, rh, rel))
{
int_range<2> tmp (type, wi::zero (prec), pop);
wide_int known_ones = ~bm.mask () & bm.value ();
wide_int low = wi::shwi (wi::popcount (known_ones), prec);
int_range<2> tmp (type, low, high);
r.intersect (tmp);
return true;
}

View file

@ -0,0 +1,13 @@
// { dg-do compile }
// { dg-options "-O2 -fdump-tree-evrp" }
void link_failure();
void f(int a)
{
a |= 0x300;
int b = __builtin_popcount(a);
if (b < 2)
link_failure();
}
// { dg-final { scan-tree-dump-not "link_failure" "evrp" } }