Do not float-in let-bindings marked NOINLINE
I first became aware of the issue from this comment: #9349 (comment 86355)
The main motivation behind this change is to give the user more control over performance in the face of the "state hack" without resorting to the heavier
-fno-state-hack. If you have a let-binding you know is expensive & shouldn't be duplicated via inlining, you could mark it as
NOINLINE to help ensure that. In general, I think this behavior would be more in line with what a user expects when they mark some binding as
I'm not familiar with the subtleties of the issue, but I was recently bitten by it: I had an IO action had JSON parsing inlined into it, causing performance issues. Adding a
NOINLINE pragma to the offending let-binding seemed to force ghc to do what I wanted, but then I saw the linked comment which made me think that fix as it stands is a bit brittle. (I've since just thrown the parse result into a compact region which fixes the issue anyways.)
There was also a recent Reddit thread where another user could've benefited from this.
As described in this comment, when a let-binding is marked
NOINLINE, do not allow it to be floated into a lambda.