Краткий ответ:
Ваш массив 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%.
В обоих случаях результат обнуления используется только через 3 инструкции. Так что вполне возможно, что это может быть на критическом пути выполнения.
Хотя я не инженер 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
), преобразование не требуется. Следовательно, проблема полностью исключена.