
Simon Marlow
On 27/12/13 20:21, Ben Gamari wrote:
Simon Marlow
writes: This sounds right to me. Did you submit a patch?
Note that dynamic linking with LLVM is likely to produce significantly worse code that with the NCG right now, because the LLVM back end uses dynamic references even for symbols in the same package, whereas the NCG back-end uses direct static references for these.
Today with the help of Edward Yang I examined the code produced by the LLVM backend in light of this statement. I was surprised to find that LLVM's code appears to be no worse than the NCG with respect to intra-package references.
My test case can be found here[2] and can be built with the included `build.sh` script. The test consists of two modules build into a shared library. One module, `LibTest`, exports a few simple members while the other module (`LibTest2`) defines members that consume them. Care is taken to ensure the members are not inlined.
The tests were done on x86_64 running LLVM 3.4 and GHC HEAD with the patches[1] I referred to in my last message. Please let me know if I've missed something.
This is good news, however what worries me is that I still don't understand *why* you got these results. Where in the LLVM backend is the magic that does something special for intra-package references?
As far as I can tell, the backend itself does nothing in particular to handle this.
I know where it is in the NCG backend - CLabel.labelDynamic - but I can't see this function used at all in the LLVM backend.
Right. For the record, I took a first stab at implementing[1] the logic that I thought would needed to get LLVM to do efficient dynamic linking before taking this measurement. I probably should have reused more of the machinery used by the NCG however. I don't believe I managed to get this code stable before dropping it when I realized that LLVM already somehow did the right thing.
So what is the mechanism that lets LLVM optimise these calls? Is it happening magically in the linker, perhaps? But that would only be possible when using -Bsymbolic or -Bsymbolic-functions, which is a choice made at link time.
This seems like the most likely explanation but given we don't pass this flag I really don't see why the linker would do this. More research is necessary it seems.
As far as I can tell, all we do is pass a flag to llc to tell it to compile for dynamic/PIC, in DriverPipeline.runPhase.
Right. Very mysterious. Cheers, - Ben [1] https://github.com/bgamari/ghc/tree/llvm-intra-package