https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122207
Bug ID: 122207
Summary: Recognize ctz loop in 502.gcc
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: enhancement
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: rdapp at gcc dot gnu.org
CC: jeffreyalaw at gmail dot com
Target Milestone: ---
Target: riscv
This was originally found by Jeff on riscv but should be valid for other
targets as well.
In 502.gcc, gcse.c, compute_transp we have an
EXECUTE_IF_SET_IN_BITMAP
where a ctz idiom is reasonably hot. Honza replaced it with a literal
__builtin_ctzl 15 years ago in upstream GCC.
A minimal example is roughly:
typedef unsigned long BITMAP_WORD;
bool
bmp_iter_set (BITMAP_WORD bits, unsigned *bit_no)
{
/* If our current word is nonzero, it contains the bit we want. */
if (bits)
{
while (!(bits & 1))
{
bits >>= 1;
*bit_no += 1;
}
return true;
}
return false;
}
Compiled with -march=rv64gcb.
The loop-niter analysis cannot deal with that, I believe for (at least) three
reasons:
- We don't return bitno directly but true or false.
- *bit_no += 1 is a store in every iteration.
- tree-ch gets in the way.
What further complicates matters is that there is no direct "return false" but
that's embedded in the search for the next nonzero word. Ideally we should be
able to recognize ctz without it, though, as bi->bits != 0 guarantees that
there is a set bit.
For comparison, the following gets transformed into a ctz when
compiled with -march=rv64gcb -fno-tree-ch
typedef unsigned long BITMAP_WORD;
char
bmp_iter_set (BITMAP_WORD bits, unsigned *bit_no)
{
int cnt = 0;
/* If our current word is nonzero, it contains the bit we want. */
if (bits)
{
while (!(bits & 1))
{
bits >>= 1;
//*bit_no += 1;
cnt += 1;
}
return cnt;
}
return 0;
}