[project @ 2003-09-23 15:29:02 by simonpj]
--------------------------
Much grunting about let-floating
--------------------------
We want to avoid putting bindings between the '=' of a defn and a '\':
let { f = let ... in \y-> ... } in ...
Reason: float-in often follows float-out, and it may then add yte
more bindings there, some of which may be strict. But f may by
not be marked as not-demanded (for other reasons: see the call to
zapDemandInfo in Simplify.completeLazyBind); and now the strict binding
may not be able to float out again. (Well, it triggers the ASSERT in
simplLazyBind.)
So this commit adds FloatOut.floatNonRecRhs (to complement floatRhs) which
is a big more vigorous about floating out.
But that in turn showed up a pile of gore to do with unlifted bindings.
We can't have them showing up at top level. After thrashing in the swamp
for a while, I eventually arranged that
let x# = e in b
(where x# has an unlifted type) is treated exactly like
case e of x# -> b
That is, it is never floated. Yes, we lose opportunities to float some
(very cheap! unlifted let-bindings are always cheap) out of a lambda,
but we're missing much bigger opportunities already. For example:
\x -> f (h y)
where h :: Int -> Int# is expensive. We'd like to float the (h y) outside
the \x, but we don't because it's unboxed. Possible solution: box it.
Anyway, that's for the future.