Desabilitando SIMD
Instruções Single Instruction Multiple Data (SIMD) são capazes de realizar uma operação (por exemplo, adição) simultaneamente em múltiplas palavras de dados, o que pode acelerar programas significativamente. A arquitetura x86_64 suporta vários padrões SIMD:
- MMX: O conjunto de instruções Multi Media Extension foi introduzido em 1997 e define oito registradores de 64 bits chamados
mm0atémm7. Esses registradores são apenas aliases para os registradores da unidade de ponto flutuante x87. - SSE: O conjunto de instruções Streaming SIMD Extensions foi introduzido em 1999. Em vez de reutilizar os registradores de ponto flutuante, ele adiciona um conjunto de registradores completamente novo. Os dezesseis novos registradores são chamados
xmm0atéxmm15e têm 128 bits cada. - AVX: As Advanced Vector Extensions são extensões que aumentam ainda mais o tamanho dos registradores multimídia. Os novos registradores são chamados
ymm0atéymm15e têm 256 bits cada. Eles estendem os registradoresxmm, então por exemploxmm0é a metade inferior deymm0.
Ao usar tais padrões SIMD, programas frequentemente podem acelerar significativamente. Bons compiladores são capazes de transformar loops normais em tal código SIMD automaticamente através de um processo chamado auto-vetorização.
No entanto, os grandes registradores SIMD levam a problemas em kernels de SO. A razão é que o kernel tem que fazer backup de todos os registradores que usa para a memória em cada interrupção de hardware, porque eles precisam ter seus valores originais quando o programa interrompido continua. Então, se o kernel usa registradores SIMD, ele tem que fazer backup de muito mais dados (512-1600 bytes), o que diminui notavelmente o desempenho. Para evitar esta perda de desempenho, queremos desabilitar os recursos sse e mmx (o recurso avx é desabilitado por padrão).
Podemos fazer isso através do campo features na nossa especificação de alvo. Para desabilitar os recursos mmx e sse, nós os adicionamos prefixados com um menos:
"features": "-mmx,-sse"
Ponto Flutuante
Infelizmente para nós, a arquitetura x86_64 usa registradores SSE para operações de ponto flutuante. Assim, todo uso de ponto flutuante com SSE desabilitado causa um erro no LLVM. O problema é que a biblioteca core do Rust já usa floats (por exemplo, ela implementa traits para f32 e f64), então evitar floats no nosso kernel não é suficiente.
Felizmente, o LLVM tem suporte para um recurso soft-float que emula todas as operações de ponto flutuante através de funções de software baseadas em inteiros normais. Isso torna possível usar floats no nosso kernel sem SSE; será apenas um pouco mais lento.
Para ativar o recurso soft-float para o nosso kernel, nós o adicionamos à linha features na nossa especificação de alvo, prefixado com um mais:
"features": "-mmx,-sse,+soft-float"