
GHC tries hard NOT to choose an INLINE function as a loop breaker. But if you write
f x = if ... then 0 else (f x') {-# INLINE f #-}
then the only possible loop breaker is 'f', so GHC has to choose it.
Indeed.
What else would you suggest?
A warning would be very welcome. Given that the debugging compiler emits one, perhaps it's not too difficult to add. Apart of that, if the heuristics is based not on INLINE pragmas, but on available unfoldings, as Matthew suggests in his wiki article, I'd propose to fix that, see the case below.
What puzzling behaviour do you have in mind?
I can't reconstruct it now, but I was profiling as set of mutually recursive functions, with -fexpose-all-unfoldings (so GHC could not decide based on available unfoldings) and INLINE on only some of them (I don't remember if the others had NOINLINE or nothing). I had an impression some of the INLINEs where ignored and that the loop breaker was not at the place I was forcing, but the impression was based only on comparison of runtimes of different variants, not on inspecting core. A warning would really help next time to let me catch a concrete example to post.