Running GHC's LLVM output through the LLVM bitcode linker first

I want to be able to call LLVM code from Haskell without the overhead of a full function call. For example:

-- 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
}

I can compile and link this to produce a functioning executable by running:

ghc -O2 -fllvm Main.hs funcs.ll

Indeed, even removing -fllvm still results in a functioning executable, eg

ghc -O2 Main.hs funcs.ll

Which leads me to strongly suspect GHC is linking these files separately in both cases using ordinary C linkage.

Indeed, when I investigate the intermediate output using:

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

I see the following in Main.s:

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

Which again suggests that GHC is just asking LLVM to compile the files separately and it then just sending the results to the system linker, which wouldn't inline the calls.

Instead, I'd like GHC to send the initial LLVM files (both from GHC and user specified) to the llvm-link, which unlike a system linker, simply combines multiple LLVM bitcode files into one LLVM bitcode file. It would be best if this result was then compiled to native code object file and sent to the system linker, instead of multiple object files being sent to the system linker.

Indeed, when I tried this manually, assembling the .ll human readable files to LLVM .bc bitcode, llvm-link ing the resulting bitcode, then disassembling the bitcode like so:

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

I found the following in the resulting LLVM code

%ln59M = add i64 %ln59L, 1

directly after the call to read, with no "call" or return. The actual function is still in the LLVM, but is uncalled.

So I tried instructing GHC to link with the LLVM linker by adding -pgml llvm-link to the command line, but this failed spectacularly, with llvm-link throwing back many errors about unknown options. This is unsurprising, as llvm-link isn't a real linker, it just combines LLVM files.

So, is there anyway to get GHC to send all it's intermediate LLVM files through the LLVM linker to enable intermodule optimisations at the LLVM level?


Have you tried these two things?

1 - Use the alwaysinline function attribute: http://llvm.org/docs/LangRef.html#function-attributes

2 - Using GHC calling convention, (cc 10 instead of 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/33190.html

上一篇: 图书馆ghc规则不激活

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