gpt4 book ai didi

haskell - 让 GHC 产生 "Add With Carry (ADC)"指令

转载 作者:行者123 更新时间:2023-12-03 14:06:06 25 4
gpt4 key购买 nike

以下代码将表示 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

不幸的是,无论是 native 还是通过 LLVM,GHC 都会产生丑陋的汇编代码,其中涉及将进位位保存到寄存器,然后通过单独的额外添加读取它,而不是仅使用 adc。 .我不想调用外部 C 函数来实现这一点,因为一旦添加了调用开销,它可能不值得,我想留在 Haskell 中,以便可以尽可能内联代码。但我也希望能够诱使编译器生成 adc适当的指导。无论如何我可以做到这一点吗?

最佳答案

最可行和最有效的方法是直接在您的程序中调用 primop。

使用 FFI 调用是最简单的方法,但正如您还指出的,由于 FFI 开销,它不是最有效的方法。

即使编译器支持您想要的指令并在某些程序中使用它,它也会很脆弱。程序中一些看似无害的更改最终可能会生成不同的生成程序集,这些程序集不使用您想要的指令。

所以我的建议是:

  • 将您需要的指令添加到 X86 代码生成器后端(如果还没有的话)。
  • 添加直接转换为您要运行的指令的 primop。首先确保不存在这样的primop。然后按照以下步骤操作:https://ghc.haskell.org/trac/ghc/wiki/AddingNewPrimitiveOperations
  • 您的 primop 应该在 GHC.Prim ( http://hackage.haskell.org/package/ghc-prim/docs/GHC-Prim.html ) 中可见,在您的程序中使用它。
  • 添加测试,提交你的补丁 :)
  • 关于haskell - 让 GHC 产生 "Add With Carry (ADC)"指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33595312/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com