
#15192: Refactor of Coercion -------------------------------------+------------------------------------- Reporter: ningning | Owner: ningning Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D4747 Wiki Page: | -------------------------------------+------------------------------------- Comment (by ningning): Replying to [comment:25 simonpj]:
Ningning, let me check my understanding
* In HEAD we have `GRefl` but not `CoherenceCo`
* In EXPERIMENT you added `CoherenceCo` and used it.
* You found that EXPERIMENT allocated up to 2.5% less.
Right so far?
The change of {{{homogenise_result}}} saves ~2.5%. With more similar changes the allocation could become fewer. For example, a similar change in {{{TcFlatten.flatten_args_slow}}} (use {{{mkTcCoherenceLeftCo'}}} instead of {{{mkTcCoherenceLeftCo}}} saves ~1% in T9872d. Namely, if we combine those two changes, it saves ~3.5%. Changes in other places does not have a significant result in T9872d though.
What are the costs of EXPERIMENT?
* The extra constructor in Coercion, and extra cases in free-vars, substitution, pretty-printing etc.
* Extra stuff in `OptCoercion`, I assume. This is already a very tricky module, so may be the biggest cost.
Is that all?
Extra stuff in the compilation pipeline, including {{{Coercion}}}, {{{OptCoercion}}}, {{{CoreLint}}}, {{{Ifacexxx}}} etc. Basically I recovered everything I have removed of {{{CoherenceCo}}} in previous commit. Except that, I added nothing new.
Other thoughts
* I recall that `CoerherenceCo` was biased to the laft. One could add a right-biased version too -- would that help even more?
I don't know the answer for sure. But I guess not. As {{{mkCoherenceRightCo}}} differs from {{{CoherenceCo}}} only by 2 {{{SymCo}}}, which won' save much I presume. In contrast, the {{{GRefl}}}-version of {{{mkCoherenceLeftCo}}} differs from {{{CoherenceCo}}}-version of {{{mkCoherenceLeftCo'}}} by a whole type, and the type can be large.
* Are you implicitly advocating adding `CoherenceCo` not for expressiveness but for efficiency? And if so, are there any other combinations of coercions that we could play a similar game with?
No I am not advocating addting `CoherenceCo` back. I don't know if it is worth it to add all those stuff for one particular test case. If we look through `Coercion.hs` in head, we can find that functions `mkCoherenceLeftCo` and `mkCoherenceRightCo` are utility functions that construct coercions and are used frequently but don't have their own constructor of coercion (namely, `CoherenceCo`). Other ones don't seem to need a new constructor. (`castCoercionKind` could be one, but I don't think it will benefit from a new constructor of coercion).
* I've noticed (in `tc_trace` printing) that we build a LOT of Refl coercions. Yet the `isGReflCo` case obviously doesn't fire, perhaps because the coercion hasn't been zonked. Yet in fact `zonkTcType` ''does'' zonk coercions, so I'm a bit puzzled about why we get quite so many of them. There might be some low-hanging fruit in finding out why.
* In writing that comment I ''also'' realised that when zonking a type (with `zonkTcType`) we fully zonk all the coercions it mentions. I wonder if that is really necessary? That is, in `zonkTcType` could we simply not-zonk any coercions, just doing the latter when we do `zonkTcTypeToType`?
I am not familiar with the zonking process (yet). If there are some other ways to improve the performance that would be great. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15192#comment:26 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler