下面的代码将表示 192 位数字的两个未装箱字三元组添加到新的未装箱字三元组中,并且还返回任何溢出:
{-# 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 #) #)
问题在于“plusWord3”的定义。理想情况下,这就像一个“adc”函数,它接受两个字和进位位并返回结果和一个新的进位,因此生成的汇编如下所示:
add x1 y1
adc x2 y2
adc x3 y3
不幸的是,GHC,无论是本机还是通过 LLVM,都会产生丑陋的汇编代码,其中涉及将进位位保存到寄存器,然后通过单独的额外添加读取它,而不是仅仅使用adc
。我不想调用外部 C 函数来实现此目的,因为一旦添加了调用开销,可能就不值得了,我想留在 Haskell 中,以便可以在可能的情况下内联代码。但我也希望能够诱使编译器生成adc
适当的指导。无论如何我可以实现这一目标吗?