%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[FloatOut]{Float bindings outwards (towards the top level)}
``Long-distance'' floating of bindings towards the top level.
\begin{code}
-#include "HsVersions.h"
-
module FloatOut ( floatOutwards ) where
-IMPORT_Trace -- ToDo: rm (debugging)
-import Pretty
-import Outputable
+#include "HsVersions.h"
-import PlainCore
+import CoreSyn
+import CoreUtils ( mkSCC )
-import BasicLit ( BasicLit(..), PrimKind )
-import CmdLineOpts ( GlobalSwitch(..) )
+import CmdLineOpts ( DynFlags, DynFlag(..), dopt )
+import ErrUtils ( dumpIfSet_dyn )
import CostCentre ( dupifyCC, CostCentre )
-import SetLevels
-import Id ( eqId )
-import IdEnv
-import Maybes ( Maybe(..), catMaybes, maybeToBool )
-import SplitUniq
-import Util
+import Id ( Id )
+import VarEnv
+import CoreLint ( beginPass, endPass )
+import SetLevels ( setLevels,
+ Level(..), tOP_LEVEL, ltMajLvl, ltLvl, isTopLvl
+ )
+import UniqSupply ( UniqSupply )
+import List ( partition )
+import Outputable
\end{code}
Random comments
~~~~~~~~~~~~~~~
-At the moment we never float a binding out to between two adjacent lambdas. For
-example:
+
+At the moment we never float a binding out to between two adjacent
+lambdas. For example:
+
@
\x y -> let t = x+x in ...
===>
\x -> let t = x+x in \y -> ...
@
-Reason: this is less efficient in the case where the original lambda is
-never partially applied.
+Reason: this is less efficient in the case where the original lambda
+is never partially applied.
But there's a case I've seen where this might not be true. Consider:
@
@
\deq x ys -> let eq = eqFromEqDict deq in ...
@
-which might usefully be separated to
+vwhich might usefully be separated to
@
\deq -> let eq = eqFromEqDict deq in \xy -> ...
@
Well, maybe. We don't do this at the moment.
-
\begin{code}
-type LevelledExpr = CoreExpr (Id, Level) Id
-type LevelledBind = CoreBinding (Id, Level) Id
-type FloatingBind = (Level, Floater)
-type FloatingBinds = [FloatingBind]
-
-data Floater = LetFloater PlainCoreBinding
-
- | CaseFloater (PlainCoreExpr -> PlainCoreExpr)
- -- Give me a right-hand side of the
- -- (usually single) alternative, and
- -- I'll build the case
+type LevelledExpr = TaggedExpr Level
+type LevelledBind = TaggedBind Level
+type FloatBind = (Level, CoreBind)
+type FloatBinds = [FloatBind]
\end{code}
%************************************************************************
%************************************************************************
\begin{code}
-floatOutwards :: (GlobalSwitch -> Bool) -- access to all global cmd-line opts
- -> SplitUniqSupply
- -> PlainCoreProgram
- -> PlainCoreProgram
-
-floatOutwards sw_chker us pgm
- = case (setLevels pgm sw_chker us) of { annotated_w_levels ->
-
- case unzip3 (map (floatTopBind sw_chker) annotated_w_levels)
- of { (fcs, lcs, final_toplev_binds_s) ->
-
- (if sw_chker D_verbose_core2core
- then pprTrace "Levels added:\n" (ppr PprDebug annotated_w_levels)
- else id
- )
- ( if sw_chker D_simplifier_stats
- then pprTrace "FloatOut stats: " (ppBesides [
- ppInt (sum fcs), ppStr " Lets floated out of ",
- ppInt (sum lcs), ppStr " Lambdas"])
- else id
- )
- concat final_toplev_binds_s
- }}
+floatOutwards :: DynFlags
+ -> Bool -- True <=> float lambdas to top level
+ -> UniqSupply
+ -> [CoreBind] -> IO [CoreBind]
+
+floatOutwards dflags float_lams us pgm
+ = do {
+ beginPass dflags float_msg ;
+
+ let { annotated_w_levels = setLevels float_lams pgm us ;
+ (fss, binds_s') = unzip (map floatTopBind annotated_w_levels)
+ } ;
-floatTopBind sw bind@(CoNonRec _ _)
- = case (floatBind sw nullIdEnv tOP_LEVEL bind) of { (fc,lc, floats, bind', _) ->
- (fc,lc, floatsToBinds floats ++ [bind'])
+ dumpIfSet_dyn dflags Opt_D_verbose_core2core "Levels added:"
+ (vcat (map ppr annotated_w_levels));
+
+ let { (tlets, ntlets, lams) = get_stats (sum_stats fss) };
+
+ dumpIfSet_dyn dflags Opt_D_dump_simpl_stats "FloatOut stats:"
+ (hcat [ int tlets, ptext SLIT(" Lets floated to top level; "),
+ int ntlets, ptext SLIT(" Lets floated elsewhere; from "),
+ int lams, ptext SLIT(" Lambda groups")]);
+
+ endPass dflags float_msg
+ (dopt Opt_D_verbose_core2core dflags)
+ {- no specific flag for dumping float-out -}
+ (concat binds_s')
}
+ where
+ float_msg | float_lams = "Float out (floating lambdas too)"
+ | otherwise = "Float out (not floating lambdas)"
-floatTopBind sw bind@(CoRec _)
- = case (floatBind sw nullIdEnv tOP_LEVEL bind) of { (fc,lc, floats, CoRec pairs', _) ->
+floatTopBind bind@(NonRec _ _)
+ = case (floatBind emptyVarEnv tOP_LEVEL bind) of { (fs, floats, bind', _) ->
+ (fs, floatsToBinds floats ++ [bind'])
+ }
+
+floatTopBind bind@(Rec _)
+ = case (floatBind emptyVarEnv tOP_LEVEL bind) of { (fs, floats, Rec pairs', _) ->
-- Actually floats will be empty
--false:ASSERT(null floats)
- (fc,lc, [CoRec (floatsToBindPairs floats ++ pairs')])
+ (fs, [Rec (floatsToBindPairs floats ++ pairs')])
}
\end{code}
\begin{code}
-floatBind :: (GlobalSwitch -> Bool)
- -> IdEnv Level
+floatBind :: IdEnv Level
-> Level
-> LevelledBind
- -> (Int,Int, FloatingBinds, PlainCoreBinding, IdEnv Level)
-
-floatBind sw env lvl (CoNonRec (name,level) rhs)
- = case (floatExpr sw env level rhs) of { (fc,lc, rhs_floats, rhs') ->
+ -> (FloatStats, FloatBinds, CoreBind, IdEnv Level)
- -- A good dumping point
- case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
+floatBind env lvl (NonRec (name,level) rhs)
+ = case (floatRhs env level rhs) of { (fs, rhs_floats, rhs') ->
+ (fs, rhs_floats,
+ NonRec name rhs',
+ extendVarEnv env name level)
+ }
- (fc,lc, rhs_floats',CoNonRec name (install heres rhs'), addOneToIdEnv env name level)
- }}
-
-floatBind sw env lvl bind@(CoRec pairs)
- = case (unzip4 (map do_pair pairs)) of { (fcs,lcs, rhss_floats, new_pairs) ->
+floatBind env lvl bind@(Rec pairs)
+ = case (unzip3 (map do_pair pairs)) of { (fss, rhss_floats, new_pairs) ->
if not (isTopLvl bind_level) then
-- Standard case
- (sum fcs,sum lcs, concat rhss_floats, CoRec new_pairs, new_env)
+ (sum_stats fss, concat rhss_floats, Rec new_pairs, new_env)
else
- {- In a recursive binding, destined for the top level (only),
- the rhs floats may contain
+ {- In a recursive binding, destined for the top level (only),
+ the rhs floats may contain
references to the bound things. For example
f = ...(let v = ...f... in b) ...
v = ...f...
f = ... b ...
- and hence we must (pessimistically) make all the floats recursive
+ and hence we must (pessimistically) make all the floats recursive
with the top binding. Later dependency analysis will unravel it.
-}
- (sum fcs,sum lcs, [],
- CoRec (new_pairs ++ floatsToBindPairs (concat rhss_floats)),
+ (sum_stats fss,
+ [],
+ Rec (new_pairs ++ floatsToBindPairs (concat rhss_floats)),
new_env)
}
where
- new_env = growIdEnvList env (map fst pairs)
+ new_env = extendVarEnvList env (map fst pairs)
bind_level = getBindLevel bind
do_pair ((name, level), rhs)
- = case (floatExpr sw new_env level rhs) of { (fc,lc, rhs_floats, rhs') ->
-
- -- A good dumping point
- case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
-
- (fc,lc, rhs_floats', (name, install heres rhs'))
- }}
+ = case (floatRhs new_env level rhs) of { (fs, rhs_floats, rhs') ->
+ (fs, rhs_floats, (name, rhs'))
+ }
\end{code}
%************************************************************************
%************************************************************************
\begin{code}
-floatExpr :: (GlobalSwitch -> Bool)
- -> IdEnv Level
- -> Level
- -> LevelledExpr
- -> (Int,Int, FloatingBinds, PlainCoreExpr)
-
-floatExpr sw env _ (CoVar v) = (0,0, [], CoVar v)
-
-floatExpr sw env _ (CoLit l) = (0,0, [], CoLit l)
-
-floatExpr sw env _ (CoPrim op ty as) = (0,0, [], CoPrim op ty as)
-floatExpr sw env _ (CoCon con ty as) = (0,0, [], CoCon con ty as)
-
-floatExpr sw env lvl (CoApp e a)
- = case (floatExpr sw env lvl e) of { (fc,lc, floating_defns, e') ->
- (fc,lc, floating_defns, CoApp e' a) }
-
-floatExpr sw env lvl (CoTyApp e ty)
- = case (floatExpr sw env lvl e) of { (fc,lc, floating_defns, e') ->
- (fc,lc, floating_defns, CoTyApp e' ty) }
-
-floatExpr sw env lvl (CoTyLam tv e)
- = let
- incd_lvl = incMinorLvl lvl
- in
- case (floatExpr sw env incd_lvl e) of { (fc,lc, floats, e') ->
+floatExpr, floatRhs
+ :: IdEnv Level
+ -> Level
+ -> LevelledExpr
+ -> (FloatStats, FloatBinds, CoreExpr)
+
+floatRhs env lvl arg
+ = case (floatExpr env lvl arg) of { (fsa, floats, arg') ->
+ case (partitionByMajorLevel lvl floats) of { (floats', heres) ->
+ -- Dump bindings that aren't going to escape from a lambda
+ -- This is to avoid floating the x binding out of
+ -- f (let x = e in b)
+ -- unnecessarily. It even causes a bug to do so if we have
+ -- y = writeArr# a n (let x = e in b)
+ -- because the y binding is an expr-ok-for-speculation one.
+ (fsa, floats', install heres arg') }}
+
+floatExpr env _ (Var v) = (zeroStats, [], Var v)
+floatExpr env _ (Type ty) = (zeroStats, [], Type ty)
+floatExpr env _ (Lit lit) = (zeroStats, [], Lit lit)
+
+floatExpr env lvl (App e a)
+ = case (floatExpr env lvl e) of { (fse, floats_e, e') ->
+ case (floatRhs env lvl a) of { (fsa, floats_a, a') ->
+ (fse `add_stats` fsa, floats_e ++ floats_a, App e' a') }}
+
+floatExpr env lvl (Lam (tv,incd_lvl) e)
+ | isTyVar tv
+ = case (floatExpr env incd_lvl e) of { (fs, floats, e') ->
-- Dump any bindings which absolutely cannot go any further
case (partitionByLevel incd_lvl floats) of { (floats', heres) ->
- (fc,lc, floats', CoTyLam tv (install heres e'))
+ (fs, floats', Lam tv (install heres e'))
}}
-floatExpr sw env lvl (CoLam args@((_,incd_lvl):_) rhs)
- = let
- args' = map fst args
- new_env = growIdEnvList env args
+floatExpr env lvl (Lam (arg,incd_lvl) rhs)
+ = ASSERT( isId arg )
+ let
+ new_env = extendVarEnv env arg incd_lvl
in
- case (floatExpr sw new_env incd_lvl rhs) of { (fc,lc, floats, rhs') ->
+ case (floatExpr new_env incd_lvl rhs) of { (fs, floats, rhs') ->
-- Dump any bindings which absolutely cannot go any further
case (partitionByLevel incd_lvl floats) of { (floats', heres) ->
- (fc + length floats', lc + 1,
- floats', mkCoLam args' (install heres rhs'))
+ (add_to_stats fs floats',
+ floats',
+ Lam arg (install heres rhs'))
}}
-floatExpr sw env lvl (CoSCC cc expr)
- = case (floatExpr sw env lvl expr) of { (fc,lc, floating_defns, expr') ->
+floatExpr env lvl (Note note@(SCC cc) expr)
+ = case (floatExpr env lvl expr) of { (fs, floating_defns, expr') ->
let
- -- annotate bindings floated outwards past an scc expression
+ -- Annotate bindings floated outwards past an scc expression
-- with the cc. We mark that cc as "duplicated", though.
annotated_defns = annotate (dupifyCC cc) floating_defns
in
- (fc,lc, annotated_defns, CoSCC cc expr') }
+ (fs, annotated_defns, Note note expr') }
where
- annotate :: CostCentre -> FloatingBinds -> FloatingBinds
+ annotate :: CostCentre -> FloatBinds -> FloatBinds
annotate dupd_cc defn_groups
= [ (level, ann_bind floater) | (level, floater) <- defn_groups ]
where
- ann_bind (LetFloater (CoNonRec binder rhs))
- = LetFloater (CoNonRec binder (ann_rhs rhs))
-
- ann_bind (LetFloater (CoRec pairs))
- = LetFloater (CoRec [(binder, ann_rhs rhs) | (binder, rhs) <- pairs])
+ ann_bind (NonRec binder rhs)
+ = NonRec binder (mkSCC dupd_cc rhs)
+
+ ann_bind (Rec pairs)
+ = Rec [(binder, mkSCC dupd_cc rhs) | (binder, rhs) <- pairs]
+
+-- At one time I tried the effect of not float anything out of an InlineMe,
+-- but it sometimes works badly. For example, consider PrelArr.done. It
+-- has the form __inline (\d. e)
+-- where e doesn't mention d. If we float this to
+-- __inline (let x = e in \d. x)
+-- things are bad. The inliner doesn't even inline it because it doesn't look
+-- like a head-normal form. So it seems a lesser evil to let things float.
+-- In SetLevels we do set the context to (Level 0 0) when we get to an InlineMe
+-- which discourages floating out.
+
+floatExpr env lvl (Note note expr) -- Other than SCCs
+ = case (floatExpr env lvl expr) of { (fs, floating_defns, expr') ->
+ (fs, floating_defns, Note note expr') }
+
+floatExpr env lvl (Let bind body)
+ = case (floatBind env lvl bind) of { (fsb, rhs_floats, bind', new_env) ->
+ case (floatExpr new_env lvl body) of { (fse, body_floats, body') ->
+ (add_stats fsb fse,
+ rhs_floats ++ [(bind_lvl, bind')] ++ body_floats,
+ body')
+ }}
+ where
+ bind_lvl = getBindLevel bind
- ann_bind (CaseFloater fn) = CaseFloater ( \ rhs -> CoSCC dupd_cc (fn rhs) )
+floatExpr env lvl (Case scrut (case_bndr, case_lvl) alts)
+ = case floatExpr env lvl scrut of { (fse, fde, scrut') ->
+ case floatList float_alt alts of { (fsa, fda, alts') ->
+ (add_stats fse fsa, fda ++ fde, Case scrut' case_bndr alts')
+ }}
+ where
+ alts_env = extendVarEnv env case_bndr case_lvl
- ann_rhs (CoLam args e) = CoLam args (ann_rhs e)
- ann_rhs (CoTyLam tv e) = CoTyLam tv (ann_rhs e)
- ann_rhs rhs@(CoCon _ _ _)= rhs -- no point in scc'ing WHNF data
- ann_rhs rhs = CoSCC dupd_cc rhs
+ partition_fn = partitionByMajorLevel
- -- Note: Nested SCC's are preserved for the benefit of
- -- cost centre stack profiling (Durham)
+ float_alt (con, bs, rhs)
+ = let
+ bs' = map fst bs
+ new_env = extendVarEnvList alts_env bs
+ in
+ case (floatExpr new_env case_lvl rhs) of { (fs, rhs_floats, rhs') ->
+ case (partition_fn case_lvl rhs_floats) of { (rhs_floats', heres) ->
+ (fs, rhs_floats', (con, bs', install heres rhs')) }}
-floatExpr sw env lvl (CoLet bind body)
- = case (floatBind sw env lvl bind) of { (fcb,lcb, rhs_floats, bind', new_env) ->
- case (floatExpr sw new_env lvl body) of { (fce,lce, body_floats, body') ->
- (fcb + fce, lcb + lce,
- rhs_floats ++ [(bind_lvl, LetFloater bind')] ++ body_floats, body')
- }}
- where
- bind_lvl = getBindLevel bind
-floatExpr sw env lvl (CoCase scrut alts)
- = case (floatExpr sw env lvl scrut) of { (fce,lce, fde, scrut') ->
+floatList :: (a -> (FloatStats, FloatBinds, b)) -> [a] -> (FloatStats, FloatBinds, [b])
+floatList f [] = (zeroStats, [], [])
+floatList f (a:as) = case f a of { (fs_a, binds_a, b) ->
+ case floatList f as of { (fs_as, binds_as, bs) ->
+ (fs_a `add_stats` fs_as, binds_a ++ binds_as, b:bs) }}
+\end{code}
- case (scrut', float_alts alts) of
+%************************************************************************
+%* *
+\subsection{Utility bits for floating stats}
+%* *
+%************************************************************************
-{- CASE-FLOATING DROPPED FOR NOW. (SLPJ 7/2/94)
+I didn't implement this with unboxed numbers. I don't want to be too
+strict in this stuff, as it is rarely turned on. (WDP 95/09)
- (CoVar scrut_var, (fda, CoAlgAlts [(con,bs,rhs')] CoNoDefault))
- | scrut_var_lvl `ltMajLvl` lvl ->
+\begin{code}
+data FloatStats
+ = FlS Int -- Number of top-floats * lambda groups they've been past
+ Int -- Number of non-top-floats * lambda groups they've been past
+ Int -- Number of lambda (groups) seen
- -- Candidate for case floater; scrutinising a variable; it can
- -- escape outside a lambda; there's only one alternative.
- (fda ++ fde ++ [case_floater], rhs')
+get_stats (FlS a b c) = (a, b, c)
- where
- case_floater = (scrut_var_lvl, CaseFloater fn)
- fn body = CoCase scrut' (CoAlgAlts [(con,bs,body)] CoNoDefault)
- scrut_var_lvl = case lookupIdEnv env scrut_var of
- Nothing -> Level 0 0
- Just lvl -> unTopify lvl
+zeroStats = FlS 0 0 0
- END OF CASE FLOATING DROPPED -}
+sum_stats xs = foldr add_stats zeroStats xs
- (_, (fca,lca, fda, alts')) ->
+add_stats (FlS a1 b1 c1) (FlS a2 b2 c2)
+ = FlS (a1 + a2) (b1 + b2) (c1 + c2)
- (fce + fca, lce + lca, fda ++ fde, CoCase scrut' alts')
- }
+add_to_stats (FlS a b c) floats
+ = FlS (a + length top_floats) (b + length other_floats) (c + 1)
where
- incd_lvl = incMinorLvl lvl
+ (top_floats, other_floats) = partition to_very_top floats
- partition_fn = partitionByMajorLevel
-
-{- OMITTED
- We don't want to be too keen about floating lets out of case alternatives
- because they may benefit from seeing the evaluation done by the case.
-
- The main reason for doing this is to allocate in fewer larger blocks
- but that's really an STG-level issue.
-
- case alts of
- -- Just one alternative, then dump only
- -- what *has* to be dumped
- CoAlgAlts [_] CoNoDefault -> partitionByLevel
- CoAlgAlts [] (CoBindDefault _ _) -> partitionByLevel
- CoPrimAlts [_] CoNoDefault -> partitionByLevel
- CoPrimAlts [] (CoBindDefault _ _) -> partitionByLevel
-
- -- If there's more than one alternative, then
- -- this is a dumping point
- other -> partitionByMajorLevel
--}
-
- float_alts (CoAlgAlts alts deflt)
- = case (float_deflt deflt) of { (fcd,lcd, fdd, deflt') ->
- case (unzip4 (map float_alg_alt alts)) of { (fcas,lcas, fdas, alts') ->
- (fcd + sum fcas, lcd + sum lcas,
- concat fdas ++ fdd, CoAlgAlts alts' deflt') }}
-
- float_alts (CoPrimAlts alts deflt)
- = case (float_deflt deflt) of { (fcd,lcd, fdd, deflt') ->
- case (unzip4 (map float_prim_alt alts)) of { (fcas,lcas, fdas, alts') ->
- (fcd + sum fcas, lcd + sum lcas,
- concat fdas ++ fdd, CoPrimAlts alts' deflt') }}
-
- -------------
- float_alg_alt (con, bs, rhs)
- = let
- bs' = map fst bs
- new_env = growIdEnvList env bs
- in
- case (floatExpr sw new_env incd_lvl rhs) of { (fc,lc, rhs_floats, rhs') ->
- case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
- (fc, lc, rhs_floats', (con, bs', install heres rhs'))
- }}
-
- --------------
- float_prim_alt (lit, rhs)
- = case (floatExpr sw env incd_lvl rhs) of { (fc,lc, rhs_floats, rhs') ->
- case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
- (fc,lc, rhs_floats', (lit, install heres rhs'))
- }}
-
- --------------
- float_deflt CoNoDefault = (0,0, [], CoNoDefault)
-
- float_deflt (CoBindDefault (b,lvl) rhs)
- = case (floatExpr sw new_env lvl rhs) of { (fc,lc, rhs_floats, rhs') ->
- case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
- (fc,lc, rhs_floats', CoBindDefault b (install heres rhs'))
- }}
- where
- new_env = addOneToIdEnv env b lvl
+ to_very_top (my_lvl, _) = isTopLvl my_lvl
\end{code}
+
%************************************************************************
%* *
-\subsection[FloatOut-utils]{Utility bits for floating}
+\subsection{Utility bits for floating}
%* *
%************************************************************************
\begin{code}
-getBindLevel (CoNonRec (_, lvl) _) = lvl
-getBindLevel (CoRec (((_,lvl), _) : _)) = lvl
+getBindLevel (NonRec (_, lvl) _) = lvl
+getBindLevel (Rec (((_,lvl), _) : _)) = lvl
\end{code}
\begin{code}
partitionByMajorLevel, partitionByLevel
:: Level -- Partitioning level
- -> FloatingBinds -- Defns to be divided into 2 piles...
+ -> FloatBinds -- Defns to be divided into 2 piles...
- -> (FloatingBinds, -- Defns with level strictly < partition level,
- FloatingBinds) -- The rest
+ -> (FloatBinds, -- Defns with level strictly < partition level,
+ FloatBinds) -- The rest
-partitionByMajorLevel ctxt_lvl defns
+partitionByMajorLevel ctxt_lvl defns
= partition float_further defns
where
- float_further (my_lvl, _) = my_lvl `ltMajLvl` ctxt_lvl ||
- isTopLvl my_lvl
+ -- Float it if we escape a value lambda,
+ -- or if we get to the top level
+ float_further (my_lvl, bind) = my_lvl `ltMajLvl` ctxt_lvl || isTopLvl my_lvl
+ -- The isTopLvl part says that if we can get to the top level, say "yes" anyway
+ -- This means that
+ -- x = f e
+ -- transforms to
+ -- lvl = e
+ -- x = f lvl
+ -- which is as it should be
partitionByLevel ctxt_lvl defns
= partition float_further defns
\end{code}
\begin{code}
-floatsToBinds :: FloatingBinds -> [PlainCoreBinding]
-floatsToBinds floats = map get_bind floats
- where
- get_bind (_, LetFloater bind) = bind
- get_bind (_, CaseFloater _) = panic "floatsToBinds"
+floatsToBinds :: FloatBinds -> [CoreBind]
+floatsToBinds floats = map snd floats
-floatsToBindPairs :: FloatingBinds -> [(Id,PlainCoreExpr)]
+floatsToBindPairs :: FloatBinds -> [(Id,CoreExpr)]
floatsToBindPairs floats = concat (map mk_pairs floats)
where
- mk_pairs (_, LetFloater (CoRec pairs)) = pairs
- mk_pairs (_, LetFloater (CoNonRec binder rhs)) = [(binder,rhs)]
- mk_pairs (_, CaseFloater _) = panic "floatsToBindPairs"
+ mk_pairs (_, Rec pairs) = pairs
+ mk_pairs (_, NonRec binder rhs) = [(binder,rhs)]
-install :: FloatingBinds -> PlainCoreExpr -> PlainCoreExpr
+install :: FloatBinds -> CoreExpr -> CoreExpr
install defn_groups expr
= foldr install_group expr defn_groups
where
- install_group (_, LetFloater defns) body = CoLet defns body
- install_group (_, CaseFloater fn) body = fn body
+ install_group (_, defns) body = Let defns body
\end{code}