Floating and CorePrep

Simon Peyton Jones simonpj at microsoft.com
Thu Oct 8 10:42:31 UTC 2015

Luke asks

| Also, can you explain why CorePrep does some floating of its own?

I thought that there was a good reason that CorePrep does floating, but
the more I tried to explain it, the less sense the explanation made. So
here's the reasoning.  Maybe I'm missing things, or maybe there's an
opportunity here to simplify GHC.  So I'm cc'ing ghc-devs.

CorePrep convets to ANF.  So if we have this: 
    x = f (g y)
we might naively generate this
	x = let a = g y in f a
Instead CorePrep generates this
	a = g y
	x = f a

However now I think about it again, I'm suddenly not sure why this is important.

* If x is a lazy thunk, the floated version will allocate 'a'
  early.  So we should only float if (f a) is a head-normal form.
  (And that happens; see CorePrep.wantFloatNested).  But if (f a)
  is a HNF, the simplifier will already have ANF'd it in prepareRhs.

* If x is marked demanded (strict), then the naive ANF'ing might
      case (let a = g y in f a) of ....
  because CorePrep converts the 'let x' into a case.  But that's
  OK because I think the code generator is fine with a let nested
  inside a case like that.

So, for nested bindings, maybe we can simply NEVER do floating?  Ah,
there is on gotcha.  Consider
   x = f raise#
where f has arity 2.  Currently raise# responds True to
Id.hasNoBinding, so CorePrep must eta-expand to
   x = f (\x. raise# x)
and now we really would like to ANF to
   z = \x. raise# x
   x = f a
because the (f a) is not a thunk, but it would be if we
introduced a nested let.  Bother.

For top level, things are slightly different.  Here if we see
   x = f (g y)
we do want to float to get
   a = g y
   x = f a
because not the allocation of 'a' is done statically rather than
dynamically.  This is particularly important for large static lists
   p = f [a,b,c,d,e]
when we want all those cons cells to be statically allocated.

This is all a bit unsatisfactory.  It would be much cleaner if
all floating was done by the simplifier, and CorePrep did none.

And I think it'd be worth a try at doing that.  I think the needful
stuff would be:

 * Always saturate hsaNoBinding functions in Core, not just at
 * Be more aggressive about floating top-level bindings like 'p'
   in the simplifier

I'm not likely to undertake this myself soon, but I could advise.


More information about the ghc-devs mailing list