Optimising Haskell for a tight inner loop
neilmitchell.blogspot.co.uk
neilmitchell.blogspot.co.uk
[1] https://github.com/martine/ninja/blob/master/src/lexer.in.cc...
[2] https://github.com/martine/ninja/blob/master/src/lexer.cc#L1...
The moment you start trying to compete against hand written assembly, any high level lang gets a bit quirky. One nice thing about ghc Haskell is you can though! A lot of my own open source work is towards a vision of making that much easier than it is today :-)
Yes, which is why I wonder why GHC went with it's own code generator instead of using LLVM? It seems like a lot of the outputted assembly would be coalesced with LLVM's optimizer passes. Is there work on this problem within the Haskell world?
This backend (usually coupled with -O2) tends to slow down compile times tremendously, but can make some math-heavy programs much faster.
LLVM didn't exist when GHC was started.
If you read the blog post, you'll see Neil mentions " tried the LLVM backend, but it generated significantly worse assembly code https://github.com/ndmitchell/blogs/blob/master/inner-loop/I...
@tenslsi : theres certainly room for improving llvm, the ghc native code gen, and pretty much any compiler generally (ghc is no different). I'm actively involved in GHC dev, and i've somewhat committed to spending some volunteer time this year improving the NCG and various backend optimization tooling.
anyways, the reddit discussion of the blog post is also pretty interesting
It's worth noting the LLVM version Neil tried was 2.8, from Dec 2010. LLVM has come a long way since then and I'd be surprised to see if produce such horrible code. I'm hoping Neil will do an updated post using LLVM 3.4 released last week.
http://blog.omega-prime.co.uk/?p=135
Quote: "In particular, LLVM conservatively assumes that GHC's stack and the heap may alias". LLVM has to assume that short of Haskell-specific analysis, so updating to LLVM 3.4 won't help with such issues.
its a very thoughtful, informative, thread. enjoy!
Haskell's performance is very good for nearly everything I write--and I don't write anything nearly that low level--but I can't deny that this is one of the uglier sides of the language.
On the other hand: In most other languages you'd just be dropping down to the C ABI (that's easy to do in Haskell, too, for that matter.) It is kind of impressive that you can write code that is as fast as C without writing C, even if it is ugly.
Impressive, perhaps -- but from a maintainability perspective I think I might prefer to pay the cost of jumping the language barrier to be able to write natural, comprehensible C rather than staying within one language and dealing with an unreadable jumble, even if it performs as well.
mov edx, @table
xor eax, eax
loop:
mov al, [ecx]
inc ecx
cmp byte [edx+eax], 0
jnz loop
I really wish Intel would optimise lodsb, scasb, and the rest of the string instructions, since they're powerful and particularly suited for this sort of scanning.Removing and re-purposing instructions is not unprecedented; it has already been done at 32->64 jump. (Prefixes, decimal instructions, etc.)