Ecco il codice che aggiunge due triple di Parole disimballati che rappresentano un numero 192 bit in un nuova tripla di parole unboxed, e anche restituisce qualsiasi overflow:Ottenere GHC per la produzione di "Add Con Carry (ADC)" istruzioni
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
import GHC.Prim(plusWord2#, Word#, or#)
longAdd ::
(# Word#, Word#, Word# #) ->
(# Word#, Word#, Word# #) ->
(# Word#, (# Word#, Word#, Word# #) #)
longAdd (# xl, xm, xh #) (# yl, ym, yh #) =
let
plusWord3 x y c =
let
(# c1, r1 #) = plusWord2# x y
(# c2, r2 #) = plusWord2# r1 c
in
(# plusWord# c1 c2, r2 #)
(# cl, rl #) = plusWord2# xl yl
(# cm, rm #) = plusWord3 xm ym cl
(# ch, rh #) = plusWord3 xh yh cm
in
(# ch, (# rl, rm, rh #) #)
Il problema è la definizione "plusWord3". Idealmente, questo è proprio come una funzione di "ADC", che prende due parole e il bit di riporto e restituisce il risultato e una nuova trasportare, in modo l'assembly risultante è simile al seguente:
add x1 y1
adc x2 y2
adc x3 y3
Purtroppo GHC, sia nativo o tramite LLVM, produce un codice di assemblaggio brutto che comporta il salvataggio del bit di carry in un registro e quindi la lettura tramite un addizionale aggiuntivo separato, invece di utilizzare semplicemente adc
. Non voglio chiamare una funzione C esterna per ottenere questo risultato, poiché una volta che aggiungi l'overhead della chiamata probabilmente non ne vale la pena, mi piacerebbe rimanere in Haskell in modo che il codice possa essere allineato laddove possibile. Ma voglio anche essere in grado di convincere il compilatore a produrre l'istruzione adc
in modo appropriato. C'è comunque posso ottenerlo?
192 parole bit (e molti altri) sono disponibili in [ 'dati.DoubleWord'] (https://hackage.haskell.org/package/data-dword-0.3/docs/Data-DoubleWord.html). Mi chiedo se è ottimizzato per generare codice efficiente, quindi potrebbe essere una fonte di conoscenza su come farlo, o un posto dove contribuire, una volta trovata la risposta. –