-- Nothing is liftable, just return
[] -> return expr
-- Something can be lifted, generate a new let expression
- _ -> change $ MkCore.mkCoreLets newbinds res
+ _ -> change $ mkNonRecLets liftable (Let (Rec nonliftable) res)
where
-- Make a list of all the binders bound in this recursive let
bndrs = map fst binds
-- See which bindings are liftable
(liftable, nonliftable) = List.partition canlift binds
- -- Create nonrec bindings for each liftable binding and a single recursive
- -- binding for all others
- newbinds = (map (uncurry NonRec) liftable) ++ [Rec nonliftable]
-- Any expression that does not use any of the binders in this recursive let
-- can be lifted into a nonrec let. It can't use its own binder either,
-- since that would mean the binding is self-recursive and should be in a
-- TODO: We would very much like to use GHC's CSE module for this, but that
-- doesn't track if something changed or not, so we can't use it properly.
letmerge, letmergetop :: Transform
-letmerge expr@(Let (Rec binds) res) = do
+letmerge expr@(Let _ _) = do
+ let (binds, res) = flattenLets expr
binds' <- domerge binds
- return (Let (Rec binds') res)
+ return $ mkNonRecLets binds' res
where
domerge :: [(CoreBndr, CoreExpr)] -> TransformMonad [(CoreBndr, CoreExpr)]
domerge [] = return []