2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section[SimplMonad]{The simplifier Monad}
8 InId, InBind, InExpr, InAlt, InArg, InType, InBinder,
9 OutId, OutTyVar, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBinder,
11 -- The simplifier mode
15 SwitchChecker, SwitchResult(..), getSwitchChecker, getSimplIntSwitch,
16 isAmongSimpl, intSwitchSet, switchIsOn,
18 setEnclosingCC, getEnclosingCC,
21 SimplEnv, mkSimplEnv, extendIdSubst, extendTvSubst,
22 zapSubstEnv, setSubstEnv,
23 getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds,
24 getRules, refineSimplEnv,
26 SimplSR(..), mkContEx, substId,
28 simplNonRecBndr, simplRecBndrs, simplLamBndr, simplLamBndrs,
29 simplBinder, simplBinders,
33 FloatsWith, FloatsWithExpr,
34 Floats, emptyFloats, isEmptyFloats, unitFloat, addFloats, flattenFloats,
35 allLifted, wrapFloats, floatBinds,
39 #include "HsVersions.h"
42 import Id ( Id, idType, idOccInfo, idUnfolding, setIdUnfolding )
43 import IdInfo ( IdInfo, vanillaIdInfo, occInfo, setOccInfo, specInfo, setSpecInfo,
44 arityInfo, setArityInfo, workerInfo, setWorkerInfo,
45 unfoldingInfo, setUnfoldingInfo, isEmptySpecInfo,
46 unknownArity, workerExists
49 import Unify ( TypeRefinement )
50 import Rules ( RuleBase )
51 import CoreUtils ( needsCaseBinding )
52 import CostCentre ( CostCentreStack, subsumedCCS )
55 import VarSet ( isEmptyVarSet )
58 import qualified CoreSubst ( Subst, mkSubst, substExpr, substSpec, substWorker )
59 import qualified Type ( substTy, substTyVarBndr )
61 import Type ( Type, TvSubst(..), TvSubstEnv, composeTvSubst,
62 isUnLiftedType, seqType, tyVarsOfType )
63 import BasicTypes ( OccInfo(..), isFragileOcc )
64 import DynFlags ( SimplifierMode(..) )
65 import Util ( mapAccumL )
69 %************************************************************************
71 \subsection[Simplify-types]{Type declarations}
73 %************************************************************************
76 type InBinder = CoreBndr
77 type InId = Id -- Not yet cloned
78 type InType = Type -- Ditto
79 type InBind = CoreBind
80 type InExpr = CoreExpr
84 type OutBinder = CoreBndr
85 type OutId = Id -- Cloned
86 type OutTyVar = TyVar -- Cloned
87 type OutType = Type -- Cloned
88 type OutBind = CoreBind
89 type OutExpr = CoreExpr
94 %************************************************************************
96 \subsubsection{The @SimplEnv@ type}
98 %************************************************************************
104 seMode :: SimplifierMode,
105 seChkr :: SwitchChecker,
106 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
108 -- Rules from other modules
109 seExtRules :: RuleBase,
111 -- The current set of in-scope variables
112 -- They are all OutVars, and all bound in this module
113 seInScope :: InScopeSet, -- OutVars only
115 -- The current substitution
116 seTvSubst :: TvSubstEnv, -- InTyVar |--> OutType
117 seIdSubst :: SimplIdSubst -- InId |--> OutExpr
120 type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
123 = DoneEx OutExpr -- Completed term
124 | DoneId OutId OccInfo -- Completed term variable, with occurrence info
125 | ContEx TvSubstEnv -- A suspended substitution
132 The in-scope part of Subst includes *all* in-scope TyVars and Ids
133 The elements of the set may have better IdInfo than the
134 occurrences of in-scope Ids, and (more important) they will
135 have a correctly-substituted type. So we use a lookup in this
136 set to replace occurrences
138 The Ids in the InScopeSet are replete with their Rules,
139 and as we gather info about the unfolding of an Id, we replace
140 it in the in-scope set.
142 The in-scope set is actually a mapping OutVar -> OutVar, and
143 in case expressions we sometimes bind
146 The substitution is *apply-once* only, because InIds and OutIds can overlap.
147 For example, we generally omit mappings
149 from the substitution, when we decide not to clone a77, but it's quite
150 legitimate to put the mapping in the substitution anyway.
152 Indeed, we do so when we want to pass fragile OccInfo to the
153 occurrences of the variable; we add a substitution
154 x77 -> DoneId x77 occ
155 to record x's occurrence information.]
157 Furthermore, consider
158 let x = case k of I# x77 -> ... in
159 let y = case k of I# x77 -> ... in ...
160 and suppose the body is strict in both x and y. Then the simplifier
161 will pull the first (case k) to the top; so the second (case k) will
162 cancel out, mapping x77 to, well, x77! But one is an in-Id and the
165 Of course, the substitution *must* applied! Things in its domain
166 simply aren't necessarily bound in the result.
168 * substId adds a binding (DoneId new_id occ) to the substitution if
169 EITHER the Id's unique has changed
170 OR the Id has interesting occurrence information
171 So in effect you can only get to interesting occurrence information
172 by looking up the *old* Id; it's not really attached to the new id
175 Note, though that the substitution isn't necessarily extended
176 if the type changes. Why not? Because of the next point:
178 * We *always, always* finish by looking up in the in-scope set
179 any variable that doesn't get a DoneEx or DoneVar hit in the substitution.
180 Reason: so that we never finish up with a "old" Id in the result.
181 An old Id might point to an old unfolding and so on... which gives a space leak.
183 [The DoneEx and DoneVar hits map to "new" stuff.]
185 * It follows that substExpr must not do a no-op if the substitution is empty.
186 substType is free to do so, however.
188 * When we come to a let-binding (say) we generate new IdInfo, including an
189 unfolding, attach it to the binder, and add this newly adorned binder to
190 the in-scope set. So all subsequent occurrences of the binder will get mapped
191 to the full-adorned binder, which is also the one put in the binding site.
193 * The in-scope "set" usually maps x->x; we use it simply for its domain.
194 But sometimes we have two in-scope Ids that are synomyms, and should
195 map to the same target: x->x, y->x. Notably:
197 That's why the "set" is actually a VarEnv Var
200 Note [GADT type refinement]
201 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
202 When we come to a GADT pattern match that refines the in-scope types, we
203 a) Refine the types of the Ids in the in-scope set, seInScope.
204 For exmaple, consider
206 Foo :: T (Bool -> Bool)
208 (\ (x::T a) (y::a) -> case x of { Foo -> y True }
210 Technically this is well-typed, but exprType will barf on the
211 (y True) unless we refine the type on y's occurrence.
213 b) Refine the range of the type substitution, seTvSubst.
214 Very similar reason to (a).
216 NB: we don't refine the range of the SimplIdSubst, because it's always
217 interpreted relative to the seInScope (see substId)
219 For (b) we need to be a little careful. Specifically, we compose the refinement
220 with the type substitution. Suppose
221 The substitution was [a->b, b->a]
222 and the refinement was [b->Int]
223 Then we want [a->Int, b->a]
226 The substitution was [a->b]
227 and the refinement was [b->Int]
228 Then we want [a->Int, b->Int]
229 becuase b might be both an InTyVar and OutTyVar
233 mkSimplEnv :: SimplifierMode -> SwitchChecker -> RuleBase -> SimplEnv
234 mkSimplEnv mode switches rules
235 = SimplEnv { seChkr = switches, seCC = subsumedCCS,
236 seMode = mode, seInScope = emptyInScopeSet,
238 seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv }
239 -- The top level "enclosing CC" is "SUBSUMED".
241 ---------------------
242 getSwitchChecker :: SimplEnv -> SwitchChecker
243 getSwitchChecker env = seChkr env
245 ---------------------
246 getMode :: SimplEnv -> SimplifierMode
247 getMode env = seMode env
249 setMode :: SimplifierMode -> SimplEnv -> SimplEnv
250 setMode mode env = env { seMode = mode }
252 ---------------------
253 getEnclosingCC :: SimplEnv -> CostCentreStack
254 getEnclosingCC env = seCC env
256 setEnclosingCC :: SimplEnv -> CostCentreStack -> SimplEnv
257 setEnclosingCC env cc = env {seCC = cc}
259 ---------------------
260 extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
261 extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
262 = env {seIdSubst = extendVarEnv subst var res}
264 extendTvSubst :: SimplEnv -> TyVar -> Type -> SimplEnv
265 extendTvSubst env@(SimplEnv {seTvSubst = subst}) var res
266 = env {seTvSubst = extendVarEnv subst var res}
268 ---------------------
269 getInScope :: SimplEnv -> InScopeSet
270 getInScope env = seInScope env
272 setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
273 setInScopeSet env in_scope = env {seInScope = in_scope}
275 setInScope :: SimplEnv -> SimplEnv -> SimplEnv
276 setInScope env env_with_in_scope = setInScopeSet env (getInScope env_with_in_scope)
278 addNewInScopeIds :: SimplEnv -> [CoreBndr] -> SimplEnv
279 -- The new Ids are guaranteed to be freshly allocated
280 addNewInScopeIds env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) vs
281 = env { seInScope = in_scope `extendInScopeSetList` vs,
282 seIdSubst = id_subst `delVarEnvList` vs }
283 -- Why delete? Consider
284 -- let x = a*b in (x, \x -> x+3)
285 -- We add [x |-> a*b] to the substitution, but we must
286 -- *delete* it from the substitution when going inside
289 modifyInScope :: SimplEnv -> CoreBndr -> CoreBndr -> SimplEnv
290 modifyInScope env@(SimplEnv {seInScope = in_scope}) v v'
291 = env {seInScope = modifyInScopeSet in_scope v v'}
293 ---------------------
294 zapSubstEnv :: SimplEnv -> SimplEnv
295 zapSubstEnv env = env {seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv}
297 setSubstEnv :: SimplEnv -> TvSubstEnv -> SimplIdSubst -> SimplEnv
298 setSubstEnv env tvs ids = env { seTvSubst = tvs, seIdSubst = ids }
300 mkContEx :: SimplEnv -> InExpr -> SimplSR
301 mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
303 isEmptySimplSubst :: SimplEnv -> Bool
304 isEmptySimplSubst (SimplEnv { seTvSubst = tvs, seIdSubst = ids })
305 = isEmptyVarEnv tvs && isEmptyVarEnv ids
307 ---------------------
308 getRules :: SimplEnv -> RuleBase
309 getRules = seExtRules
314 Given an idempotent substitution, generated by the unifier, use it to
315 refine the environment
318 refineSimplEnv :: SimplEnv -> TypeRefinement -> SimplEnv
319 -- The TvSubstEnv is the refinement, and it refines OutTyVars into OutTypes
320 refineSimplEnv env@(SimplEnv { seTvSubst = tv_subst, seInScope = in_scope })
321 (refine_tv_subst, all_bound_here)
322 = env { seTvSubst = composeTvSubst in_scope refine_tv_subst tv_subst,
323 seInScope = in_scope' }
326 | all_bound_here = in_scope
327 -- The tvs are the tyvars bound here. If only they
328 -- are refined, there's no need to do anything
329 | otherwise = mapInScopeSet refine_id in_scope
331 refine_id v -- Only refine its type; any rules will get
332 -- refined if they are used (I hope)
333 | isId v = setIdType v (Type.substTy refine_subst (idType v))
335 refine_subst = TvSubst in_scope refine_tv_subst
338 %************************************************************************
342 %************************************************************************
346 substId :: SimplEnv -> Id -> SimplSR
347 substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
350 | otherwise -- A local Id
351 = case lookupVarEnv ids v of
352 Just (DoneId v occ) -> DoneId (refine v) occ
354 Nothing -> let v' = refine v
355 in DoneId v' (idOccInfo v')
356 -- We don't put LoopBreakers in the substitution (unless then need
357 -- to be cloned for name-clash rasons), so the idOccInfo is
358 -- very important! If isFragileOcc returned True for
359 -- loop breakers we could avoid this call, but at the expense
360 -- of adding more to the substitution, and building new Ids
361 -- a bit more often than really necessary
363 -- Get the most up-to-date thing from the in-scope set
364 -- Even though it isn't in the substitution, it may be in
365 -- the in-scope set with a different type (we only use the
366 -- substitution if the unique changes).
367 refine v = case lookupInScope in_scope v of
369 Nothing -> WARN( True, ppr v ) v -- This is an error!
373 %************************************************************************
375 \section{Substituting an Id binder}
377 %************************************************************************
380 These functions are in the monad only so that they can be made strict via seq.
383 simplBinders, simplLamBndrs
384 :: SimplEnv -> [InBinder] -> SimplM (SimplEnv, [OutBinder])
385 simplBinders env bndrs = mapAccumLSmpl simplBinder env bndrs
386 simplLamBndrs env bndrs = mapAccumLSmpl simplLamBndr env bndrs
389 simplBinder :: SimplEnv -> InBinder -> SimplM (SimplEnv, OutBinder)
390 -- Used for lambda and case-bound variables
391 -- Clone Id if necessary, substitute type
392 -- Return with IdInfo already substituted, but (fragile) occurrence info zapped
393 -- The substitution is extended only if the variable is cloned, because
394 -- we *don't* need to use it to track occurrence info.
396 | isTyVar bndr = do { let (env', tv) = substTyVarBndr env bndr
397 ; seqTyVar tv `seq` return (env', tv) }
398 | otherwise = do { let (env', id) = substIdBndr env bndr
399 ; seqId id `seq` return (env', id) }
402 simplLamBndr :: SimplEnv -> Var -> SimplM (SimplEnv, Var)
403 -- Used for lambda binders. These sometimes have unfoldings added by
404 -- the worker/wrapper pass that must be preserved, becuase they can't
405 -- be reconstructed from context. For example:
406 -- f x = case x of (a,b) -> fw a b x
407 -- fw a b x{=(a,b)} = ...
408 -- The "{=(a,b)}" is an unfolding we can't reconstruct otherwise.
409 simplLamBndr env bndr
410 | not (isId bndr && hasSomeUnfolding old_unf) = simplBinder env bndr -- Normal case
411 | otherwise = seqId id2 `seq` return (env', id2)
413 old_unf = idUnfolding bndr
414 (env', id1) = substIdBndr env bndr
415 id2 = id1 `setIdUnfolding` substUnfolding env old_unf
418 substIdBndr :: SimplEnv -> Id -- Substitition and Id to transform
419 -> (SimplEnv, Id) -- Transformed pair
422 -- * Unique changed if necessary
423 -- * Type substituted
424 -- * Unfolding zapped
425 -- * Rules, worker, lbvar info all substituted
426 -- * Fragile occurrence info zapped
427 -- * The in-scope set extended with the returned Id
428 -- * The substitution extended with a DoneId if unique changed
429 -- In this case, the var in the DoneId is the same as the
432 substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
434 = (env { seInScope = in_scope `extendInScopeSet` new_id,
435 seIdSubst = new_subst }, new_id)
437 -- id1 is cloned if necessary
438 id1 = uniqAway in_scope old_id
440 -- id2 has its type zapped
441 id2 = substIdType env id1
443 -- new_id has the final IdInfo
444 subst = mkCoreSubst env
445 new_id = maybeModifyIdInfo (substIdInfo subst) id2
447 -- Extend the substitution if the unique has changed
448 -- See the notes with substTyVarBndr for the delSubstEnv
449 new_subst | new_id /= old_id
450 = extendVarEnv id_subst old_id (DoneId new_id (idOccInfo old_id))
452 = delVarEnv id_subst old_id
457 seqTyVar :: TyVar -> ()
458 seqTyVar b = b `seq` ()
461 seqId id = seqType (idType id) `seq`
467 seqIds (id:ids) = seqId id `seq` seqIds ids
471 %************************************************************************
475 %************************************************************************
477 Simplifying let binders
478 ~~~~~~~~~~~~~~~~~~~~~~~
479 Rename the binders if necessary, and substitute their IdInfo,
480 and re-attach it. The resulting binders therefore have all
481 their RULES, which is important in a mutually recursive group
483 We must transfer the IdInfo of the original binder to the new binder.
484 This is crucial, to preserve
488 etc. To do this we must apply the current substitution,
489 which incorporates earlier substitutions in this very letrec group.
491 NB 1. We do this *before* processing the RHS of the binder, so that
492 its substituted rules are visible in its own RHS.
493 This is important. Manuel found cases where he really, really
494 wanted a RULE for a recursive function to apply in that function's
497 NB 2: We do not transfer the arity (see Subst.substIdInfo)
498 The arity of an Id should not be visible
499 in its own RHS, else we eta-reduce
503 which isn't sound. And it makes the arity in f's IdInfo greater than
504 the manifest arity, which isn't good.
505 The arity will get added later.
507 NB 3: It's important that we *do* transer the loop-breaker OccInfo,
508 because that's what stops the Id getting inlined infinitely, in the body
511 NB 4: does no harm for non-recursive bindings
514 simplNonRecBndr :: SimplEnv -> InBinder -> SimplM (SimplEnv, OutBinder)
515 simplNonRecBndr env id
516 = do { let subst = mkCoreSubst env
517 (env1, id1) = substLetIdBndr subst env id
518 ; seqId id1 `seq` return (env1, id1) }
521 simplRecBndrs :: SimplEnv -> [InBinder] -> SimplM (SimplEnv, [OutBinder])
522 simplRecBndrs env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) ids
523 = do { let -- Notice the knot here; we need the result to make
524 -- a substitution for the IdInfo. c.f. CoreSubst.substIdBndr
525 (env1, ids1) = mapAccumL (substLetIdBndr subst) env ids
526 subst = mkCoreSubst env1
527 ; seqIds ids1 `seq` return (env1, ids1) }
530 substLetIdBndr :: CoreSubst.Subst -- Substitution to use for the IdInfo (knot-tied)
531 -> SimplEnv -> InBinder -- Env and binder to transform
532 -> (SimplEnv, OutBinder)
533 -- C.f. CoreSubst.substIdBndr
534 -- Clone Id if necessary, substitute its type
535 -- Return an Id with completely zapped IdInfo
536 -- [A subsequent substIdInfo will restore its IdInfo]
537 -- Augment the subtitution
538 -- if the unique changed, *or*
539 -- if there's interesting occurrence info
541 -- The difference between SimplEnv.substIdBndr above is
543 -- b) the hackish "interesting occ info" part (due to vanish)
545 substLetIdBndr rec_subst env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) old_id
546 = (env { seInScope = in_scope `extendInScopeSet` new_id,
547 seIdSubst = new_subst }, new_id)
549 id1 = uniqAway in_scope old_id
550 id2 = substIdType env id1
551 new_id = maybeModifyIdInfo (substIdInfo rec_subst) id2
553 -- Extend the substitution if the unique has changed,
554 -- or there's some useful occurrence information
555 -- See the notes with substTyVarBndr for the delSubstEnv
556 occ_info = occInfo (idInfo old_id)
557 new_subst | new_id /= old_id || isFragileOcc occ_info
558 = extendVarEnv id_subst old_id (DoneId new_id occ_info)
560 = delVarEnv id_subst old_id
562 substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo
567 -- Keep only 'robust' OccInfo
570 -- Seq'ing on the returned IdInfo is enough to cause all the
571 -- substitutions to happen completely
573 substIdInfo subst info
574 | nothing_to_do = Nothing
575 | otherwise = Just (info `setOccInfo` (if keep_occ then old_occ else NoOccInfo)
576 `setArityInfo` (if keep_arity then old_arity else unknownArity)
577 `setSpecInfo` CoreSubst.substSpec subst old_rules
578 `setWorkerInfo` CoreSubst.substWorker subst old_wrkr
579 `setUnfoldingInfo` noUnfolding)
580 -- setSpecInfo does a seq
581 -- setWorkerInfo does a seq
583 nothing_to_do = keep_occ && keep_arity &&
584 isEmptySpecInfo old_rules &&
585 not (workerExists old_wrkr) &&
586 not (hasUnfolding (unfoldingInfo info))
588 keep_occ = not (isFragileOcc old_occ)
589 keep_arity = old_arity == unknownArity
590 old_arity = arityInfo info
591 old_occ = occInfo info
592 old_rules = specInfo info
593 old_wrkr = workerInfo info
596 substIdType :: SimplEnv -> Id -> Id
597 substIdType env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env}) id
598 | isEmptyVarEnv tv_env || isEmptyVarSet (tyVarsOfType old_ty) = id
599 | otherwise = setIdType id (Type.substTy (TvSubst in_scope tv_env) old_ty)
600 -- The tyVarsOfType is cheaper than it looks
601 -- because we cache the free tyvars of the type
602 -- in a Note in the id's type itself
607 substUnfolding env NoUnfolding = NoUnfolding
608 substUnfolding env (OtherCon cons) = OtherCon cons
609 substUnfolding env (CompulsoryUnfolding rhs) = CompulsoryUnfolding (substExpr env rhs)
610 substUnfolding env (CoreUnfolding rhs t v w g) = CoreUnfolding (substExpr env rhs) t v w g
614 %************************************************************************
616 Impedence matching to type substitution
618 %************************************************************************
621 substTy :: SimplEnv -> Type -> Type
622 substTy (SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) ty
623 = Type.substTy (TvSubst in_scope tv_env) ty
625 substTyVarBndr :: SimplEnv -> TyVar -> (SimplEnv, TyVar)
626 substTyVarBndr env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) tv
627 = case Type.substTyVarBndr (TvSubst in_scope tv_env) tv of
628 (TvSubst in_scope' tv_env', tv')
629 -> (env { seInScope = in_scope', seTvSubst = tv_env'}, tv')
631 -- When substituting in rules etc we can get CoreSubst to do the work
632 -- But CoreSubst uses a simpler form of IdSubstEnv, so we must impedence-match
633 -- here. I think the this will not usually result in a lot of work;
634 -- the substitutions are typically small, and laziness will avoid work in many cases.
636 mkCoreSubst :: SimplEnv -> CoreSubst.Subst
637 mkCoreSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seIdSubst = id_env })
638 = mk_subst tv_env id_env
640 mk_subst tv_env id_env = CoreSubst.mkSubst in_scope tv_env (mapVarEnv fiddle id_env)
642 fiddle (DoneEx e) = e
643 fiddle (DoneId v occ) = Var v
644 fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
646 substExpr :: SimplEnv -> CoreExpr -> CoreExpr
648 | isEmptySimplSubst env = expr
649 | otherwise = CoreSubst.substExpr (mkCoreSubst env) expr
653 %************************************************************************
657 %************************************************************************
660 type FloatsWithExpr = FloatsWith OutExpr
661 type FloatsWith a = (Floats, a)
662 -- We return something equivalent to (let b in e), but
663 -- in pieces to avoid the quadratic blowup when floating
664 -- incrementally. Comments just before simplExprB in Simplify.lhs
666 data Floats = Floats (OrdList OutBind)
667 InScopeSet -- Environment "inside" all the floats
668 Bool -- True <=> All bindings are lifted
670 allLifted :: Floats -> Bool
671 allLifted (Floats _ _ is_lifted) = is_lifted
673 wrapFloats :: Floats -> OutExpr -> OutExpr
674 wrapFloats (Floats bs _ _) body = foldrOL Let body bs
676 isEmptyFloats :: Floats -> Bool
677 isEmptyFloats (Floats bs _ _) = isNilOL bs
679 floatBinds :: Floats -> [OutBind]
680 floatBinds (Floats bs _ _) = fromOL bs
682 flattenFloats :: Floats -> Floats
683 -- Flattens into a single Rec group
684 flattenFloats (Floats bs is is_lifted)
685 = ASSERT2( is_lifted, ppr (fromOL bs) )
686 Floats (unitOL (Rec (flattenBinds (fromOL bs)))) is is_lifted
690 emptyFloats :: SimplEnv -> Floats
691 emptyFloats env = Floats nilOL (getInScope env) True
693 unitFloat :: SimplEnv -> OutId -> OutExpr -> Floats
694 -- A single non-rec float; extend the in-scope set
695 unitFloat env var rhs = Floats (unitOL (NonRec var rhs))
696 (extendInScopeSet (getInScope env) var)
697 (not (isUnLiftedType (idType var)))
699 addFloats :: SimplEnv -> Floats
700 -> (SimplEnv -> SimplM (FloatsWith a))
701 -> SimplM (FloatsWith a)
702 addFloats env (Floats b1 is1 l1) thing_inside
706 = thing_inside (setInScopeSet env is1) `thenSmpl` \ (Floats b2 is2 l2, res) ->
707 returnSmpl (Floats (b1 `appOL` b2) is2 (l1 && l2), res)
709 addLetBind :: OutBind -> Floats -> Floats
710 addLetBind bind (Floats binds in_scope lifted)
711 = Floats (bind `consOL` binds) in_scope (lifted && is_lifted_bind bind)
713 is_lifted_bind (Rec _) = True
714 is_lifted_bind (NonRec b r) = not (isUnLiftedType (idType b))
716 -- addAuxiliaryBind * takes already-simplified things (bndr and rhs)
717 -- * extends the in-scope env
718 -- * assumes it's a let-bindable thing
719 addAuxiliaryBind :: SimplEnv -> OutBind
720 -> (SimplEnv -> SimplM (FloatsWith a))
721 -> SimplM (FloatsWith a)
722 -- Extends the in-scope environment as well as wrapping the bindings
723 addAuxiliaryBind env bind thing_inside
724 = ASSERT( case bind of { NonRec b r -> not (needsCaseBinding (idType b) r) ; Rec _ -> True } )
725 thing_inside (addNewInScopeIds env (bindersOf bind)) `thenSmpl` \ (floats, x) ->
726 returnSmpl (addLetBind bind floats, x)