Commit 4539cb1b authored by simonpj@microsoft.com's avatar simonpj@microsoft.com
Browse files

Float casts out of lambdas

See Note [Casts and lambdas] in SimplUtils.  I found this transformation
when staring at some cast-heavy code generated by
Language.Haskell.Lexer.hs in the haskell-src library.

The basic transformation is this:
	(\x. e `cast` g1)  -->  (\x.e) `cast` (tx -> g1)
where x:tx.
parent 7f7b6cef
......@@ -804,6 +804,14 @@ mkLam bndrs body
= do { dflags <- getDOptsSmpl
; mkLam' dflags bndrs body }
where
mkLam' :: DynFlags -> [OutBndr] -> OutExpr -> SimplM OutExpr
mkLam' dflags bndrs (Cast body@(Lam _ _) co)
-- Note [Casts and lambdas]
= do { lam <- mkLam' dflags (bndrs ++ bndrs') body'
; return (mkCoerce (mkPiTypes bndrs co) lam) }
where
(bndrs',body') = collectBinders body
mkLam' dflags bndrs body
| dopt Opt_DoEtaReduction dflags,
Just etad_lam <- tryEtaReduce bndrs body
......@@ -819,6 +827,21 @@ mkLam bndrs body
= returnSmpl (mkLams bndrs body)
\end{code}
Note [Casts and lambdas]
~~~~~~~~~~~~~~~~~~~~~~~~
Consider
(\x. (\y. e) `cast` g1) `cast` g2
There is a danger here that the two lambdas look separated, and the
full laziness pass might float an expression to between the two.
So this equation in mkLam' floats the g1 out, thus:
(\x. e `cast` g1) --> (\x.e) `cast` (tx -> g1)
where x:tx.
In general, this floats casts outside lambdas, where (I hope) they might meet
and cancel with some other cast.
-- c) floating lets out through big lambdas
-- [only if all tyvar lambdas, and only if this lambda
-- is the RHS of a let]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment