[GHC] #12618: Add saturated constructor applications to Core

GHC ghc-devs at haskell.org
Mon Oct 24 14:56:05 UTC 2016


#12618: Add saturated constructor applications to Core
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  nomeata
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by nomeata):

 Allright, it is done, and I can report back.

 Introducing `ConApp` (without any compression) was quite tedious, and for
 me, rather two than one week. By now, it validates (almost; the GHCi
 debugger shows some difference in behaviour that I did not investigate)
 and shows the same runtime performance.

 The most tricky points are related to rules, which really do not like it
 if eta-expansion changes the Core too much. It took me a while to get
 equivalent program output after this refactoring (and I took a shortcut
 for now, duplicating some list fusion rules that match `build (:)` to have
 a second variant matching `build (\x y -> x : y)`). With a bit more
 careful work, this could be fixed, should we want this code to be merged.

 This change on its own affected some compiler perf benchmarks in the test
 suite: T9961 improves by 13%, T9233 by 2.5%., T9020 by 2.5%. T4801
 regresses by 3.87% (bytes allocated)

 I then, in a separate patch, implemented omitting redundant type arguments
 from constructors such as `Just`, `(:)` and tuples, which was the main
 motivation here. At every use of `ConApp`, I tried to understand the code
 as to whether it actually cares about the type arguments (which means that
 the they need to be recovered) or not (in which case the compressed
 argument list can be traversed, which is of course more efficient).

 In these places I had to uncompress the type arguments:

 * `freeVars` (which also calculates the types)
 * The linter
 * `cpeRhsE`
 * `exprIsConApp_maybe`
 * `exprType`
 * `collectStaticPtrSatArgs`, `sptModuleInitCode` (all about static pointer
 tables)
 * `decomposeRuleLhs` in the desugarer
 * `toIfaceExpr` when serializing tuples (low-hanging fruit here)
 * `match_magicDict`
 * `occAnal`
 * `simplExprF1`
 * `isValue` is `specConstr`

 I found that it is crucial to analyze the type of the data constructor
 only once, and store the “compression scheme” (i.e. which type arguments
 to recover form which term arguments) once in the data constructor, as
 this analysis is not completely cheap.

 But even with this optimization in place, the effect of this is –
 neglectible.

 My gut feeling:
 * `ConApp` is not a good idea in this form. Constructor applications are
 still just applications, and treating them that separately is not going to
 be healthy. It might be a better idea to make ''all'' applications
 saturated (as in strict core, or less invasive, “spotty types”).
 * The compression scheme is nice in principle, but there are still too
 many code paths that want the types. Some might be taken off the list
 after careful analysis of the code and mild refactoring. In others, making
 sure that the type in a `Type` data constructor is used as lazily as
 possible might help avoiding actually running `exprType` (this is a blind
 guess).
 * Furthermore, the large types that occur with nested tuples are already
 in the type checker! So avoiding them in Core is only half the story.
 * If compression would make a difference, then I think we want it at all
 applications (or at least applications headed by an `Id`, where we could
 store the compression scheme). Another point in favor of making all
 applications saturated.

 As for the problem of nested tuples: Maybe it would have been better to
 first carefully analyze the compiler (using `-v`/profiling/ticky-ticky) to
 be sure where we pay the unwanted cost (type checking, Core, interfaces,
 somewhere else) to know what we have to fix, before having a shot at one
 assumed cause.

 The code is at Phab:D2564.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12618#comment:36>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list