So we must not change the arity of any top-level function,
because we've already fixed it and put it out into the interface file.
+ Nor must we change a value (e.g. constructor) into a thunk.
It's ok to introduce extra bindings, which don't appear in the
interface file. We don't put arity info on these extra bindings,
-> OrdList FloatingBind -> CoreExpr -- Rhs: let binds in body
-> UniqSM (OrdList FloatingBind)
mkNonRec bndr dem floats rhs
- | exprIsValue rhs -- Notably constructor applications
- = ASSERT( allLazy floats ) -- The only floats we can get out of a value are eta expansions
- -- e.g. C $wJust ==> let s = \x -> $wJust x in C s
- -- Here we want to float the s binding.
+ | exprIsValue rhs && allLazy floats -- Notably constructor applications
+ = -- Why the test for allLazy? You might think that the only
+ -- floats we can get out of a value are eta expansions
+ -- e.g. C $wJust ==> let s = \x -> $wJust x in C s
+ -- Here we want to float the s binding.
+ --
+ -- But if the programmer writes this:
+ -- f x = case x of { (a,b) -> \y -> a }
+ -- then the strictness analyser may say that f has strictness "S"
+ -- Later the eta expander will transform to
+ -- f x y = case x of { (a,b) -> a }
+ -- So now f has arity 2. Now CoreSat may see
+ -- v = f E
+ -- so the E argument will turn into a FloatCase.
+ -- Indeed we should end up with
+ -- v = case E of { r -> f r }
+ -- That is, we should not float, even though (f r) is a value
returnUs (floats `snocOL` FloatLet (NonRec bndr rhs))
| isUnLiftedType bndr_rep_ty || isStrictDem dem
deLam :: CoreExpr -> UniqSM CoreExpr
-- Remove top level lambdas by let-bindinig
+
+deLam (Note n expr)
+ = -- You can get things like
+ -- case e of { p -> coerce t (\s -> ...) }
+ deLam expr `thenUs` \ expr' ->
+ returnUs (Note n expr')
+
deLam expr
| null bndrs = returnUs expr
| otherwise = case tryEta bndrs body of
where
(bndrs,body) = collectBinders expr
+-- Why try eta reduction? Hasn't the simplifier already done eta?
+-- But the simplifier only eta reduces if that leaves something
+-- trivial (like f, or f Int). But for deLam it would be enough to
+-- get to a partial application, like (map f).
+
tryEta bndrs expr@(App _ _)
| ok_to_eta_reduce f &&
n_remaining >= 0 &&
safeDem = RhsDemand False False -- always safe to use this
onceDem = RhsDemand False True -- used at most once
\end{code}
+
+