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;