-- 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 []
(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),
res = case resexpr of
(Var x) -> x
_ -> error $ "Normalize.splitNormalized: Not in normal form: " ++ pprString expr ++ "\n"
-
--- | Flattens nested lets into a single list of bindings. The expression
--- passed does not have to be a let expression, if it isn't an empty list of
--- bindings is returned.
-flattenLets ::
- CoreExpr -- ^ The expression to flatten.
- -> ([Binding], CoreExpr) -- ^ The bindings and resulting expression.
-flattenLets (Let binds expr) =
- (bindings ++ bindings', expr')
- where
- -- Recursively flatten the contained expression
- (bindings', expr') =flattenLets expr
- -- Flatten our own bindings to remove the Rec / NonRec constructors
- bindings = CoreSyn.flattenBinds [binds]
-flattenLets expr = ([], expr)