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

Reply via email to