【问题标题】:Running GHC's LLVM output through the LLVM bitcode linker first首先通过 LLVM 位码链接器运行 GHC 的 LLVM 输出
【发布时间】:2015-11-23 02:53:04
【问题描述】:

我希望能够从 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 人类可读文件组装到 LLVM .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 链接器链接,但这非常失败,llvm-link 抛出了许多关于未知选项的错误。这并不奇怪,因为llvm-link 不是真正的链接器,它只是组合 LLVM 文件。

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

【问题讨论】:

    标签: haskell llvm ghc


    【解决方案1】:

    这两件事你试过了吗?

    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
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-12
      • 2021-01-27
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多