(Esta é uma versão expandida do problema (https://github.com/WebAssembly/spec/issues/446))
A aritmética de precisão múltipla requer manuseio especial. Isso está disponível de alguma forma em todas as ISAs, mas não está disponível atualmente no webasm.
Existem basicamente três maneiras de fazer isso (parece-me), nenhuma das quais é especialmente palatável no contexto do design atual:
Opção 1. Adicione um registrador de flags especial, junto com instruções que fazem aritmética com aquele registrador.
Esta é a abordagem tradicional no hardware convencional.
Você recebe instruções como
adicionar
que adicionará dois números e o valor do sinalizador de transporte e definirá o sinalizador de transporte no resultado.
Isso não é agradável porque adiciona um registro especial.
Opção 2.
Suporta uma forma de aritmética de 60 bits com 4 bits para sinalizadores.
Opção 3.
Suporta aritmética multi-palavra: a adição leva 3 argumentos e produz 2 saídas.
Essa abordagem causará menos danos ao ISA existente e à arquitetura de registro. No entanto, isso será difícil de mapear para o hardware existente de forma eficiente (nem todos os ISAs de hardware suportam o carregamento do registro de sinalizadores diretamente.
Seja como for, a aritmética de precisão múltipla é bastante importante e muito difícil de emular sem algum suporte de hardware simples.
Parece-me que para a opção 3 existem otimizações plausíveis que tornariam isso prático. Suponha que {i32,i64}.addc receba três entradas, op2 no topo, op1 abaixo, carry na base e produza duas saídas, result no topo e carry abaixo. Por uma questão de argumento, suponha que o carry seja sempre do mesmo tipo que os outros operandos. Defina addc apenas para usar o bit baixo do carry e para que o carry restante após a operação seja zero ou um. As coisas agora estão razoavelmente configuradas para uma adição de várias palavras, digamos. Em um loop adequadamente desenrolado, um compilador JIT/Wasm realmente deve ser capaz de ver que é o transporte que está sendo propagado e gerar um bom código. (E se o loop não for desenrolado, a sobrecarga do loop diluirá a extração/inserção de transporte de qualquer maneira.) Acho que o código livre de ramificação do pior caso para extração de transporte deve ser mov rd, 0; adc rd, 0
; para inserção, algo como and rc, 1; add rc, ~0
onde rc é um registrador que contém um valor a ser tratado como um carry.
No ARM, consumir um carry é separado de produzir um carry: ADC consome, ADC.S consome e produz, ADD.S apenas produz. Queremos todas essas variantes? E sobre o transbordamento?
(Pode haver uma quarta opção, onde adicionamos uma operação de operação e ramificação na condição que produz um resultado e ramifica para um rótulo ou não, por exemplo, i32.addc op1 op2 carry L
ramifica para L no conjunto de transporte e cai no carry clear, e de qualquer forma deixa um resultado na pilha, mas parece mais difícil de usar em geral do que as três opções que você sugeriu.)
Existe alguém disposto a defender esta proposta? Precisaríamos de semântica proposta, codificação binária e gostaria de pelo menos um mínimo de casos de uso e uma implementação com números de desempenho para esses casos de uso (compare o MVP WebAssembly atual, com essa adição proposta e o código nativo).
Em princípio, eu estaria disposto a defender isso.
No entanto, mudanças pessoais significam que tenho recursos limitados pelo menos nos próximos meses.
———
Frank McCabe
Arquiteto de Software Sênior
Telefone: 650-740 6673 | E-mail: [email protected] [email protected]
Lógica de inicialização | 450 Lambert Ave, Palo Alto, CA 94306 | instartlogic. com http://instartlogic.com/
Em 11 de maio de 2017, às 10h14, JF Bastien [email protected] escreveu:
Existe alguém disposto a defender esta proposta? Precisaríamos de semântica proposta, codificação binária e gostaria de pelo menos um mínimo de casos de uso e uma implementação com números de desempenho para esses casos de uso (compare o MVP WebAssembly atual, com essa adição proposta e o código nativo).
—
Você está recebendo isso porque foi o autor do tópico.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/WebAssembly/design/issues/1021#issuecomment-300856161 ou silencie o tópico https://github.com/notifications/unsubscribe-auth/ADfCzd9le4ufXm6DSsArpfXCYsGdV7UIks5r40H5gaJpZM4MrKma .
Provavelmente terei tempo para me dedicar a isso, embora não muito até junho ou algo assim, e depois no outono. IMO essa funcionalidade é bastante importante, e acho que o sinalizador de estouro é tão importante quanto o sinalizador de transporte, embora com diferentes casos de uso (fixnum das linguagens dinâmicas -> transição bignum).
Discuti isso com algumas pessoas da Mozilla hoje. Resumindo:
Houve algum progresso nesta questão? Carregar e emprestar são necessários para implementar a criptografia moderna (por exemplo, SIDH) de forma eficiente. A adição de grande número sem ADDC é vários fatores mais lenta do que com. O mesmo se aplica à subtração e à multiplicação.
Acho que estamos pelo menos esperando que o multi-valor seja concluído para que possamos expressar facilmente uma operação com mais de um resultado. O valor múltiplo está "quase lá".
Comentários muito úteis
Houve algum progresso nesta questão? Carregar e emprestar são necessários para implementar a criptografia moderna (por exemplo, SIDH) de forma eficiente. A adição de grande número sem ADDC é vários fatores mais lenta do que com. O mesmo se aplica à subtração e à multiplicação.