A particular solution is to use the 64-bit version ctzalong with the argument -march, so instead it is bsfused tzcnt, for example:
char* ptrAdd(char* ptr, uint32_t x)
{
return ptr + __builtin_ctzl(x);
}
This results in unsigned expansion:
ptrAdd(char*, unsigned int):
mov eax, esi
tzcnt rax, rax
add rax, rdi
ret
mov ( 32 64 ), xor 32- ( , tzcnt ). , mov . 64- tzcnt 32-, , undefined ( gcc, tzcnt).
, -march, tzcnt, bsf, .
, bsf tzcnt , bsf undefined . , , 0 63, . , int, "" (__builtin_clzl (x) & 0xff) == 0xdeadbeef.
gcc docs __builtin_ctzl "undefined" - , , C/++ "undefined", - ( ), " ".
gcc bugzilla, 7 .