首先通过LLVM位代码链接器运行GHC的LLVM输出

我希望能够从Haskell调用LLVM代码,而不需要全部函数调用的开销。 例如:

-- Main.hs --

{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE UnliftedFFITypes #-}
{-# LANGUAGE BangPatterns #-}

import GHC.Exts(Word(W#))
import GHC.Prim(Word#)

foreign import ccall llvminc :: Word# -> Word#

main = do
  line1 <- getLine
  let !(W# x1) = read line1
  let !r1 = llvminc x1
  print (W# r1)


-- funcs.ll --

define fastcc i64 @llvminc(i64 inreg %x) {
  %r = add i64 %x, 1
  ret i64 %r
}

我可以通过运行编译并链接它来生成可执行的可执行文件:

ghc -O2 -fllvm Main.hs funcs.ll

事实上,即使删除-fllvm仍然会导致正常运行,例如

ghc -O2 Main.hs funcs.ll

这导致我强烈怀疑GHC正在使用普通C链接在这两种情况下分别链接这些文件。

事实上,当我使用以下方法调查中间产出时:

ghc -O2 -fllvm -keep-s-files Main.hs funcs.ll

我在Main.s中看到以下内容:

callq   suspendThread
movq    %rax, %rbp
movq    %rbx, %rdi
callq   llvminc
movq    %rax, %rbx
movq    %rbp, %rdi
callq   resumeThread

这再次表明,GHC只是要求LLVM分别编译这些文件,然后将结果发送给系统链接程序,该链接程序不会内联该呼叫。

相反,我希望GHC将最初的LLVM文件(从GHC和用户指定的文件)发送到llvm-link,这与系统链接器不同,它简单地将多个LLVM位码文件组合成一个LLVM位码文件。 如果将此结果编译为本地代码对象文件并发送到系统链接程序,而不是将多个对象文件发送到系统链接程序,则最好。

事实上,当我手动尝试这种方式时,将.ll人类可读文件组装成.bc位代码,然后将生成的位代码llvm-link起来,然后像下面这样拆分位代码:

llvm-as Main.ll
llvm-as funcs.ll
llvm-link funcs.bc Main.bc -o combined.bc
llvm-dis combined.bc

我在LLVM代码中找到了以下内容

%ln59M = add i64 %ln59L, 1

在通话结束后直接阅读,没有“通话”或返回。 实际功能仍在LLVM中,但未被调用。

所以我试着通过在命令行中添加-pgml llvm-link来指示GHC与LLVM链接器进行-pgml llvm-link ,但是这种失败非常严重,并且llvm-link抛出关于未知选项的许多错误。 这并不令人惊讶,因为llvm-link不是一个真正的链接器,它只是结合了LLVM文件。

那么,有没有办法让GHC通过LLVM链接器发送所有LLVM文件的中间文件,以实现LLVM级别的模块间优化?


你尝试过这两件事吗?

1 - 使用alwaysinline函数属性:http: //llvm.org/docs/LangRef.html#function-attributes

2 - 使用GHC调用约定(cc 10代替fastcc):http://llvm.org/docs/LangRef.html#calling-conventions

define cc 10 i64 @llvminc(i64 inreg %x) alwaysinline {
  %r = add i64 %x, 1
  ret i64 %r
}
链接地址: http://www.djcxy.com/p/33189.html

上一篇: Running GHC's LLVM output through the LLVM bitcode linker first

下一篇: } Causes 'RULE left