2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[StgVarInfo]{Sets free/live variable info in STG syntax}
6 And, as we have the info in hand, we may convert some lets to
10 module StgVarInfo ( setStgVarInfo ) where
12 #include "HsVersions.h"
16 import Id ( emptyIdSet, mkIdSet, minusIdSet,
17 unionIdSets, unionManyIdSets, isEmptyIdSet,
18 unitIdSet, intersectIdSets,
19 addIdArity, getIdArity,
21 nullIdEnv, growIdEnvList, lookupIdEnv,
22 unitIdEnv, combineIdEnvs, delManyFromIdEnv,
24 GenId{-instance Eq-}, Id
26 import IdInfo ( ArityInfo(..) )
27 import Maybes ( maybeToBool )
28 import Name ( isLocallyDefined )
29 import BasicTypes ( Arity )
30 import PprType ( GenType{-instance Outputable-} )
33 infixr 9 `thenLne`, `thenLne_`
36 %************************************************************************
38 \subsection[live-vs-free-doc]{Documentation}
40 %************************************************************************
42 (There is other relevant documentation in codeGen/CgLetNoEscape.)
44 March 97: setStgVarInfo guarantees to leave every variable's arity correctly
45 set. The lambda lifter makes some let-bound variables (which have arities)
46 and turns them into lambda-bound ones (which should not, else we get Vap trouble),
47 so this guarantee is necessary, as well as desirable.
49 The arity information is used in the code generator, when deciding if
50 a right-hand side is a saturated application so we can generate a VAP
53 The actual Stg datatype is decorated with {\em live variable}
54 information, as well as {\em free variable} information. The two are
55 {\em not} the same. Liveness is an operational property rather than a
56 semantic one. A variable is live at a particular execution point if
57 it can be referred to {\em directly} again. In particular, a dead
58 variable's stack slot (if it has one):
61 should be stubbed to avoid space leaks, and
63 may be reused for something else.
66 There ought to be a better way to say this. Here are some examples:
73 Just after the `in', v is live, but q is dead. If the whole of that
74 let expression was enclosed in a case expression, thus:
76 case (let v = [q] \[x] -> e in ...v...) of
79 (ie @alts@ mention @q@), then @q@ is live even after the `in'; because
80 we'll return later to the @alts@ and need it.
82 Let-no-escapes make this a bit more interesting:
84 let-no-escape v = [q] \ [x] -> e
88 Here, @q@ is still live at the `in', because @v@ is represented not by
89 a closure but by the current stack state. In other words, if @v@ is
90 live then so is @q@. Furthermore, if @e@ mentions an enclosing
91 let-no-escaped variable, then {\em its} free variables are also live
94 %************************************************************************
96 \subsection[binds-StgVarInfo]{Setting variable info: top-level, binds, RHSs}
98 %************************************************************************
102 setStgVarInfo :: Bool -- True <=> do let-no-escapes
103 -> [StgBinding] -- input
104 -> [StgBinding] -- result
106 setStgVarInfo want_LNEs pgm
109 (pgm', _) = initLne want_LNEs (varsTopBinds pgm)
113 For top-level guys, we basically aren't worried about this
114 live-variable stuff; we do need to keep adding to the environment
115 as we step through the bindings (using @extendVarEnv@).
118 varsTopBinds :: [StgBinding] -> LneM ([StgBinding], FreeVarsInfo)
120 varsTopBinds [] = returnLne ([], emptyFVInfo)
121 varsTopBinds (bind:binds)
122 = extendVarEnv env_extension (
123 varsTopBinds binds `thenLne` \ (binds', fv_binds) ->
124 varsTopBind binders' fv_binds bind `thenLne` \ (bind', fv_bind) ->
125 returnLne ((bind' : binds'),
126 (fv_binds `unionFVInfo` fv_bind) `minusFVBinders` binders'
132 StgNonRec binder rhs -> [(binder,rhs)]
133 StgRec pairs -> pairs
135 binders' = [ binder `addIdArity` ArityExactly (rhsArity rhs)
136 | (binder, rhs) <- pairs
139 env_extension = binders' `zip` repeat how_bound
141 how_bound = LetrecBound
146 varsTopBind :: [Id] -- New binders (with correct arity)
147 -> FreeVarsInfo -- Info about the body
149 -> LneM (StgBinding, FreeVarsInfo)
151 varsTopBind [binder'] body_fvs (StgNonRec binder rhs)
152 = varsRhs body_fvs (binder,rhs) `thenLne` \ (rhs2, fvs, _) ->
153 returnLne (StgNonRec binder' rhs2, fvs)
155 varsTopBind binders' body_fvs (StgRec pairs)
156 = fixLne (\ ~(_, rec_rhs_fvs) ->
158 scope_fvs = unionFVInfo body_fvs rec_rhs_fvs
160 mapAndUnzip3Lne (varsRhs scope_fvs) pairs `thenLne` \ (rhss2, fvss, _) ->
162 fvs = unionFVInfos fvss
164 returnLne (StgRec (binders' `zip` rhss2), fvs)
170 varsRhs :: FreeVarsInfo -- Free var info for the scope of the binding
172 -> LneM (StgRhs, FreeVarsInfo, EscVarsSet)
174 varsRhs scope_fv_info (binder, StgRhsCon cc con args)
175 = varsAtoms args `thenLne` \ (args', fvs) ->
176 returnLne (StgRhsCon cc con args', fvs, getFVSet fvs)
178 varsRhs scope_fv_info (binder, StgRhsClosure cc _ _ upd args body)
179 = extendVarEnv [ (zapArity a, LambdaBound) | a <- args ] (
180 do_body args body `thenLne` \ (body2, body_fvs, body_escs) ->
182 set_of_args = mkIdSet args
183 rhs_fvs = body_fvs `minusFVBinders` args
184 rhs_escs = body_escs `minusIdSet` set_of_args
185 binder_info = lookupFVInfo scope_fv_info binder
187 returnLne (StgRhsClosure cc binder_info (getFVs rhs_fvs) upd args body2,
191 -- Pick out special case of application in body of thunk
192 do_body [] (StgApp (StgVarArg f) args _) = varsApp (Just upd) f args
193 do_body _ other_body = varsExpr other_body
198 varsAtoms :: [StgArg]
199 -> LneM ([StgArg], FreeVarsInfo)
200 -- It's not *really* necessary to return fresh arguments,
201 -- because the only difference is that the argument variable
202 -- arities are correct. But it seems safer to do so.
205 = mapAndUnzipLne var_atom atoms `thenLne` \ (args', fvs_lists) ->
206 returnLne (args', unionFVInfos fvs_lists)
208 var_atom a@(StgLitArg _) = returnLne (a, emptyFVInfo)
209 var_atom a@(StgConArg _) = returnLne (a, emptyFVInfo)
210 var_atom a@(StgVarArg v)
211 = lookupVarEnv v `thenLne` \ (v', how_bound) ->
212 returnLne (StgVarArg v', singletonFVInfo v' how_bound stgArgOcc)
215 %************************************************************************
217 \subsection[expr-StgVarInfo]{Setting variable info on expressions}
219 %************************************************************************
221 @varsExpr@ carries in a monad-ised environment, which binds each
222 let(rec) variable (ie non top level, not imported, not lambda bound,
223 not case-alternative bound) to:
225 - its set of live vars.
226 For normal variables the set of live vars is just the variable
227 itself. For let-no-escaped variables, the set of live vars is the set
228 live at the moment the variable is entered. The set is guaranteed to
229 have no further let-no-escaped vars in it.
233 -> LneM (StgExpr, -- Decorated expr
234 FreeVarsInfo, -- Its free vars (NB free, not live)
235 EscVarsSet) -- Its escapees, a subset of its free vars;
236 -- also a subset of the domain of the envt
237 -- because we are only interested in the escapees
238 -- for vars which might be turned into
239 -- let-no-escaped ones.
242 The second and third components can be derived in a simple bottom up pass, not
243 dependent on any decisions about which variables will be let-no-escaped or
244 not. The first component, that is, the decorated expression, may then depend
245 on these components, but it in turn is not scrutinised as the basis for any
246 decisions. Hence no black holes.
249 varsExpr (StgApp lit@(StgLitArg _) args _)
250 = returnLne (StgApp lit [] emptyIdSet, emptyFVInfo, emptyIdSet)
252 varsExpr (StgApp lit@(StgConArg _) args _)
253 = panic "varsExpr StgConArg" -- Only occur in argument positions
255 varsExpr (StgApp fun@(StgVarArg f) args _) = varsApp Nothing f args
257 varsExpr (StgCon con args _)
258 = getVarsLiveInCont `thenLne` \ live_in_cont ->
259 varsAtoms args `thenLne` \ (args', args_fvs) ->
261 returnLne (StgCon con args' live_in_cont, args_fvs, getFVSet args_fvs)
263 varsExpr (StgPrim op args _)
264 = getVarsLiveInCont `thenLne` \ live_in_cont ->
265 varsAtoms args `thenLne` \ (args', args_fvs) ->
266 returnLne (StgPrim op args' live_in_cont, args_fvs, getFVSet args_fvs)
268 varsExpr (StgSCC ty label expr)
269 = varsExpr expr `thenLne` ( \ (expr2, fvs, escs) ->
270 returnLne (StgSCC ty label expr2, fvs, escs) )
273 Cases require a little more real work.
275 varsExpr (StgCase scrut _ _ uniq alts)
276 = getVarsLiveInCont `thenLne` \ live_in_cont ->
277 vars_alts alts `thenLne` \ (alts2, alts_fvs, alts_escs) ->
278 lookupLiveVarsForSet alts_fvs `thenLne` \ alts_lvs ->
280 live_in_alts = live_in_cont `unionIdSets` alts_lvs
282 -- we tell the scrutinee that everything live in the alts
283 -- is live in it, too.
284 setVarsLiveInCont live_in_alts (
286 ) `thenLne` \ (scrut2, scrut_fvs, scrut_escs) ->
287 lookupLiveVarsForSet scrut_fvs `thenLne` \ scrut_lvs ->
289 live_in_whole_case = live_in_alts `unionIdSets` scrut_lvs
292 StgCase scrut2 live_in_whole_case live_in_alts uniq alts2,
293 scrut_fvs `unionFVInfo` alts_fvs,
294 alts_escs `unionIdSets` (getFVSet scrut_fvs) -- All free vars in the scrutinee escape
297 vars_alts (StgAlgAlts ty alts deflt)
298 = mapAndUnzip3Lne vars_alg_alt alts
299 `thenLne` \ (alts2, alts_fvs_list, alts_escs_list) ->
301 alts_fvs = unionFVInfos alts_fvs_list
302 alts_escs = unionManyIdSets alts_escs_list
304 vars_deflt deflt `thenLne` \ (deflt2, deflt_fvs, deflt_escs) ->
306 StgAlgAlts ty alts2 deflt2,
307 alts_fvs `unionFVInfo` deflt_fvs,
308 alts_escs `unionIdSets` deflt_escs
311 vars_alg_alt (con, binders, worthless_use_mask, rhs)
312 = extendVarEnv [(zapArity b, CaseBound) | b <- binders] (
313 varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
315 good_use_mask = [ b `elementOfFVInfo` rhs_fvs | b <- binders ]
316 -- records whether each param is used in the RHS
319 (con, binders, good_use_mask, rhs2),
320 rhs_fvs `minusFVBinders` binders,
321 rhs_escs `minusIdSet` mkIdSet binders -- ToDo: remove the minusIdSet;
322 -- since escs won't include
323 -- any of these binders
326 vars_alts (StgPrimAlts ty alts deflt)
327 = mapAndUnzip3Lne vars_prim_alt alts
328 `thenLne` \ (alts2, alts_fvs_list, alts_escs_list) ->
330 alts_fvs = unionFVInfos alts_fvs_list
331 alts_escs = unionManyIdSets alts_escs_list
333 vars_deflt deflt `thenLne` \ (deflt2, deflt_fvs, deflt_escs) ->
335 StgPrimAlts ty alts2 deflt2,
336 alts_fvs `unionFVInfo` deflt_fvs,
337 alts_escs `unionIdSets` deflt_escs
340 vars_prim_alt (lit, rhs)
341 = varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
342 returnLne ((lit, rhs2), rhs_fvs, rhs_escs)
344 vars_deflt StgNoDefault
345 = returnLne (StgNoDefault, emptyFVInfo, emptyIdSet)
347 vars_deflt (StgBindDefault binder _ rhs)
348 = extendVarEnv [(zapArity binder, CaseBound)] (
349 varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
351 used_in_rhs = binder `elementOfFVInfo` rhs_fvs
354 StgBindDefault binder used_in_rhs rhs2,
355 rhs_fvs `minusFVBinders` [binder],
356 rhs_escs `minusIdSet` unitIdSet binder
360 Lets not only take quite a bit of work, but this is where we convert
361 then to let-no-escapes, if we wish.
363 (Meanwhile, we don't expect to see let-no-escapes...)
365 varsExpr (StgLetNoEscape _ _ _ _) = panic "varsExpr: unexpected StgLetNoEscape"
367 varsExpr (StgLet bind body)
368 = isSwitchSetLne {-StgDoLetNoEscapes-} `thenLne` \ want_LNEs ->
370 (fixLne (\ ~(_, _, _, no_binder_escapes) ->
372 non_escaping_let = want_LNEs && no_binder_escapes
374 vars_let non_escaping_let bind body
375 )) `thenLne` \ (new_let, fvs, escs, _) ->
377 returnLne (new_let, fvs, escs)
382 varsApp :: Maybe UpdateFlag -- Just upd <=> this application is
383 -- the rhs of a thunk binding
384 -- x = [...] \upd [] -> the_app
385 -- with specified update flag
387 -> [StgArg] -- Arguments
388 -> LneM (StgExpr, FreeVarsInfo, EscVarsSet)
390 varsApp maybe_thunk_body f args
391 = getVarsLiveInCont `thenLne` \ live_in_cont ->
393 varsAtoms args `thenLne` \ (args', args_fvs) ->
395 lookupVarEnv f `thenLne` \ (f', how_bound) ->
399 not_letrec_bound = not (isLetrecBound how_bound)
400 f_arity = getIdArity f'
401 fun_fvs = singletonFVInfo f' how_bound fun_occ
405 = NoStgBinderInfo -- Uninteresting variable
407 | otherwise -- Letrec bound; must have its arity
410 | n_args == 0 -> stgFakeFunAppOcc -- Function Application
411 -- with no arguments.
412 -- used by the lambda lifter.
413 | arity > n_args -> stgUnsatOcc -- Unsaturated
417 maybeToBool maybe_thunk_body -> -- Exactly saturated,
419 case maybe_thunk_body of
420 Just Updatable -> stgStdHeapOcc
421 Just SingleEntry -> stgNoUpdHeapOcc
422 other -> panic "varsApp"
424 | otherwise -> stgNormalOcc
425 -- Record only that it occurs free
427 myself = unitIdSet f'
429 fun_escs | not_letrec_bound = emptyIdSet -- Only letrec-bound escapees are interesting
430 | otherwise = case f_arity of -- Letrec bound, so must have its arity
432 | arity == n_args -> emptyIdSet
433 -- Function doesn't escape
434 | otherwise -> myself
435 -- Inexact application; it does escape
437 -- At the moment of the call:
439 -- either the function is *not* let-no-escaped, in which case
440 -- nothing is live except live_in_cont
441 -- or the function *is* let-no-escaped in which case the
442 -- variables it uses are live, but still the function
443 -- itself is not. PS. In this case, the function's
444 -- live vars should already include those of the
445 -- continuation, but it does no harm to just union the
449 = live_in_cont `unionIdSets` case how_bound of
450 LetrecBound _ lvs -> lvs `minusIdSet` myself
454 StgApp (StgVarArg f') args' live_at_call,
455 fun_fvs `unionFVInfo` args_fvs,
456 fun_escs `unionIdSets` (getFVSet args_fvs)
457 -- All the free vars of the args are disqualified
458 -- from being let-no-escaped.
464 vars_let :: Bool -- True <=> yes, we are let-no-escaping this let
465 -> StgBinding -- bindings
467 -> LneM (StgExpr, -- new let
468 FreeVarsInfo, -- variables free in the whole let
469 EscVarsSet, -- variables that escape from the whole let
470 Bool) -- True <=> none of the binders in the bindings
471 -- is among the escaping vars
473 vars_let let_no_escape bind body
474 = fixLne (\ ~(_, _, _, rec_bind_lvs, _, rec_body_fvs, _, _) ->
476 -- Do the bindings, setting live_in_cont to empty if
477 -- we ain't in a let-no-escape world
478 getVarsLiveInCont `thenLne` \ live_in_cont ->
480 (if let_no_escape then live_in_cont else emptyIdSet)
481 (vars_bind rec_bind_lvs rec_body_fvs bind)
482 `thenLne` \ (bind2, bind_fvs, bind_escs, env_ext) ->
484 -- The live variables of this binding are the ones which are live
485 -- by virtue of being accessible via the free vars of the binding (lvs_from_fvs)
486 -- together with the live_in_cont ones
487 lookupLiveVarsForSet (bind_fvs `minusFVBinders` binders) `thenLne` \ lvs_from_fvs ->
489 bind_lvs = lvs_from_fvs `unionIdSets` live_in_cont
492 -- bind_fvs and bind_escs still include the binders of the let(rec)
493 -- but bind_lvs does not
496 extendVarEnv env_ext (
497 varsExpr body `thenLne` \ (body2, body_fvs, body_escs) ->
498 lookupLiveVarsForSet body_fvs `thenLne` \ body_lvs ->
500 returnLne (bind2, bind_fvs, bind_escs, bind_lvs,
501 body2, body_fvs, body_escs, body_lvs)
503 )) `thenLne` (\ (bind2, bind_fvs, bind_escs, bind_lvs,
504 body2, body_fvs, body_escs, body_lvs) ->
507 -- Compute the new let-expression
509 new_let = if let_no_escape then
510 -- trace "StgLetNoEscape!" (
511 StgLetNoEscape live_in_whole_let bind_lvs bind2 body2
517 = (bind_fvs `unionFVInfo` body_fvs) `minusFVBinders` binders
520 = bind_lvs `unionIdSets` (body_lvs `minusIdSet` set_of_binders)
522 real_bind_escs = if let_no_escape then
526 -- Everything escapes which is free in the bindings
528 let_escs = (real_bind_escs `unionIdSets` body_escs) `minusIdSet` set_of_binders
530 all_escs = bind_escs `unionIdSets` body_escs -- Still includes binders of
533 no_binder_escapes = isEmptyIdSet (set_of_binders `intersectIdSets` all_escs)
534 -- Mustn't depend on the passed-in let_no_escape flag, since
535 -- no_binder_escapes is used by the caller to derive the flag!
544 set_of_binders = mkIdSet binders
545 binders = case bind of
546 StgNonRec binder rhs -> [binder]
547 StgRec pairs -> map fst pairs
549 mk_binding bind_lvs (binder,rhs)
550 = (binder `addIdArity` ArityExactly (stgArity rhs),
551 LetrecBound False -- Not top level
555 live_vars = if let_no_escape then
556 addOneToIdSet bind_lvs binder
560 vars_bind :: StgLiveVars
561 -> FreeVarsInfo -- Free var info for body of binding
564 FreeVarsInfo, EscVarsSet, -- free vars; escapee vars
566 -- extension to environment
568 vars_bind rec_bind_lvs rec_body_fvs (StgNonRec binder rhs)
569 = varsRhs rec_body_fvs (binder,rhs) `thenLne` \ (rhs2, fvs, escs) ->
571 env_ext_item@(binder', _) = mk_binding rec_bind_lvs (binder,rhs)
573 returnLne (StgNonRec binder' rhs2, fvs, escs, [env_ext_item])
575 vars_bind rec_bind_lvs rec_body_fvs (StgRec pairs)
577 env_ext = map (mk_binding rec_bind_lvs) pairs
578 binders' = map fst env_ext
580 extendVarEnv env_ext (
581 fixLne (\ ~(_, rec_rhs_fvs, _, _) ->
583 rec_scope_fvs = unionFVInfo rec_body_fvs rec_rhs_fvs
585 mapAndUnzip3Lne (varsRhs rec_scope_fvs) pairs `thenLne` \ (rhss2, fvss, escss) ->
587 fvs = unionFVInfos fvss
588 escs = unionManyIdSets escss
590 returnLne (StgRec (binders' `zip` rhss2), fvs, escs, env_ext)
594 %************************************************************************
596 \subsection[LNE-monad]{A little monad for this let-no-escaping pass}
598 %************************************************************************
600 There's a lot of stuff to pass around, so we use this @LneM@ monad to
601 help. All the stuff here is only passed {\em down}.
604 type LneM a = Bool -- True <=> do let-no-escapes
605 -> IdEnv (Id, HowBound) -- Use the Id at all occurrences; it has correct
606 -- arity information inside it.
607 -> StgLiveVars -- vars live in continuation
615 Bool -- True <=> bound at top level
616 StgLiveVars -- Live vars... see notes below
618 isLetrecBound (LetrecBound _ _) = True
619 isLetrecBound other = False
622 For a let(rec)-bound variable, x, we record what varibles are live if
623 x is live. For "normal" variables that is just x alone. If x is
624 a let-no-escaped variable then x is represented by a code pointer and
625 a stack pointer (well, one for each stack). So all of the variables
626 needed in the execution of x are live if x is, and are therefore recorded
627 in the LetrecBound constructor; x itself *is* included.
629 The std monad functions:
631 initLne :: Bool -> LneM a -> a
632 initLne want_LNEs m = m want_LNEs nullIdEnv emptyIdSet
634 {-# INLINE thenLne #-}
635 {-# INLINE thenLne_ #-}
636 {-# INLINE returnLne #-}
638 returnLne :: a -> LneM a
639 returnLne e sw env lvs_cont = e
641 thenLne :: LneM a -> (a -> LneM b) -> LneM b
642 thenLne m k sw env lvs_cont
643 = case (m sw env lvs_cont) of
644 m_result -> k m_result sw env lvs_cont
646 thenLne_ :: LneM a -> LneM b -> LneM b
647 thenLne_ m k sw env lvs_cont
648 = case (m sw env lvs_cont) of
649 _ -> k sw env lvs_cont
651 mapLne :: (a -> LneM b) -> [a] -> LneM [b]
652 mapLne f [] = returnLne []
654 = f x `thenLne` \ r ->
655 mapLne f xs `thenLne` \ rs ->
658 mapAndUnzipLne :: (a -> LneM (b,c)) -> [a] -> LneM ([b],[c])
660 mapAndUnzipLne f [] = returnLne ([],[])
661 mapAndUnzipLne f (x:xs)
662 = f x `thenLne` \ (r1, r2) ->
663 mapAndUnzipLne f xs `thenLne` \ (rs1, rs2) ->
664 returnLne (r1:rs1, r2:rs2)
666 mapAndUnzip3Lne :: (a -> LneM (b,c,d)) -> [a] -> LneM ([b],[c],[d])
668 mapAndUnzip3Lne f [] = returnLne ([],[],[])
669 mapAndUnzip3Lne f (x:xs)
670 = f x `thenLne` \ (r1, r2, r3) ->
671 mapAndUnzip3Lne f xs `thenLne` \ (rs1, rs2, rs3) ->
672 returnLne (r1:rs1, r2:rs2, r3:rs3)
674 fixLne :: (a -> LneM a) -> LneM a
675 fixLne expr sw env lvs_cont = result
677 result = expr result sw env lvs_cont
678 -- ^^^^^^ ------ ^^^^^^
681 Functions specific to this monad:
683 isSwitchSetLne :: LneM Bool
684 isSwitchSetLne want_LNEs env lvs_cont
687 getVarsLiveInCont :: LneM StgLiveVars
688 getVarsLiveInCont sw env lvs_cont = lvs_cont
690 setVarsLiveInCont :: StgLiveVars -> LneM a -> LneM a
691 setVarsLiveInCont new_lvs_cont expr sw env lvs_cont
692 = expr sw env new_lvs_cont
694 extendVarEnv :: [(Id, HowBound)] -> LneM a -> LneM a
695 extendVarEnv ids_w_howbound expr sw env lvs_cont
696 = expr sw (growIdEnvList env [(id, pair) | pair@(id,_) <- ids_w_howbound]) lvs_cont
699 lookupVarEnv :: Id -> LneM (Id, HowBound)
700 lookupVarEnv v sw env lvs_cont
702 case (lookupIdEnv env v) of
704 Nothing -> --false:ASSERT(not (isLocallyDefined v))
708 -- The result of lookupLiveVarsForSet, a set of live variables, is
709 -- only ever tacked onto a decorated expression. It is never used as
710 -- the basis of a control decision, which might give a black hole.
712 lookupLiveVarsForSet :: FreeVarsInfo -> LneM StgLiveVars
714 lookupLiveVarsForSet fvs sw env lvs_cont
715 = returnLne (unionManyIdSets (map do_one (getFVs fvs)))
719 = if isLocallyDefined v then
720 case (lookupIdEnv env v) of
721 Just (_, LetrecBound _ lvs) -> addOneToIdSet lvs v
722 Just _ -> unitIdSet v
723 Nothing -> pprPanic "lookupVarEnv/do_one:" (ppr v)
729 %************************************************************************
731 \subsection[Free-var info]{Free variable information}
733 %************************************************************************
736 type FreeVarsInfo = IdEnv (Id, Bool, StgBinderInfo)
737 -- If f is mapped to NoStgBinderInfo, that means
738 -- that f *is* mentioned (else it wouldn't be in the
739 -- IdEnv at all), but only in a saturated applications.
741 -- All case/lambda-bound things are also mapped to
742 -- NoStgBinderInfo, since we aren't interested in their
745 -- The Bool is True <=> the Id is top level letrec bound
747 type EscVarsSet = IdSet
751 emptyFVInfo :: FreeVarsInfo
752 emptyFVInfo = nullIdEnv
754 singletonFVInfo :: Id -> HowBound -> StgBinderInfo -> FreeVarsInfo
755 singletonFVInfo id ImportBound info = nullIdEnv
756 singletonFVInfo id (LetrecBound top_level _) info = unitIdEnv id (id, top_level, info)
757 singletonFVInfo id other info = unitIdEnv id (id, False, info)
759 unionFVInfo :: FreeVarsInfo -> FreeVarsInfo -> FreeVarsInfo
760 unionFVInfo fv1 fv2 = combineIdEnvs plusFVInfo fv1 fv2
762 unionFVInfos :: [FreeVarsInfo] -> FreeVarsInfo
763 unionFVInfos fvs = foldr unionFVInfo emptyFVInfo fvs
765 minusFVBinders :: FreeVarsInfo -> [Id] -> FreeVarsInfo
766 minusFVBinders fv ids = fv `delManyFromIdEnv` ids
768 elementOfFVInfo :: Id -> FreeVarsInfo -> Bool
769 elementOfFVInfo id fvs = maybeToBool (lookupIdEnv fvs id)
771 lookupFVInfo :: FreeVarsInfo -> Id -> StgBinderInfo
772 lookupFVInfo fvs id = case lookupIdEnv fvs id of
773 Nothing -> NoStgBinderInfo
774 Just (_,_,info) -> info
776 getFVs :: FreeVarsInfo -> [Id] -- Non-top-level things only
777 getFVs fvs = [id | (id,False,_) <- rngIdEnv fvs]
779 getFVSet :: FreeVarsInfo -> IdSet
780 getFVSet fvs = mkIdSet (getFVs fvs)
782 plusFVInfo (id1,top1,info1) (id2,top2,info2)
783 = ASSERT (id1 == id2 && top1 == top2)
784 (id1, top1, combineStgBinderInfo info1 info2)
788 rhsArity :: StgRhs -> Arity
789 rhsArity (StgRhsCon _ _ _) = 0
790 rhsArity (StgRhsClosure _ _ _ _ args _) = length args
793 zapArity id = id `addIdArity` UnknownArity