MSVC эквивалентно __builtin_popcount?

Что эквивалентно __builtin_popcount как найти в GCC и Clang, для MSVC-10?

3 ответа

Решение

Используя предоставленные комментарии:

  • __popcnt доступны через <intrin.h>
  • _mm_popcnt_u64 с SSE4 и <nmmintrin.h>

С помощью этого фрагмента кода вы получаете встроенный GCC при сборке с MSVC:

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#endif

(Работает с Visual Studio 2008).

__popcount Упомянутый выше intrinsic не работает на ARM или даже на всех процессорах x86 (для этого требуется набор команд ABM). Вы не должны использовать это непосредственно; вместо этого, если вы используете x86/amd64, вы должны использовать __cpuid встроенный, чтобы определить во время выполнения, поддерживает ли процессор popcnt,

Имейте в виду, что вы, вероятно, не хотите выдавать cpuid для каждого popcnt вызов; Вы хотите сохранить результат где-нибудь. Если ваш код всегда будет однопоточным, это тривиально, но если вам нужно быть поточно-ориентированным, вам придется использовать что-то вроде одноразовой инициализации. Это будет работать только с Windows ≥ Vista; если вам нужно работать со старыми версиями, вам нужно будет свернуть свою собственную (или использовать что-то от стороннего производителя).

Для машин без ABM (или если обнаружение во время выполнения не стоит), есть несколько портативных версий в Bit Twiddling Hacks (см. "Набор подсчитанных битов"). Моя любимая версия работает для любого типа T до 128 бит

v = v - ((v >> 1) & (T)~(T)0/3);                           // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count

Если вам нужна встроенная версия, вы можете использовать встроенный модуль в portable-snippets (полное описание: portable-snippets - один из моих проектов), который должен работать практически везде.

Другие вопросы по тегам