Получение 4 вместо 59 звучит как clang _BitScanReverse64
как 63 - lzcnt
. Фактический bsr
медленный на AMD, поэтому да, есть причины, по которым компилятор может захотеть скомпилировать встроенный c BSR в другую инструкцию.
Но затем вы запустили исполняемый файл на компьютере который на самом деле не поддерживает BMI, поэтому lzcnt
декодируется как rep bsr
= bsr
, давая счетчик ведущих нулей вместо битового индекса самого высокого установленного бита.
AFAIK, все процессоры с AVX2 также имеют BMI. Если в вашем процессоре этого нет, вам не следует ожидать, что ваши исполняемые файлы, собранные с /arch:AVX2
, будут правильно работать на вашем процессоре. И в этом случае режим отказа не был незаконной инструкцией, он был lzcnt
запущен как bsr
.
MSV C обычно не оптимизирует встроенные функции, очевидно, включая этот случай, поэтому он просто использует bsr
напрямую.
Обновление: i7-3930K - это SandyBridge-E. У него нет AVX2, так что это объясняет ваши результаты.
clang-cl не вызывает ошибки, когда вы говорите ему создать исполняемый файл AVX2 на компьютере, отличном от AVX2. Примером использования для этого будет компиляция на одной машине для создания исполняемого файла для запуска на разных машинах.
Это также не добавляет код проверки CPUID в ваш исполняемый файл за вас. Если хотите, напишите сами. Это C ++, он вас за руку не держит.
параметры целевого процессора
MSV C -style /arch
параметры гораздо более ограничены, чем обычный стиль GCC / clang. Их нет для разных уровней SSE, таких как SSE4.1; он переходит прямо к AVX.
Кроме того, /arch:AVX2
очевидно подразумевает BMI1 / 2, хотя это разные наборы инструкций с разными битами функций CPUID. Например, в коде ядра вам могут понадобиться целочисленные инструкции BMI, но не инструкции SIMD, которые касаются регистров XMM / YMM.
clang -O3 -mavx2
не также включает -mbmi
. Обычно вы этого захотите, но если бы вам не удалось также включить BMI, clang застрял бы с использованием bsr
. (Что на самом деле лучше для процессоров Intel, чем 63-lzcnt
). Я думаю, что MSV C / arch: AVX2 - это что-то вроде -march=haswell
, если он также включает инструкции FMA.
И ничто в MSV C не поддерживает оптимизацию двоичных файлов для запускать на компьютере, на котором вы их собираете . В этом есть смысл, он разработан для модели разработки программного обеспечения с закрытым исходным кодом.
Но G CC и clang имеют -march=native
, чтобы включить все наборы инструкций на вашем компьютере. поддерживает. И, что немаловажно, установите параметры настройки , подходящие для вашего компьютера. например, не беспокойтесь о создании кода, который будет медленным на процессоре AMD или на старом Intel, просто сделайте asm, который подходит для вашего CPU.
TL: DR: параметры выбора процессора in clang-cl очень грубые, объединяющие не-SIMD-расширения с некоторым уровнем AVX. Вот почему /arch:AVX2
включает целочисленное расширение BMI, а clang -mavx2
не поддерживает.