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 simplLetBndr, simplLetBndrs, simplLamBndr, simplLamBndrs,
29 simplBinder, simplBinders,
30 simplIdInfo, substExpr, substTy,
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,
46 unknownArity, workerExists
49 import Rules ( RuleBase )
50 import CoreUtils ( needsCaseBinding )
51 import CostCentre ( CostCentreStack, subsumedCCS )
54 import VarSet ( isEmptyVarSet, elemVarSetByKey, mkVarSet )
57 import qualified CoreSubst ( Subst, mkSubst, substExpr, substRules, substWorker )
58 import qualified Type ( substTy, substTyVarBndr )
60 import Type ( Type, TvSubst(..), TvSubstEnv, composeTvSubst,
61 isUnLiftedType, seqType, tyVarsOfType )
62 import BasicTypes ( OccInfo(..), isFragileOcc )
63 import CmdLineOpts ( SimplifierMode(..) )
67 %************************************************************************
69 \subsection[Simplify-types]{Type declarations}
71 %************************************************************************
74 type InBinder = CoreBndr
75 type InId = Id -- Not yet cloned
76 type InType = Type -- Ditto
77 type InBind = CoreBind
78 type InExpr = CoreExpr
82 type OutBinder = CoreBndr
83 type OutId = Id -- Cloned
84 type OutTyVar = TyVar -- Cloned
85 type OutType = Type -- Cloned
86 type OutBind = CoreBind
87 type OutExpr = CoreExpr
92 %************************************************************************
94 \subsubsection{The @SimplEnv@ type}
96 %************************************************************************
102 seMode :: SimplifierMode,
103 seChkr :: SwitchChecker,
104 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
106 -- Rules from other modules
107 seExtRules :: RuleBase,
109 -- The current set of in-scope variables
110 -- They are all OutVars, and all bound in this module
111 seInScope :: InScopeSet, -- OutVars only
113 -- The current substitution
114 seTvSubst :: TvSubstEnv, -- InTyVar |--> OutType
115 seIdSubst :: SimplIdSubst -- InId |--> OutExpr
118 type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
121 = DoneEx OutExpr -- Completed term
122 | DoneId OutId OccInfo -- Completed term variable, with occurrence info
123 | ContEx TvSubstEnv -- A suspended substitution
130 The in-scope part of Subst includes *all* in-scope TyVars and Ids
131 The elements of the set may have better IdInfo than the
132 occurrences of in-scope Ids, and (more important) they will
133 have a correctly-substituted type. So we use a lookup in this
134 set to replace occurrences
136 The Ids in the InScopeSet are replete with their Rules,
137 and as we gather info about the unfolding of an Id, we replace
138 it in the in-scope set.
140 The in-scope set is actually a mapping OutVar -> OutVar, and
141 in case expressions we sometimes bind
144 The substitution is *apply-once* only, because InIds and OutIds can overlap.
145 For example, we generally omit mappings
147 from the substitution, when we decide not to clone a77, but it's quite
148 legitimate to put the mapping in the substitution anyway.
150 Indeed, we do so when we want to pass fragile OccInfo to the
151 occurrences of the variable; we add a substitution
152 x77 -> DoneId x77 occ
153 to record x's occurrence information.]
155 Furthermore, consider
156 let x = case k of I# x77 -> ... in
157 let y = case k of I# x77 -> ... in ...
158 and suppose the body is strict in both x and y. Then the simplifier
159 will pull the first (case k) to the top; so the second (case k) will
160 cancel out, mapping x77 to, well, x77! But one is an in-Id and the
163 Of course, the substitution *must* applied! Things in its domain
164 simply aren't necessarily bound in the result.
166 * substId adds a binding (DoneId new_id occ) to the substitution if
167 EITHER the Id's unique has changed
168 OR the Id has interesting occurrence information
169 So in effect you can only get to interesting occurrence information
170 by looking up the *old* Id; it's not really attached to the new id
173 Note, though that the substitution isn't necessarily extended
174 if the type changes. Why not? Because of the next point:
176 * We *always, always* finish by looking up in the in-scope set
177 any variable that doesn't get a DoneEx or DoneVar hit in the substitution.
178 Reason: so that we never finish up with a "old" Id in the result.
179 An old Id might point to an old unfolding and so on... which gives a space leak.
181 [The DoneEx and DoneVar hits map to "new" stuff.]
183 * It follows that substExpr must not do a no-op if the substitution is empty.
184 substType is free to do so, however.
186 * When we come to a let-binding (say) we generate new IdInfo, including an
187 unfolding, attach it to the binder, and add this newly adorned binder to
188 the in-scope set. So all subsequent occurrences of the binder will get mapped
189 to the full-adorned binder, which is also the one put in the binding site.
191 * The in-scope "set" usually maps x->x; we use it simply for its domain.
192 But sometimes we have two in-scope Ids that are synomyms, and should
193 map to the same target: x->x, y->x. Notably:
195 That's why the "set" is actually a VarEnv Var
198 Note [GADT type refinement]
199 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
200 When we come to a GADT pattern match that refines the in-scope types, we
201 a) Refine the types of the Ids in the in-scope set, seInScope.
202 For exmaple, consider
204 Foo :: T (Bool -> Bool)
206 (\ (x::T a) (y::a) -> case x of { Foo -> y True }
208 Technically this is well-typed, but exprType will barf on the
209 (y True) unless we refine the type on y's occurrence.
211 b) Refine the range of the type substitution, seTvSubst.
212 Very similar reason to (a).
214 NB: we don't refine the range of the SimplIdSubst, because it's always
215 interpreted relative to the seInScope (see substId)
217 For (b) we need to be a little careful. Specifically, we compose the refinement
218 with the type substitution. Suppose
219 The substitution was [a->b, b->a]
220 and the refinement was [b->Int]
221 Then we want [a->Int, b->a]
224 The substitution was [a->b]
225 and the refinement was [b->Int]
226 Then we want [a->Int, b->Int]
227 becuase b might be both an InTyVar and OutTyVar
231 mkSimplEnv :: SimplifierMode -> SwitchChecker -> RuleBase -> SimplEnv
232 mkSimplEnv mode switches rules
233 = SimplEnv { seChkr = switches, seCC = subsumedCCS,
234 seMode = mode, seInScope = emptyInScopeSet,
236 seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv }
237 -- The top level "enclosing CC" is "SUBSUMED".
239 ---------------------
240 getSwitchChecker :: SimplEnv -> SwitchChecker
241 getSwitchChecker env = seChkr env
243 ---------------------
244 getMode :: SimplEnv -> SimplifierMode
245 getMode env = seMode env
247 setMode :: SimplifierMode -> SimplEnv -> SimplEnv
248 setMode mode env = env { seMode = mode }
250 ---------------------
251 getEnclosingCC :: SimplEnv -> CostCentreStack
252 getEnclosingCC env = seCC env
254 setEnclosingCC :: SimplEnv -> CostCentreStack -> SimplEnv
255 setEnclosingCC env cc = env {seCC = cc}
257 ---------------------
258 extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
259 extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
260 = env {seIdSubst = extendVarEnv subst var res}
262 extendTvSubst :: SimplEnv -> TyVar -> Type -> SimplEnv
263 extendTvSubst env@(SimplEnv {seTvSubst = subst}) var res
264 = env {seTvSubst = extendVarEnv subst var res}
266 ---------------------
267 getInScope :: SimplEnv -> InScopeSet
268 getInScope env = seInScope env
270 setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
271 setInScopeSet env in_scope = env {seInScope = in_scope}
273 setInScope :: SimplEnv -> SimplEnv -> SimplEnv
274 setInScope env env_with_in_scope = setInScopeSet env (getInScope env_with_in_scope)
276 addNewInScopeIds :: SimplEnv -> [CoreBndr] -> SimplEnv
277 -- The new Ids are guaranteed to be freshly allocated
278 addNewInScopeIds env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) vs
279 = env { seInScope = in_scope `extendInScopeSetList` vs,
280 seIdSubst = id_subst `delVarEnvList` vs } -- Why delete?
282 modifyInScope :: SimplEnv -> CoreBndr -> CoreBndr -> SimplEnv
283 modifyInScope env@(SimplEnv {seInScope = in_scope}) v v'
284 = env {seInScope = modifyInScopeSet in_scope v v'}
286 ---------------------
287 zapSubstEnv :: SimplEnv -> SimplEnv
288 zapSubstEnv env = env {seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv}
290 setSubstEnv :: SimplEnv -> TvSubstEnv -> SimplIdSubst -> SimplEnv
291 setSubstEnv env tvs ids = env { seTvSubst = tvs, seIdSubst = ids }
293 mkContEx :: SimplEnv -> InExpr -> SimplSR
294 mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
296 isEmptySimplSubst :: SimplEnv -> Bool
297 isEmptySimplSubst (SimplEnv { seTvSubst = tvs, seIdSubst = ids })
298 = isEmptyVarEnv tvs && isEmptyVarEnv ids
300 ---------------------
301 getRules :: SimplEnv -> RuleBase
302 getRules = seExtRules
307 Given an idempotent substitution, generated by the unifier, use it to
308 refine the environment
311 refineSimplEnv :: SimplEnv -> TvSubstEnv -> [OutTyVar] -> SimplEnv
312 -- The TvSubstEnv is the refinement, and it refines OutTyVars into OutTypes
313 refineSimplEnv env@(SimplEnv { seTvSubst = tv_subst, seInScope = in_scope })
315 = env { seTvSubst = composeTvSubst in_scope refine_tv_subst tv_subst,
316 seInScope = in_scope' }
319 | all bound_here (varEnvKeys refine_tv_subst) = in_scope
320 -- The tvs are the tyvars bound here. If only they
321 -- are refined, there's no need to do anything
322 | otherwise = mapInScopeSet refine_id in_scope
324 bound_here uniq = elemVarSetByKey uniq tv_set
325 tv_set = mkVarSet tvs
327 refine_id v -- Only refine its type; any rules will get
328 -- refined if they are used (I hope)
329 | isId v = setIdType v (Type.substTy refine_subst (idType v))
331 refine_subst = TvSubst in_scope refine_tv_subst
334 %************************************************************************
338 %************************************************************************
342 substId :: SimplEnv -> Id -> SimplSR
343 substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
346 | otherwise -- A local Id
347 = case lookupVarEnv ids v of
348 Just (DoneId v occ) -> DoneId (refine v) occ
350 Nothing -> let v' = refine v
351 in DoneId v' (idOccInfo v')
352 -- We don't put LoopBreakers in the substitution (unless then need
353 -- to be cloned for name-clash rasons), so the idOccInfo is
354 -- very important! If isFragileOcc returned True for
355 -- loop breakers we could avoid this call, but at the expense
356 -- of adding more to the substitution, and building new Ids
357 -- a bit more often than really necessary
359 -- Get the most up-to-date thing from the in-scope set
360 -- Even though it isn't in the substitution, it may be in
361 -- the in-scope set with a different type (we only use the
362 -- substitution if the unique changes).
363 refine v = case lookupInScope in_scope v of
365 Nothing -> WARN( True, ppr v ) v -- This is an error!
369 %************************************************************************
371 \section{Substituting an Id binder}
373 %************************************************************************
376 These functions are in the monad only so that they can be made strict via seq.
379 simplBinders, simplLamBndrs, simplLetBndrs
380 :: SimplEnv -> [InBinder] -> SimplM (SimplEnv, [OutBinder])
381 simplBinders env bndrs = mapAccumLSmpl simplBinder env bndrs
382 simplLamBndrs env bndrs = mapAccumLSmpl simplLamBndr env bndrs
383 simplLetBndrs env bndrs = mapAccumLSmpl simplLetBndr env bndrs
386 simplBinder :: SimplEnv -> InBinder -> SimplM (SimplEnv, OutBinder)
387 -- Used for lambda and case-bound variables
388 -- Clone Id if necessary, substitute type
389 -- Return with IdInfo already substituted, but (fragile) occurrence info zapped
390 -- The substitution is extended only if the variable is cloned, because
391 -- we *don't* need to use it to track occurrence info.
393 | isTyVar bndr = do { let (env', tv) = substTyVarBndr env bndr
394 ; seqTyVar tv `seq` return (env', tv) }
395 | otherwise = do { let (env', id) = substIdBndr env bndr
396 ; seqId id `seq` return (env', id) }
399 simplLetBndr :: SimplEnv -> Var -> SimplM (SimplEnv, Var)
400 simplLetBndr env id = do { let (env', id') = substLetId env id
401 ; seqId id' `seq` return (env', id') }
404 simplLamBndr :: SimplEnv -> Var -> SimplM (SimplEnv, Var)
405 -- Used for lambda binders. These sometimes have unfoldings added by
406 -- the worker/wrapper pass that must be preserved, becuase they can't
407 -- be reconstructed from context. For example:
408 -- f x = case x of (a,b) -> fw a b x
409 -- fw a b x{=(a,b)} = ...
410 -- The "{=(a,b)}" is an unfolding we can't reconstruct otherwise.
411 simplLamBndr env bndr
412 | not (isId bndr && hasSomeUnfolding old_unf) = simplBinder env bndr -- Normal case
413 | otherwise = seqId id2 `seq` return (env', id2)
415 old_unf = idUnfolding bndr
416 (env', id1) = substIdBndr env bndr
417 id2 = id1 `setIdUnfolding` substUnfolding env old_unf
420 seqTyVar :: TyVar -> ()
421 seqTyVar b = b `seq` ()
424 seqId id = seqType (idType id) `seq`
430 substIdBndr :: SimplEnv -> Id -- Substitition and Id to transform
431 -> (SimplEnv, Id) -- Transformed pair
434 -- * Unique changed if necessary
435 -- * Type substituted
436 -- * Unfolding zapped
437 -- * Rules, worker, lbvar info all substituted
438 -- * Fragile occurrence info zapped
439 -- * The in-scope set extended with the returned Id
440 -- * The substitution extended with a DoneId if unique changed
441 -- In this case, the var in the DoneId is the same as the
444 substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
446 = (env { seInScope = in_scope `extendInScopeSet` new_id,
447 seIdSubst = new_subst }, new_id)
449 -- id1 is cloned if necessary
450 id1 = uniqAway in_scope old_id
452 -- id2 has its type zapped
453 id2 = substIdType env id1
455 -- new_id has the right IdInfo
456 -- The lazy-set is because we're in a loop here, with
457 -- rec_env, when dealing with a mutually-recursive group
458 new_id = maybeModifyIdInfo (substIdInfo env) id2
460 -- Extend the substitution if the unique has changed
461 -- See the notes with substTyVarBndr for the delSubstEnv
462 new_subst | new_id /= old_id
463 = extendVarEnv id_subst old_id (DoneId new_id (idOccInfo old_id))
465 = delVarEnv id_subst old_id
467 substLetId :: SimplEnv -> Id -> (SimplEnv, Id)
468 -- A variant for let-bound Ids
469 -- Clone Id if necessary
470 -- Substitute its type
471 -- Return an Id with completely zapped IdInfo
472 -- [A subsequent substIdInfo will restore its IdInfo]
473 -- Augment the subtitution
474 -- if the unique changed, *or*
475 -- if there's interesting occurrence info
477 substLetId env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) old_id
478 = (env { seInScope = in_scope `extendInScopeSet` new_id,
479 seIdSubst = new_subst }, new_id)
481 old_info = idInfo old_id
482 id1 = uniqAway in_scope old_id
483 id2 = substIdType env id1
484 new_id = setIdInfo id2 vanillaIdInfo
486 -- Extend the substitution if the unique has changed,
487 -- or there's some useful occurrence information
488 -- See the notes with substTyVarBndr for the delSubstEnv
489 occ_info = occInfo old_info
490 new_subst | new_id /= old_id || isFragileOcc occ_info
491 = extendVarEnv id_subst old_id (DoneId new_id occ_info)
493 = delVarEnv id_subst old_id
497 %************************************************************************
499 Impedence matching to type substitution
501 %************************************************************************
504 substTy :: SimplEnv -> Type -> Type
505 substTy (SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) ty
506 = Type.substTy (TvSubst in_scope tv_env) ty
508 substTyVarBndr :: SimplEnv -> TyVar -> (SimplEnv, TyVar)
509 substTyVarBndr env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) tv
510 = case Type.substTyVarBndr (TvSubst in_scope tv_env) tv of
511 (TvSubst in_scope' tv_env', tv')
512 -> (env { seInScope = in_scope', seTvSubst = tv_env'}, tv')
514 -- When substituting in rules etc we can get CoreSubst to do the work
515 -- But CoreSubst uses a simpler form of IdSubstEnv, so we must impedence-match
516 -- here. I think the this will not usually result in a lot of work;
517 -- the substitutions are typically small, and laziness will avoid work in many cases.
519 mkCoreSubst :: SimplEnv -> CoreSubst.Subst
520 mkCoreSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seIdSubst = id_env })
521 = mk_subst tv_env id_env
523 mk_subst tv_env id_env = CoreSubst.mkSubst in_scope tv_env (mapVarEnv fiddle id_env)
525 fiddle (DoneEx e) = e
526 fiddle (DoneId v occ) = Var v
527 fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
529 substExpr :: SimplEnv -> CoreExpr -> CoreExpr
531 | isEmptySimplSubst env = expr
532 | otherwise = CoreSubst.substExpr (mkCoreSubst env) expr
536 %************************************************************************
538 \section{IdInfo substitution}
540 %************************************************************************
543 simplIdInfo :: SimplEnv -> IdInfo -> IdInfo
544 -- Used by the simplifier to compute new IdInfo for a let(rec) binder,
545 -- subsequent to simplLetId having zapped its IdInfo
546 simplIdInfo env old_info
547 = case substIdInfo env old_info of
548 Just new_info -> new_info
551 substIdInfo :: SimplEnv
558 -- Keep only 'robust' OccInfo
561 -- Seq'ing on the returned IdInfo is enough to cause all the
562 -- substitutions to happen completely
565 | nothing_to_do = Nothing
566 | otherwise = Just (info `setOccInfo` (if keep_occ then old_occ else NoOccInfo)
567 `setArityInfo` (if keep_arity then old_arity else unknownArity)
568 `setSpecInfo` CoreSubst.substRules subst old_rules
569 `setWorkerInfo` CoreSubst.substWorker subst old_wrkr
570 `setUnfoldingInfo` noUnfolding)
571 -- setSpecInfo does a seq
572 -- setWorkerInfo does a seq
574 subst = mkCoreSubst env
575 nothing_to_do = keep_occ && keep_arity &&
576 isEmptyCoreRules old_rules &&
577 not (workerExists old_wrkr) &&
578 not (hasUnfolding (unfoldingInfo info))
580 keep_occ = not (isFragileOcc old_occ)
581 keep_arity = old_arity == unknownArity
582 old_arity = arityInfo info
583 old_occ = occInfo info
584 old_rules = specInfo info
585 old_wrkr = workerInfo info
588 substIdType :: SimplEnv -> Id -> Id
589 substIdType env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env}) id
590 | isEmptyVarEnv tv_env || isEmptyVarSet (tyVarsOfType old_ty) = id
591 | otherwise = setIdType id (Type.substTy (TvSubst in_scope tv_env) old_ty)
592 -- The tyVarsOfType is cheaper than it looks
593 -- because we cache the free tyvars of the type
594 -- in a Note in the id's type itself
599 substUnfolding env NoUnfolding = NoUnfolding
600 substUnfolding env (OtherCon cons) = OtherCon cons
601 substUnfolding env (CompulsoryUnfolding rhs) = CompulsoryUnfolding (substExpr env rhs)
602 substUnfolding env (CoreUnfolding rhs t v w g) = CoreUnfolding (substExpr env rhs) t v w g
606 %************************************************************************
610 %************************************************************************
613 type FloatsWithExpr = FloatsWith OutExpr
614 type FloatsWith a = (Floats, a)
615 -- We return something equivalent to (let b in e), but
616 -- in pieces to avoid the quadratic blowup when floating
617 -- incrementally. Comments just before simplExprB in Simplify.lhs
619 data Floats = Floats (OrdList OutBind)
620 InScopeSet -- Environment "inside" all the floats
621 Bool -- True <=> All bindings are lifted
623 allLifted :: Floats -> Bool
624 allLifted (Floats _ _ is_lifted) = is_lifted
626 wrapFloats :: Floats -> OutExpr -> OutExpr
627 wrapFloats (Floats bs _ _) body = foldrOL Let body bs
629 isEmptyFloats :: Floats -> Bool
630 isEmptyFloats (Floats bs _ _) = isNilOL bs
632 floatBinds :: Floats -> [OutBind]
633 floatBinds (Floats bs _ _) = fromOL bs
635 flattenFloats :: Floats -> Floats
636 -- Flattens into a single Rec group
637 flattenFloats (Floats bs is is_lifted)
638 = ASSERT2( is_lifted, ppr (fromOL bs) )
639 Floats (unitOL (Rec (flattenBinds (fromOL bs)))) is is_lifted
643 emptyFloats :: SimplEnv -> Floats
644 emptyFloats env = Floats nilOL (getInScope env) True
646 unitFloat :: SimplEnv -> OutId -> OutExpr -> Floats
647 -- A single non-rec float; extend the in-scope set
648 unitFloat env var rhs = Floats (unitOL (NonRec var rhs))
649 (extendInScopeSet (getInScope env) var)
650 (not (isUnLiftedType (idType var)))
652 addFloats :: SimplEnv -> Floats
653 -> (SimplEnv -> SimplM (FloatsWith a))
654 -> SimplM (FloatsWith a)
655 addFloats env (Floats b1 is1 l1) thing_inside
659 = thing_inside (setInScopeSet env is1) `thenSmpl` \ (Floats b2 is2 l2, res) ->
660 returnSmpl (Floats (b1 `appOL` b2) is2 (l1 && l2), res)
662 addLetBind :: OutBind -> Floats -> Floats
663 addLetBind bind (Floats binds in_scope lifted)
664 = Floats (bind `consOL` binds) in_scope (lifted && is_lifted_bind bind)
666 is_lifted_bind (Rec _) = True
667 is_lifted_bind (NonRec b r) = not (isUnLiftedType (idType b))
669 -- addAuxiliaryBind * takes already-simplified things (bndr and rhs)
670 -- * extends the in-scope env
671 -- * assumes it's a let-bindable thing
672 addAuxiliaryBind :: SimplEnv -> OutBind
673 -> (SimplEnv -> SimplM (FloatsWith a))
674 -> SimplM (FloatsWith a)
675 -- Extends the in-scope environment as well as wrapping the bindings
676 addAuxiliaryBind env bind thing_inside
677 = ASSERT( case bind of { NonRec b r -> not (needsCaseBinding (idType b) r) ; Rec _ -> True } )
678 thing_inside (addNewInScopeIds env (bindersOf bind)) `thenSmpl` \ (floats, x) ->
679 returnSmpl (addLetBind bind floats, x)