Ответ 1
Краткий ответ:
Ваш массив asd
объявлен следующим образом:
int *asd=new int[16];
Поэтому используйте int
как возвращаемый тип, а не bool.
Альтернативно, измените тип массива на bool
.
В любом случае, возвращаемый тип функции test
соответствует типу массива.
Пропустите снизу для более подробной информации.
Длинный ответ:
В ручной встроенной версии "ядро" одной итерации выглядит следующим образом:
xor eax,eax
mov edx,ecx
and edx,0Fh
mov dword ptr [ebp+edx*4],eax
mov eax,dword ptr [esp+1Ch]
movss xmm0,dword ptr [eax]
movss xmm1,dword ptr [edi]
cvtps2pd xmm0,xmm0
cvtps2pd xmm1,xmm1
comisd xmm1,xmm0
Встроенная версия компилятора полностью идентична, кроме первой инструкции.
Где вместо:
xor eax,eax
он имеет:
xor eax,eax
movzx edx,al
Хорошо, так что это одна дополнительная инструкция. Они оба делают то же самое - обнуление регистра. Это единственное отличие, которое я вижу...
Команда movzx
имеет однократную задержку и 0.33
циклическую обратную пропускную способность на всех новых архитектурах. Поэтому я не могу представить, как это может привести к 10% -ной разнице.
В обоих случаях результат обнуления используется только тремя инструкциями позже. Поэтому очень возможно, что это может быть на критическом пути выполнения.
Пока я не инженер Intel, я думаю:
Большинство современных процессоров рассматривают операции обнуления (например, xor eax,eax
) через переименовать регистр в банк нулевых регистров. Он полностью обходит исполнительные блоки. Однако возможно, что эта специальная обработка может вызвать пузырь трубопровода, когда доступ к (частичному) регистру осуществляется через movzx edi,al
.
Кроме того, существует также ложная зависимость от eax
в встроенной версии компилятора:
movzx edx,al
mov eax,ecx // False dependency on "eax".
Независимо от того, может ли выполнить нестандартное выполнение, это выходит за рамки меня.
Хорошо, это в основном превращается в вопрос обратного проектирования компилятора MSVC...
Здесь я объясню почему, что генерируется дополнительный movzx
, а также почему он остается.
Ключевым здесь является возвращаемое значение bool
. По-видимому, типы данных bool
, вероятно, являются хранимыми 8-битными значениями внутри внутреннего представления MSVC.
Поэтому, когда вы неявно конвертируете из bool
в int
здесь:
asd[j%16] = a.test(b);
^^^^^^^^^ ^^^^^^^^^
type int type bool
существует 8-битное → 32-битное целочисленное продвижение. Именно по этой причине MSVC генерирует инструкцию movzx
.
Когда встраивание выполняется вручную, компилятор имеет достаточно информации для оптимизации этого преобразования и сохраняет все как 32-битный IR-тип данных.
Однако, когда код помещается в его собственную функцию с возвращаемым значением bool
, компилятор не может оптимизировать 8-разрядный промежуточный тип данных. Поэтому movzx
остается.
Когда вы создаете оба типа данных одинаковыми (либо int
, либо bool
), преобразование не требуется. Поэтому проблему вообще можно избежать.