Для функции, которую я пишу, я бы хотел вернуть Nan, если ввод не имеет смысла.
Как мне проще всего вставить NaN в регистр xmm ?
Для функции, которую я пишу, я бы хотел вернуть Nan, если ввод не имеет смысла.
Как мне проще всего вставить NaN в регистр xmm ?
Ответы:
All-One - это тихий (не сигнальный, нормальный) NaN, который вам нужен. Самый простой способ получить его - использовать SSE2 pcmpeqd xmm0,xmm0
для установки каждого бита в регистре 1
, то есть целого числа дополнения 2 -1
. ( Установите все биты в регистре ЦП на 1 / Каковы наилучшие последовательности команд для генерации векторных констант на лету? )
Это на самом деле -NaN
- бит знака установлен. Рассмотрим целое число вправо shift ( psrld xmm0,1
) или разделить на ноль / ноль ( xorps xmm0,xmm0
/ divpd xmm0,xmm0
), если это нежелательно.
Математические функции, которые хотят возвращать NaN, часто также хотят убедиться, что бит неверного исключения FP установлен в MXCSR (или фактически вызовет исключение, если ваш вызывающий абонент разоблачил это исключение). Для того, чтобы сделать что , вы можете умножить или добавить NaN с собой. например
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
Или mulss
для одинарной точности float
. mulpd
/ mulps
также будет уместно.
Битовый шаблон для умножения или добавления NaN с NaN определенно все еще является NaN, и все равно должен быть такой же полезной нагрузкой, так что все равно единицами.
Наличие возвращаемого значения в результате mulsd
или addsd
(или divsd
) также имеет то преимущество, что если вызывающий использует этот регистр несколько раз в цикле, у него не будет задержки обхода при пересечении домена. (В семействе Sandybridge это длится вечно. Например, у каждого addsd xmm1, xmm0
будет дополнительный цикл задержки от входа xmm1 до выхода xmm1, если xmm0 пришло pcmpeqd
, даже если это было давно, и uop с целочисленным SIMD уже удалился.)
Вы можете даже сделать это без ответвлений, если вы используете cmpsd
или cmppd
: вы можете использовать orps
эту маску 0 / -1 в результате, чтобы сделать его NaN или неизменным. Если какой-либо другой расчет (или уже будет) установит флаг FP-invalid или если вам это не важно, все готово.
Остерегайтесь удлинения критического пути с помощью дополнительных cmp / или; если вы ожидаете, что это очень редко, вы все равно можете сравнить и перейти, например, с помощью movmskpd
/ test eax,eax
/ jnz
для результата cmppd, чтобы увидеть, был ли установлен какой-либо бит => один из элементов SIMD не прошел проверку.