Como você determina qual "entrada não faz sentido"? Se este é o resultado de uma comparação, você pode apenas bit a bit - ou seu resultado "normal" com a máscara de resultado da comparação.
Na verdade, é um -NaN- o bit do sinal está definido. Considere shift inteiro à direita ( psrld xmm0,1) ou divida por zero / zero ( xorps xmm0,xmm0/ divpd xmm0,xmm0), se isso for indesejável.
As funções matemáticas que desejam retornar o NaN geralmente também desejam garantir que o bit de exceção autônomo FP-inválido seja definido no MXCSR (ou, na verdade, crie uma exceção se o chamador desmascarou essa exceção). Para fazer isso , você pode multiplicar ou adicionar o NaN com ele mesmo. por exemplo
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
Ou mulsspara precisão única float. mulpd/ mulpstambém seria apropriado.
O padrão de bits para multiplicar ou adicionar NaN com NaN ainda é definitivamente um NaN e ainda deve ser a mesma carga útil, portanto ainda é tudo.
Ter o valor de retorno como resultado de mulsdou addsd(ou divsd) também tem a vantagem de que, se o chamador usar esse registro repetidamente em um loop, ele não terá latência de desvio de cruzamento de domínio. (Na família Sandybridge, isso dura para sempre. Por exemplo, todos addsd xmm1, xmm0teriam um ciclo extra de latência da entrada xmm1 para a saída xmm1 se xmm0 viesse pcmpeqd, mesmo que isso tenha sido há muito tempo e o uop SIMD inteiro já tenha se aposentado.)
Você pode até fazê-lo sem ramificações se usar cmpsdou cmppd: pode orpsmascarar 0 / -1 em um resultado para torná-lo NaN ou inalterado. Se algum outro cálculo (ou já tiver) definido o sinalizador de FP inválido, ou se você não se importa com isso, está tudo pronto.
Cuidado ao prolongar o caminho crítico com extra cmp / ou; se você acha que é super raro, você ainda pode comparar e ramificar, por exemplo, com movmskpd/ test eax,eax/ jnzem um resultado cmppd para ver se um dos bits foi definido => um dos elementos SIMD falhou em alguma verificação.
Respostas:
All-ones é um NaN silencioso (sem sinalização, também conhecido como normal), que é o que você deseja. A maneira mais fácil de produzir uma é com o SSE2
pcmpeqd xmm0,xmm0
para definir cada bit no registrador como1
, ou seja, o número inteiro do complemento de 2-1
. ( Defina todos os bits no registro da CPU como 1 de forma eficiente / Quais são as melhores seqüências de instruções para gerar constantes de vetores em tempo real? )Na verdade, é um
-NaN
- o bit do sinal está definido. Considere shift inteiro à direita (psrld xmm0,1
) ou divida por zero / zero (xorps xmm0,xmm0
/divpd xmm0,xmm0
), se isso for indesejável.As funções matemáticas que desejam retornar o NaN geralmente também desejam garantir que o bit de exceção autônomo FP-inválido seja definido no MXCSR (ou, na verdade, crie uma exceção se o chamador desmascarou essa exceção). Para fazer isso , você pode multiplicar ou adicionar o NaN com ele mesmo. por exemplo
Ou
mulss
para precisão únicafloat
.mulpd
/mulps
também seria apropriado.O padrão de bits para multiplicar ou adicionar NaN com NaN ainda é definitivamente um NaN e ainda deve ser a mesma carga útil, portanto ainda é tudo.
Ter o valor de retorno como resultado de
mulsd
ouaddsd
(oudivsd
) também tem a vantagem de que, se o chamador usar esse registro repetidamente em um loop, ele não terá latência de desvio de cruzamento de domínio. (Na família Sandybridge, isso dura para sempre. Por exemplo, todosaddsd xmm1, xmm0
teriam um ciclo extra de latência da entrada xmm1 para a saída xmm1 se xmm0 viessepcmpeqd
, mesmo que isso tenha sido há muito tempo e o uop SIMD inteiro já tenha se aposentado.)Você pode até fazê-lo sem ramificações se usar
cmpsd
oucmppd
: podeorps
mascarar 0 / -1 em um resultado para torná-lo NaN ou inalterado. Se algum outro cálculo (ou já tiver) definido o sinalizador de FP inválido, ou se você não se importa com isso, está tudo pronto.Cuidado ao prolongar o caminho crítico com extra cmp / ou; se você acha que é super raro, você ainda pode comparar e ramificar, por exemplo, com
movmskpd
/test eax,eax
/jnz
em um resultado cmppd para ver se um dos bits foi definido => um dos elementos SIMD falhou em alguma verificação.fonte