Как вы можете вставить NaN в регистр xmm? - PullRequest
9 голосов
/ 21 января 2020

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

Как я могу вставить NaN в регистр xmm самым простым способом

1 Ответ

13 голосов
/ 21 января 2020

Все-это тихий (не сигнализирующий, иначе нормальный) NaN, который вы хотите. Самый простой способ получить единицу - с помощью SSE2 pcmpeqd xmm0,xmm0 установить для каждого бита в регистре значение 1, то есть целое число дополнения 2 -1. ( Эффективно установить все биты в регистре ЦП на 1 / Каковы наилучшие последовательности команд для генерации векторных констант на лету? )

Это на самом деле -NaN - бит знака установлен. Рассмотрите целочисленное смещение вправо (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) также имеет то преимущество, что если вызывающий использует этот регистр повторно в al oop, он не будет иметь задержка обхода домена. (В семействе Sandybridge это длится вечно. Например, каждый addsd xmm1, xmm0 будет иметь дополнительный цикл задержки от ввода xmm1 к выводу xmm1, если xmm0 пришел от pcmpeqd, даже если это было длинным go и целочисленным SIMD Уоп уже удалился.)


Вы можете даже сделать это без ответвлений, если вы используете cmpsd или cmppd: вы можете orps эту маску 0 / -1 в результате для сделать это NaN или без изменений. Если какой-то другой расчет (или уже будет) установит флаг FP-invalid или если вас это не волнует, все готово.

Остерегайтесь удлинения критического пути с помощью дополнительного cmp / или; если вы ожидаете, что это очень редко, вы все равно можете сравнить и перейти, например, с movmskpd / test eax,eax / jnz на результат cmppd, чтобы посмотреть, был ли установлен какой-либо бит =>, один из элементов SIMD не прошел некоторую проверку.

...