-- 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
-- Unused let binding removal
--------------------------------
letremoveunused, letremoveunusedtop :: Transform
-letremoveunused expr@(Let (Rec binds) res) = do
+letremoveunused expr@(Let _ _) = do
-- Filter out all unused binds.
let binds' = filter dobind binds
-- Only set the changed flag if binds got removed
- changeif (length binds' /= length binds) (Let (Rec binds') res)
+ changeif (length binds' /= length binds) (mkNonRecLets binds' res)
where
+ (binds, res) = flattenLets expr
bound_exprs = map snd binds
-- For each bind check if the bind is used by res or any of the bound
-- expressions
letmerge expr@(Let _ _) = do
let (binds, res) = flattenLets expr
binds' <- domerge binds
- return $ MkCore.mkCoreLets (map (uncurry NonRec) binds') res
+ return $ mkNonRecLets binds' res
where
domerge :: [(CoreBndr, CoreExpr)] -> TransformMonad [(CoreBndr, CoreExpr)]
domerge [] = return []
(bindingss, alts') <- (Monad.liftM unzip) $ mapM doalt alts
let bindings = concat bindingss
-- Replace the case with a let with bindings and a case
- let newlet = (Let (Rec bindings) (Case scrut b ty alts'))
+ let newlet = mkNonRecLets bindings (Case scrut b ty alts')
-- If there are no non-wild binders, or this case is already a simple
-- selector (i.e., a single alt with exactly one binding), already a simple
-- selector altan no bindings (i.e., no wild binders in the original case),