2015-11-08 58 views
17

這裏是代碼,增加了代表192位的數字拆箱詞兩個三倍到一個新的三重未裝箱的話,還返回任何溢出:獲取GHC產生「帶進位加法(ADC)」的說明

{-# 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指令。無論如何,我可以實現這一目標嗎?

+1

192位字(和許多其他人)在['可用數據。DoubleWord'](https://hackage.haskell.org/package/data-dword-0.3/docs/Data-DoubleWord.html)。我想知道它是否經過優化以生成高效的代碼,因此一旦找到答案,它可能是知道如何去做的地方,也可能是提供貢獻的地方。 –

回答

8

我對低級編程不熟悉,但是在Freenode的#ghc通道回答問題後,我得到了指向addIntC# primop的指針,這與LLVM的llvm.sadd.with.overflow.有關。我不確定什麼llvm編譯成。


GHC的本機代碼根似乎知道即將adc指令:X86/CodeGen.hs。但正如評論說:

我們處理另外,而是嚴重


編輯:你用文字工作。看來,LLVM後端編譯不MO_Add2(這是另一個plusWord2名)llvm.uadd.with.overflowhttps://github.com/ghc/ghc/blob/2b7d9c2b96eb9da3cce7826df4a91c3426095528/compiler/llvmGen/LlvmCodeGen/CodeGen.hs#L737,相關門票:https://ghc.haskell.org/trac/ghc/ticket/9430

11

最可靠而有效的方法是在你的程序直接調用primop。

使用FFI調用是最簡單的方法,但你也注意到它不會是最有效的方式,因爲FFI開銷。

即使編譯器會支持你想要的指令,並在某些程序中使用它,這將是脆弱的。程序中一些看似無意的更改可能會以不同的生成程序集而不使用所需的指令爲結束。

所以我的建議是:

  1. 添加你需要X86代碼生成器後端的指令,如果它不存在的話。
  2. 添加直接轉化爲你想要運行的指令primop。首先確保沒有這樣的primop存在。然後按照下列步驟操作:https://ghc.haskell.org/trac/ghc/wiki/AddingNewPrimitiveOperations
  3. 您primop應該是可見的GHC.Prim(http://hackage.haskell.org/package/ghc-prim/docs/GHC-Prim.html),在你的程序中使用它。
  4. 添加測試,提交你的補丁:)