I am very disappointed with my favourite language this week. I found out that x `shift` 7
and x `rotate` 7
do not have the bounds checks on 7
optimised away in GHC. One solution is to write non-portable GHC specific code such as x `uncheckedShiftL#` 7
, but I won’t do it and I shouldn’t have to do it. Clearly the optimiser is what is broken. Asking for bounds checks on compile-time constants to be removed is only natural.
With the help of Samuel Bronson (actually it was all his work) we’ve managed to hack a patch together that allows functions like shift
to get inlined and have the bounds checking rewritten away. However rotate
is still a problem.
The problem as I see it is that GHC relies on its inliner to expose code that rewrite rules and other simplifications can operate on; however, the inliner is unreliable for this task. The inliner works by always inlining small bits of code, never inlining large bits of code, and sometimes inlining medium bits of code. The sometimes tries to guess if it would be useful to inline or not, and it does a poor job of guessing.
This method of inlining leads to bizarre consequences. As small bits of code get repeatedly inlined, small bits of code can turn into large bits of code. The net result is that it may be possible for one to mark a small bit of code as {-# NOINLINE foo #-}
, allowing another piece of code to remain small, allowing it to be inlined, allowing rules to be applied that would not otherwise be applied, and resulting in smaller and faster code than would be generated if the the no-inline pragma wasn’t used.
This whole business of using heuristics to inline or not seems like a bunch of nonsense. I would expect the compiler to know if there is a potential for a rule to cross a βδ-reduction boundary, and try inlining in that case to see what happens. Or I would expect the compiler to break bits of code and inline part of a function where a rule can apply.
I know that writing an optimal optimiser that is still practical is a difficult challenge, but if this is the state-of-the-art in functional program optimisation then we are in big trouble.