Как вы можете вставить NaN в регистр xmm?

9

Для функции, которую я пишу, я бы хотел вернуть Nan, если ввод не имеет смысла.

Как мне проще всего вставить NaN в регистр xmm ?

Markus
источник
1
Как вы определяете, какой «вклад не имеет смысла»? Если это результат сравнения, вы можете просто поразрядно - или ваш «нормальный» результат с маской результата сравнения.
ЧТЗ

Ответы:

13

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 не прошел проверку.

Питер Кордес
источник