https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127172

            Bug ID: 127172
           Summary: Failed to recognize 64-bit CTZ from 2 32-bit CTZ
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: liuhongt at gcc dot gnu.org
  Target Milestone: ---

typedef unsigned int       U32;
typedef unsigned long long U64;

static unsigned ctz32_debruijn(U32 val)  
{
    static const U32 D[32] = {
        0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
        31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
    };
    return D[((U32)((val & ((~val) + 1)) * 0x077CB531U)) >> 27];
}

unsigned ctz64(U64 val)
{
    U32 hi = (U32)(val >> 32);
    U32 lo = (U32)val;
    if (lo == 0)
        return 32 + ctz32_debruijn(hi);
    else
        return ctz32_debruijn(lo);
}


Currently, we recognize ctz64 as 2 32-bit ctz + condition move, but it should
be simple 64-bit ctz

  <bb 2> [local count: 1073741824]:
  # DEBUG BEGIN_STMT
  # DEBUG D#2 => val_3(D) >> 32
  # DEBUG D#1 => (U32) D#2
  # DEBUG hi => D#1
  # DEBUG BEGIN_STMT
  lo_5 = (U32) val_3(D);
  # DEBUG lo => lo_5
  # DEBUG BEGIN_STMT
  if (lo_5 == 0)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 3> [local count: 536870912]:
  _1 = val_3(D) >> 32;
  hi_4 = (U32) _1;
  # DEBUG BEGIN_STMT
  # DEBUG val => D#1
  # DEBUG INLINE_ENTRY ctz32_debruijn
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  _7 = .CTZ (hi_4, 32);
  _8 = _7 & 31;
  _10 = (unsigned int) _8;
  # DEBUG val => NULL
  _9 = _10 + 32;
  goto <bb 5>; [100.00%]

  <bb 4> [local count: 536870912]:
  # DEBUG BEGIN_STMT
  # DEBUG val => lo_5
  # DEBUG INLINE_ENTRY ctz32_debruijn
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  _11 = .CTZ (lo_5, 32); [tail call]
  _12 = (unsigned int) _11;
  # DEBUG val => NULL

  <bb 5> [local count: 1073741824]:
  # _2 = PHI <_9(3), _12(4)>
  return _2;

Reply via email to