https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126035
Bug ID: 126035
Summary: Missed CTZ32 to CTZ64 optimisations
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ktkachov at gcc dot gnu.org
Target Milestone: ---
Maybe there already duplicates of this but this testcase:
#include <stdint.h>
static inline unsigned ctz32 (uint32_t v) { return (unsigned) __builtin_ctz
(v); }
unsigned ctz64_split (uint64_t val)
{
uint32_t hi = (uint32_t) (val >> 32);
uint32_t lo = (uint32_t) val;
return lo ? ctz32 (lo) : 32u + ctz32 (hi);
}
const unsigned char *match_extend (const unsigned char *p, uint64_t x)
{
return p + (ctz64_split (x) >> 3);
}
with aarch64 clang at -O3 generates:
ctz64_split(unsigned long):
rbit x8, x0
clz x0, x8
ret
match_extend(unsigned char const*, unsigned long):
rbit x8, x1
clz x8, x8
add x0, x0, x8, lsr #3
ret
but with GCC it's:
ctz64_split(unsigned long):
cmp w0, 0
rbit w1, w0
clz w1, w1
lsr x0, x0, 32
rbit w0, w0
clz w0, w0
add w0, w0, 32
csel w0, w0, w1, eq
ret
match_extend(unsigned char const*, unsigned long):
cmp w1, 0
rbit w2, w1
clz w2, w2
lsr x1, x1, 32
rbit w1, w1
clz w1, w1
add w1, w1, 32
csel w1, w1, w2, eq
ubfx x1, x1, 3, 4
add x0, x0, x1
ret
apparently this appears in the zstd benchmark in SPEC2026