Я встретил этот код CRC32 и было любопытно, почему автор решил использовать
crc = crc ^ ~0U;
вместо
crc = ~crc;
Насколько я могу судить, они эквивалентны.
Я даже разобрал две версии в Visual Studio 2010.
Не оптимизированная сборка:
crc = crc ^ ~0U;
009D13F4 mov eax,dword ptr [crc]
009D13F7 xor eax,0FFFFFFFFh
009D13FA mov dword ptr [crc],eax
crc = ~crc;
011C13F4 mov eax,dword ptr [crc]
011C13F7 not eax
011C13F9 mov dword ptr [crc],eax
Я также не могу оправдывать код, думая о количестве циклов, которое берет каждая инструкция, поскольку оба должны выполнить 1 цикл для завершения. Фактически, у xor может быть штраф за то, что нужно загрузить литерал откуда-то, хотя я не уверен в этом.
Итак, я остаюсь думать, что это возможно просто предпочтительный способ описать алгоритм, а не оптимизацию... Правильно ли это?
Изменить 1:
Так как я только понял, что тип переменной crc
, вероятно, важно упомянуть, что я включаю весь код (за исключением таблицы поиска, слишком большой), поэтому вам не нужно следовать ссылке.
uint32_t crc32(uint32_t crc, const void *buf, size_t size)
{
const uint8_t *p;
p = buf;
crc = crc ^ ~0U;
while (size--)
{
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ ~0U;
}
Изменить 2:
Поскольку кто-то поднял тот факт, что оптимизированная сборка будет интересна, я сделал ее и включил ее ниже.
Оптимизированная сборка:
Обратите внимание, что вся функция (включенная в последнее изменение ниже) была встроена.
// crc = crc ^ ~0U;
zeroCrc = 0;
zeroCrc = crc32(zeroCrc, zeroBufferSmall, sizeof(zeroBufferSmall));
00971148 mov ecx,14h
0097114D lea edx,[ebp-40h]
00971150 or eax,0FFFFFFFFh
00971153 movzx esi,byte ptr [edx]
00971156 xor esi,eax
00971158 and esi,0FFh
0097115E shr eax,8
00971161 xor eax,dword ptr ___defaultmatherr+4 (973018h)[esi*4]
00971168 add edx,ebx
0097116A sub ecx,ebx
0097116C jne main+153h (971153h)
0097116E not eax
00971170 mov ebx,eax
// crc = ~crc;
zeroCrc = 0;
zeroCrc = crc32(zeroCrc, zeroBufferSmall, sizeof(zeroBufferSmall));
01251148 mov ecx,14h
0125114D lea edx,[ebp-40h]
01251150 or eax,0FFFFFFFFh
01251153 movzx esi,byte ptr [edx]
01251156 xor esi,eax
01251158 and esi,0FFh
0125115E shr eax,8
01251161 xor eax,dword ptr ___defaultmatherr+4 (1253018h)[esi*4]
01251168 add edx,ebx
0125116A sub ecx,ebx
0125116C jne main+153h (1251153h)
0125116E not eax
01251170 mov ebx,eax