Do two-phase inlining in simpleOptPgm
As of #12988 (closed), having simpleOptPgm leave β-redexes lying around is painful because it requires a special loophole in Core Lint to allow a jump inside a β-redex. We'd rather use a two-phase approach, mirroring the simplifier's preInlineUnconditionally and postInlineUnconditionally, so we can aggressively eliminate β-redexes without fear of exponential blowup.
Consider:
joinrec j1 x = e1 in
join j2 x y = jump j1 e2 in
jump j2 e3 e4
Since j2 is only used once, it gets inlined. But simpleOptPgm only performs inlining //after// a binding is simplified, so we end up here:
joinrec j1 x = e1' in
(\x y -> jump j1 e2') e3' e4'
Since e2' was already simplified, performing the β-reduction here risks exponential blowup for the same reason it can happen in the simplifier (see the Secrets paper; perf/compiler/T783 is a live example, increasing in allocs by over 80% if we re-simplify here). We //could// just let-bind e3' and e4' (carefully avoiding capturing free occurrences of x in e4'), but not if one them is actually a type argument. Well, okay, we //could// introduce a type let, but doing that here means the desugarer can now return a type let and we're not prepared for that. (Specifically, under certain circumstances, the simplifier never runs in between the desugarer and Float Out, and the latter breaks in the presence of type let.)
So for the moment, we leave the β-redex there, but this needs a special rule just for β-redexes because normally you can't have a jump under a lambda (or an application, for that matter). In the long term, we'd prefer to take the simplifier's approach instead: If we want to inline something because it only occurs once (even though it may be big), we add it to the substitution //before// simplifying it so that we only simplify it once. This means the substitution has to carry lexical closures around, though, just like the simplifier does (see SimplSR's ContEx disjunct), so it's not trivial.
The simpleOptPgm β-redexes are the only reason for the special rule in Core Lint (see Note [Beta redexes] in CoreLint.hs), so once this is done we can be rid of that.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |