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 #include "HsVersions.h"
12 module StgVarInfo ( setStgVarInfo ) where
18 import Id ( emptyIdSet, mkIdSet, minusIdSet,
19 unionIdSets, unionManyIdSets, isEmptyIdSet,
20 unitIdSet, intersectIdSets,
21 addIdArity, getIdArity,
22 addOneToIdSet, SYN_IE(IdSet),
23 nullIdEnv, growIdEnvList, lookupIdEnv,
24 unitIdEnv, combineIdEnvs, delManyFromIdEnv,
25 rngIdEnv, SYN_IE(IdEnv),
26 GenId{-instance Eq-}, SYN_IE(Id)
28 import IdInfo ( ArityInfo(..) )
29 import Maybes ( maybeToBool )
30 import Name ( isLocallyDefined )
31 import TyCon ( SYN_IE(Arity) )
32 import PprStyle ( PprStyle(..) )
33 import PprType ( GenType{-instance Outputable-} )
34 import Util ( panic, pprPanic, assertPanic )
36 #if __GLASGOW_HASKELL__ >= 202
37 import Outputable ( Outputable(..) )
39 infixr 9 `thenLne`, `thenLne_`
42 %************************************************************************
44 \subsection[live-vs-free-doc]{Documentation}
46 %************************************************************************
48 (There is other relevant documentation in codeGen/CgLetNoEscape.)
50 March 97: setStgVarInfo guarantees to leave every variable's arity correctly
51 set. The lambda lifter makes some let-bound variables (which have arities)
52 and turns them into lambda-bound ones (which should not, else we get Vap trouble),
53 so this guarantee is necessary, as well as desirable.
55 The arity information is used in the code generator, when deciding if
56 a right-hand side is a saturated application so we can generate a VAP
59 The actual Stg datatype is decorated with {\em live variable}
60 information, as well as {\em free variable} information. The two are
61 {\em not} the same. Liveness is an operational property rather than a
62 semantic one. A variable is live at a particular execution point if
63 it can be referred to {\em directly} again. In particular, a dead
64 variable's stack slot (if it has one):
67 should be stubbed to avoid space leaks, and
69 may be reused for something else.
72 There ought to be a better way to say this. Here are some examples:
79 Just after the `in', v is live, but q is dead. If the whole of that
80 let expression was enclosed in a case expression, thus:
82 case (let v = [q] \[x] -> e in ...v...) of
85 (ie @alts@ mention @q@), then @q@ is live even after the `in'; because
86 we'll return later to the @alts@ and need it.
88 Let-no-escapes make this a bit more interesting:
90 let-no-escape v = [q] \ [x] -> e
94 Here, @q@ is still live at the `in', because @v@ is represented not by
95 a closure but by the current stack state. In other words, if @v@ is
96 live then so is @q@. Furthermore, if @e@ mentions an enclosing
97 let-no-escaped variable, then {\em its} free variables are also live
100 %************************************************************************
102 \subsection[binds-StgVarInfo]{Setting variable info: top-level, binds, RHSs}
104 %************************************************************************
108 setStgVarInfo :: Bool -- True <=> do let-no-escapes
109 -> [StgBinding] -- input
110 -> [StgBinding] -- result
112 setStgVarInfo want_LNEs pgm
115 (pgm', _) = initLne want_LNEs (varsTopBinds pgm)
119 For top-level guys, we basically aren't worried about this
120 live-variable stuff; we do need to keep adding to the environment
121 as we step through the bindings (using @extendVarEnv@).
124 varsTopBinds :: [StgBinding] -> LneM ([StgBinding], FreeVarsInfo)
126 varsTopBinds [] = returnLne ([], emptyFVInfo)
127 varsTopBinds (bind:binds)
128 = extendVarEnv env_extension (
129 varsTopBinds binds `thenLne` \ (binds', fv_binds) ->
130 varsTopBind binders' fv_binds bind `thenLne` \ (bind', fv_bind) ->
131 returnLne ((bind' : binds'),
132 (fv_binds `unionFVInfo` fv_bind) `minusFVBinders` binders'
138 StgNonRec binder rhs -> [(binder,rhs)]
139 StgRec pairs -> pairs
141 binders' = [ binder `addIdArity` ArityExactly (rhsArity rhs)
142 | (binder, rhs) <- pairs
145 env_extension = binders' `zip` repeat how_bound
147 how_bound = LetrecBound
152 varsTopBind :: [Id] -- New binders (with correct arity)
153 -> FreeVarsInfo -- Info about the body
155 -> LneM (StgBinding, FreeVarsInfo)
157 varsTopBind [binder'] body_fvs (StgNonRec binder rhs)
158 = varsRhs body_fvs (binder,rhs) `thenLne` \ (rhs2, fvs, _) ->
159 returnLne (StgNonRec binder' rhs2, fvs)
161 varsTopBind binders' body_fvs (StgRec pairs)
162 = fixLne (\ ~(_, rec_rhs_fvs) ->
164 scope_fvs = unionFVInfo body_fvs rec_rhs_fvs
166 mapAndUnzip3Lne (varsRhs scope_fvs) pairs `thenLne` \ (rhss2, fvss, _) ->
168 fvs = unionFVInfos fvss
170 returnLne (StgRec (binders' `zip` rhss2), fvs)
176 varsRhs :: FreeVarsInfo -- Free var info for the scope of the binding
178 -> LneM (StgRhs, FreeVarsInfo, EscVarsSet)
180 varsRhs scope_fv_info (binder, StgRhsCon cc con args)
181 = varsAtoms args `thenLne` \ (args', fvs) ->
182 returnLne (StgRhsCon cc con args', fvs, getFVSet fvs)
184 varsRhs scope_fv_info (binder, StgRhsClosure cc _ _ upd args body)
185 = extendVarEnv [ (zapArity a, LambdaBound) | a <- args ] (
186 do_body args body `thenLne` \ (body2, body_fvs, body_escs) ->
188 set_of_args = mkIdSet args
189 rhs_fvs = body_fvs `minusFVBinders` args
190 rhs_escs = body_escs `minusIdSet` set_of_args
191 binder_info = lookupFVInfo scope_fv_info binder
193 returnLne (StgRhsClosure cc binder_info (getFVs rhs_fvs) upd args body2,
197 -- Pick out special case of application in body of thunk
198 do_body [] (StgApp (StgVarArg f) args _) = varsApp (Just upd) f args
199 do_body _ other_body = varsExpr other_body
204 varsAtoms :: [StgArg]
205 -> LneM ([StgArg], FreeVarsInfo)
206 -- It's not *really* necessary to return fresh arguments,
207 -- because the only difference is that the argument variable
208 -- arities are correct. But it seems safer to do so.
211 = mapAndUnzipLne var_atom atoms `thenLne` \ (args', fvs_lists) ->
212 returnLne (args', unionFVInfos fvs_lists)
214 var_atom a@(StgLitArg _) = returnLne (a, emptyFVInfo)
215 var_atom a@(StgConArg _) = returnLne (a, emptyFVInfo)
216 var_atom a@(StgVarArg v)
217 = lookupVarEnv v `thenLne` \ (v', how_bound) ->
218 returnLne (StgVarArg v', singletonFVInfo v' how_bound stgArgOcc)
221 %************************************************************************
223 \subsection[expr-StgVarInfo]{Setting variable info on expressions}
225 %************************************************************************
227 @varsExpr@ carries in a monad-ised environment, which binds each
228 let(rec) variable (ie non top level, not imported, not lambda bound,
229 not case-alternative bound) to:
231 - its set of live vars.
232 For normal variables the set of live vars is just the variable
233 itself. For let-no-escaped variables, the set of live vars is the set
234 live at the moment the variable is entered. The set is guaranteed to
235 have no further let-no-escaped vars in it.
239 -> LneM (StgExpr, -- Decorated expr
240 FreeVarsInfo, -- Its free vars (NB free, not live)
241 EscVarsSet) -- Its escapees, a subset of its free vars;
242 -- also a subset of the domain of the envt
243 -- because we are only interested in the escapees
244 -- for vars which might be turned into
245 -- let-no-escaped ones.
248 The second and third components can be derived in a simple bottom up pass, not
249 dependent on any decisions about which variables will be let-no-escaped or
250 not. The first component, that is, the decorated expression, may then depend
251 on these components, but it in turn is not scrutinised as the basis for any
252 decisions. Hence no black holes.
255 varsExpr (StgApp lit@(StgLitArg _) args _)
256 = returnLne (StgApp lit [] emptyIdSet, emptyFVInfo, emptyIdSet)
258 varsExpr (StgApp lit@(StgConArg _) args _)
259 = panic "varsExpr StgConArg" -- Only occur in argument positions
261 varsExpr (StgApp fun@(StgVarArg f) args _) = varsApp Nothing f args
263 varsExpr (StgCon con args _)
264 = getVarsLiveInCont `thenLne` \ live_in_cont ->
265 varsAtoms args `thenLne` \ (args', args_fvs) ->
267 returnLne (StgCon con args' live_in_cont, args_fvs, getFVSet args_fvs)
269 varsExpr (StgPrim op args _)
270 = getVarsLiveInCont `thenLne` \ live_in_cont ->
271 varsAtoms args `thenLne` \ (args', args_fvs) ->
272 returnLne (StgPrim op args' live_in_cont, args_fvs, getFVSet args_fvs)
274 varsExpr (StgSCC ty label expr)
275 = varsExpr expr `thenLne` ( \ (expr2, fvs, escs) ->
276 returnLne (StgSCC ty label expr2, fvs, escs) )
279 Cases require a little more real work.
281 varsExpr (StgCase scrut _ _ uniq alts)
282 = getVarsLiveInCont `thenLne` \ live_in_cont ->
283 vars_alts alts `thenLne` \ (alts2, alts_fvs, alts_escs) ->
284 lookupLiveVarsForSet alts_fvs `thenLne` \ alts_lvs ->
286 live_in_alts = live_in_cont `unionIdSets` alts_lvs
288 -- we tell the scrutinee that everything live in the alts
289 -- is live in it, too.
290 setVarsLiveInCont live_in_alts (
292 ) `thenLne` \ (scrut2, scrut_fvs, scrut_escs) ->
293 lookupLiveVarsForSet scrut_fvs `thenLne` \ scrut_lvs ->
295 live_in_whole_case = live_in_alts `unionIdSets` scrut_lvs
298 StgCase scrut2 live_in_whole_case live_in_alts uniq alts2,
299 scrut_fvs `unionFVInfo` alts_fvs,
300 alts_escs `unionIdSets` (getFVSet scrut_fvs) -- All free vars in the scrutinee escape
303 vars_alts (StgAlgAlts ty alts deflt)
304 = mapAndUnzip3Lne vars_alg_alt alts
305 `thenLne` \ (alts2, alts_fvs_list, alts_escs_list) ->
307 alts_fvs = unionFVInfos alts_fvs_list
308 alts_escs = unionManyIdSets alts_escs_list
310 vars_deflt deflt `thenLne` \ (deflt2, deflt_fvs, deflt_escs) ->
312 StgAlgAlts ty alts2 deflt2,
313 alts_fvs `unionFVInfo` deflt_fvs,
314 alts_escs `unionIdSets` deflt_escs
317 vars_alg_alt (con, binders, worthless_use_mask, rhs)
318 = extendVarEnv [(zapArity b, CaseBound) | b <- binders] (
319 varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
321 good_use_mask = [ b `elementOfFVInfo` rhs_fvs | b <- binders ]
322 -- records whether each param is used in the RHS
325 (con, binders, good_use_mask, rhs2),
326 rhs_fvs `minusFVBinders` binders,
327 rhs_escs `minusIdSet` mkIdSet binders -- ToDo: remove the minusIdSet;
328 -- since escs won't include
329 -- any of these binders
332 vars_alts (StgPrimAlts ty alts deflt)
333 = mapAndUnzip3Lne vars_prim_alt alts
334 `thenLne` \ (alts2, alts_fvs_list, alts_escs_list) ->
336 alts_fvs = unionFVInfos alts_fvs_list
337 alts_escs = unionManyIdSets alts_escs_list
339 vars_deflt deflt `thenLne` \ (deflt2, deflt_fvs, deflt_escs) ->
341 StgPrimAlts ty alts2 deflt2,
342 alts_fvs `unionFVInfo` deflt_fvs,
343 alts_escs `unionIdSets` deflt_escs
346 vars_prim_alt (lit, rhs)
347 = varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
348 returnLne ((lit, rhs2), rhs_fvs, rhs_escs)
350 vars_deflt StgNoDefault
351 = returnLne (StgNoDefault, emptyFVInfo, emptyIdSet)
353 vars_deflt (StgBindDefault binder _ rhs)
354 = extendVarEnv [(zapArity binder, CaseBound)] (
355 varsExpr rhs `thenLne` \ (rhs2, rhs_fvs, rhs_escs) ->
357 used_in_rhs = binder `elementOfFVInfo` rhs_fvs
360 StgBindDefault binder used_in_rhs rhs2,
361 rhs_fvs `minusFVBinders` [binder],
362 rhs_escs `minusIdSet` unitIdSet binder
366 Lets not only take quite a bit of work, but this is where we convert
367 then to let-no-escapes, if we wish.
369 (Meanwhile, we don't expect to see let-no-escapes...)
371 varsExpr (StgLetNoEscape _ _ _ _) = panic "varsExpr: unexpected StgLetNoEscape"
373 varsExpr (StgLet bind body)
374 = isSwitchSetLne {-StgDoLetNoEscapes-} `thenLne` \ want_LNEs ->
376 (fixLne (\ ~(_, _, _, no_binder_escapes) ->
378 non_escaping_let = want_LNEs && no_binder_escapes
380 vars_let non_escaping_let bind body
381 )) `thenLne` \ (new_let, fvs, escs, _) ->
383 returnLne (new_let, fvs, escs)
388 varsApp :: Maybe UpdateFlag -- Just upd <=> this application is
389 -- the rhs of a thunk binding
390 -- x = [...] \upd [] -> the_app
391 -- with specified update flag
393 -> [StgArg] -- Arguments
394 -> LneM (StgExpr, FreeVarsInfo, EscVarsSet)
396 varsApp maybe_thunk_body f args
397 = getVarsLiveInCont `thenLne` \ live_in_cont ->
399 varsAtoms args `thenLne` \ (args', args_fvs) ->
401 lookupVarEnv f `thenLne` \ (f', how_bound) ->
405 not_letrec_bound = not (isLetrecBound how_bound)
406 f_arity = getIdArity f'
407 fun_fvs = singletonFVInfo f' how_bound fun_occ
411 = NoStgBinderInfo -- Uninteresting variable
413 | otherwise -- Letrec bound; must have its arity
416 | n_args == 0 -> stgFakeFunAppOcc -- Function Application
417 -- with no arguments.
418 -- used by the lambda lifter.
419 | arity > n_args -> stgUnsatOcc -- Unsaturated
423 maybeToBool maybe_thunk_body -> -- Exactly saturated,
425 case maybe_thunk_body of
426 Just Updatable -> stgStdHeapOcc
427 Just SingleEntry -> stgNoUpdHeapOcc
428 other -> panic "varsApp"
430 | otherwise -> stgNormalOcc
431 -- Record only that it occurs free
433 myself = unitIdSet f'
435 fun_escs | not_letrec_bound = emptyIdSet -- Only letrec-bound escapees are interesting
436 | otherwise = case f_arity of -- Letrec bound, so must have its arity
438 | arity == n_args -> emptyIdSet
439 -- Function doesn't escape
440 | otherwise -> myself
441 -- Inexact application; it does escape
443 -- At the moment of the call:
445 -- either the function is *not* let-no-escaped, in which case
446 -- nothing is live except live_in_cont
447 -- or the function *is* let-no-escaped in which case the
448 -- variables it uses are live, but still the function
449 -- itself is not. PS. In this case, the function's
450 -- live vars should already include those of the
451 -- continuation, but it does no harm to just union the
455 = live_in_cont `unionIdSets` case how_bound of
456 LetrecBound _ lvs -> lvs `minusIdSet` myself
460 StgApp (StgVarArg f') args' live_at_call,
461 fun_fvs `unionFVInfo` args_fvs,
462 fun_escs `unionIdSets` (getFVSet args_fvs)
463 -- All the free vars of the args are disqualified
464 -- from being let-no-escaped.
470 vars_let :: Bool -- True <=> yes, we are let-no-escaping this let
471 -> StgBinding -- bindings
473 -> LneM (StgExpr, -- new let
474 FreeVarsInfo, -- variables free in the whole let
475 EscVarsSet, -- variables that escape from the whole let
476 Bool) -- True <=> none of the binders in the bindings
477 -- is among the escaping vars
479 vars_let let_no_escape bind body
480 = fixLne (\ ~(_, _, _, rec_bind_lvs, _, rec_body_fvs, _, _) ->
482 -- Do the bindings, setting live_in_cont to empty if
483 -- we ain't in a let-no-escape world
484 getVarsLiveInCont `thenLne` \ live_in_cont ->
486 (if let_no_escape then live_in_cont else emptyIdSet)
487 (vars_bind rec_bind_lvs rec_body_fvs bind)
488 `thenLne` \ (bind2, bind_fvs, bind_escs, env_ext) ->
490 -- The live variables of this binding are the ones which are live
491 -- by virtue of being accessible via the free vars of the binding (lvs_from_fvs)
492 -- together with the live_in_cont ones
493 lookupLiveVarsForSet (bind_fvs `minusFVBinders` binders) `thenLne` \ lvs_from_fvs ->
495 bind_lvs = lvs_from_fvs `unionIdSets` live_in_cont
498 -- bind_fvs and bind_escs still include the binders of the let(rec)
499 -- but bind_lvs does not
502 extendVarEnv env_ext (
503 varsExpr body `thenLne` \ (body2, body_fvs, body_escs) ->
504 lookupLiveVarsForSet body_fvs `thenLne` \ body_lvs ->
506 returnLne (bind2, bind_fvs, bind_escs, bind_lvs,
507 body2, body_fvs, body_escs, body_lvs)
509 )) `thenLne` (\ (bind2, bind_fvs, bind_escs, bind_lvs,
510 body2, body_fvs, body_escs, body_lvs) ->
513 -- Compute the new let-expression
515 new_let = if let_no_escape then
516 -- trace "StgLetNoEscape!" (
517 StgLetNoEscape live_in_whole_let bind_lvs bind2 body2
523 = (bind_fvs `unionFVInfo` body_fvs) `minusFVBinders` binders
526 = bind_lvs `unionIdSets` (body_lvs `minusIdSet` set_of_binders)
528 real_bind_escs = if let_no_escape then
532 -- Everything escapes which is free in the bindings
534 let_escs = (real_bind_escs `unionIdSets` body_escs) `minusIdSet` set_of_binders
536 all_escs = bind_escs `unionIdSets` body_escs -- Still includes binders of
539 no_binder_escapes = isEmptyIdSet (set_of_binders `intersectIdSets` all_escs)
540 -- Mustn't depend on the passed-in let_no_escape flag, since
541 -- no_binder_escapes is used by the caller to derive the flag!
550 set_of_binders = mkIdSet binders
551 binders = case bind of
552 StgNonRec binder rhs -> [binder]
553 StgRec pairs -> map fst pairs
555 mk_binding bind_lvs (binder,rhs)
556 = (binder `addIdArity` ArityExactly (stgArity rhs),
557 LetrecBound False -- Not top level
561 live_vars = if let_no_escape then
562 addOneToIdSet bind_lvs binder
566 vars_bind :: StgLiveVars
567 -> FreeVarsInfo -- Free var info for body of binding
570 FreeVarsInfo, EscVarsSet, -- free vars; escapee vars
572 -- extension to environment
574 vars_bind rec_bind_lvs rec_body_fvs (StgNonRec binder rhs)
575 = varsRhs rec_body_fvs (binder,rhs) `thenLne` \ (rhs2, fvs, escs) ->
577 env_ext_item@(binder', _) = mk_binding rec_bind_lvs (binder,rhs)
579 returnLne (StgNonRec binder' rhs2, fvs, escs, [env_ext_item])
581 vars_bind rec_bind_lvs rec_body_fvs (StgRec pairs)
583 env_ext = map (mk_binding rec_bind_lvs) pairs
584 binders' = map fst env_ext
586 extendVarEnv env_ext (
587 fixLne (\ ~(_, rec_rhs_fvs, _, _) ->
589 rec_scope_fvs = unionFVInfo rec_body_fvs rec_rhs_fvs
591 mapAndUnzip3Lne (varsRhs rec_scope_fvs) pairs `thenLne` \ (rhss2, fvss, escss) ->
593 fvs = unionFVInfos fvss
594 escs = unionManyIdSets escss
596 returnLne (StgRec (binders' `zip` rhss2), fvs, escs, env_ext)
600 %************************************************************************
602 \subsection[LNE-monad]{A little monad for this let-no-escaping pass}
604 %************************************************************************
606 There's a lot of stuff to pass around, so we use this @LneM@ monad to
607 help. All the stuff here is only passed {\em down}.
610 type LneM a = Bool -- True <=> do let-no-escapes
611 -> IdEnv (Id, HowBound) -- Use the Id at all occurrences; it has correct
612 -- arity information inside it.
613 -> StgLiveVars -- vars live in continuation
621 Bool -- True <=> bound at top level
622 StgLiveVars -- Live vars... see notes below
624 isLetrecBound (LetrecBound _ _) = True
625 isLetrecBound other = False
628 For a let(rec)-bound variable, x, we record what varibles are live if
629 x is live. For "normal" variables that is just x alone. If x is
630 a let-no-escaped variable then x is represented by a code pointer and
631 a stack pointer (well, one for each stack). So all of the variables
632 needed in the execution of x are live if x is, and are therefore recorded
633 in the LetrecBound constructor; x itself *is* included.
635 The std monad functions:
637 initLne :: Bool -> LneM a -> a
638 initLne want_LNEs m = m want_LNEs nullIdEnv emptyIdSet
640 {-# INLINE thenLne #-}
641 {-# INLINE thenLne_ #-}
642 {-# INLINE returnLne #-}
644 returnLne :: a -> LneM a
645 returnLne e sw env lvs_cont = e
647 thenLne :: LneM a -> (a -> LneM b) -> LneM b
648 thenLne m k sw env lvs_cont
649 = case (m sw env lvs_cont) of
650 m_result -> k m_result sw env lvs_cont
652 thenLne_ :: LneM a -> LneM b -> LneM b
653 thenLne_ m k sw env lvs_cont
654 = case (m sw env lvs_cont) of
655 _ -> k sw env lvs_cont
657 mapLne :: (a -> LneM b) -> [a] -> LneM [b]
658 mapLne f [] = returnLne []
660 = f x `thenLne` \ r ->
661 mapLne f xs `thenLne` \ rs ->
664 mapAndUnzipLne :: (a -> LneM (b,c)) -> [a] -> LneM ([b],[c])
666 mapAndUnzipLne f [] = returnLne ([],[])
667 mapAndUnzipLne f (x:xs)
668 = f x `thenLne` \ (r1, r2) ->
669 mapAndUnzipLne f xs `thenLne` \ (rs1, rs2) ->
670 returnLne (r1:rs1, r2:rs2)
672 mapAndUnzip3Lne :: (a -> LneM (b,c,d)) -> [a] -> LneM ([b],[c],[d])
674 mapAndUnzip3Lne f [] = returnLne ([],[],[])
675 mapAndUnzip3Lne f (x:xs)
676 = f x `thenLne` \ (r1, r2, r3) ->
677 mapAndUnzip3Lne f xs `thenLne` \ (rs1, rs2, rs3) ->
678 returnLne (r1:rs1, r2:rs2, r3:rs3)
680 fixLne :: (a -> LneM a) -> LneM a
681 fixLne expr sw env lvs_cont = result
683 result = expr result sw env lvs_cont
684 -- ^^^^^^ ------ ^^^^^^
687 Functions specific to this monad:
689 isSwitchSetLne :: LneM Bool
690 isSwitchSetLne want_LNEs env lvs_cont
693 getVarsLiveInCont :: LneM StgLiveVars
694 getVarsLiveInCont sw env lvs_cont = lvs_cont
696 setVarsLiveInCont :: StgLiveVars -> LneM a -> LneM a
697 setVarsLiveInCont new_lvs_cont expr sw env lvs_cont
698 = expr sw env new_lvs_cont
700 extendVarEnv :: [(Id, HowBound)] -> LneM a -> LneM a
701 extendVarEnv ids_w_howbound expr sw env lvs_cont
702 = expr sw (growIdEnvList env [(id, pair) | pair@(id,_) <- ids_w_howbound]) lvs_cont
705 lookupVarEnv :: Id -> LneM (Id, HowBound)
706 lookupVarEnv v sw env lvs_cont
708 case (lookupIdEnv env v) of
710 Nothing -> --false:ASSERT(not (isLocallyDefined v))
714 -- The result of lookupLiveVarsForSet, a set of live variables, is
715 -- only ever tacked onto a decorated expression. It is never used as
716 -- the basis of a control decision, which might give a black hole.
718 lookupLiveVarsForSet :: FreeVarsInfo -> LneM StgLiveVars
720 lookupLiveVarsForSet fvs sw env lvs_cont
721 = returnLne (unionManyIdSets (map do_one (getFVs fvs)))
725 = if isLocallyDefined v then
726 case (lookupIdEnv env v) of
727 Just (_, LetrecBound _ lvs) -> addOneToIdSet lvs v
728 Just _ -> unitIdSet v
729 Nothing -> pprPanic "lookupVarEnv/do_one:" (ppr PprShowAll v)
735 %************************************************************************
737 \subsection[Free-var info]{Free variable information}
739 %************************************************************************
742 type FreeVarsInfo = IdEnv (Id, Bool, StgBinderInfo)
743 -- If f is mapped to NoStgBinderInfo, that means
744 -- that f *is* mentioned (else it wouldn't be in the
745 -- IdEnv at all), but only in a saturated applications.
747 -- All case/lambda-bound things are also mapped to
748 -- NoStgBinderInfo, since we aren't interested in their
751 -- The Bool is True <=> the Id is top level letrec bound
753 type EscVarsSet = IdSet
757 emptyFVInfo :: FreeVarsInfo
758 emptyFVInfo = nullIdEnv
760 singletonFVInfo :: Id -> HowBound -> StgBinderInfo -> FreeVarsInfo
761 singletonFVInfo id ImportBound info = nullIdEnv
762 singletonFVInfo id (LetrecBound top_level _) info = unitIdEnv id (id, top_level, info)
763 singletonFVInfo id other info = unitIdEnv id (id, False, info)
765 unionFVInfo :: FreeVarsInfo -> FreeVarsInfo -> FreeVarsInfo
766 unionFVInfo fv1 fv2 = combineIdEnvs plusFVInfo fv1 fv2
768 unionFVInfos :: [FreeVarsInfo] -> FreeVarsInfo
769 unionFVInfos fvs = foldr unionFVInfo emptyFVInfo fvs
771 minusFVBinders :: FreeVarsInfo -> [Id] -> FreeVarsInfo
772 minusFVBinders fv ids = fv `delManyFromIdEnv` ids
774 elementOfFVInfo :: Id -> FreeVarsInfo -> Bool
775 elementOfFVInfo id fvs = maybeToBool (lookupIdEnv fvs id)
777 lookupFVInfo :: FreeVarsInfo -> Id -> StgBinderInfo
778 lookupFVInfo fvs id = case lookupIdEnv fvs id of
779 Nothing -> NoStgBinderInfo
780 Just (_,_,info) -> info
782 getFVs :: FreeVarsInfo -> [Id] -- Non-top-level things only
783 getFVs fvs = [id | (id,False,_) <- rngIdEnv fvs]
785 getFVSet :: FreeVarsInfo -> IdSet
786 getFVSet fvs = mkIdSet (getFVs fvs)
788 plusFVInfo (id1,top1,info1) (id2,top2,info2)
789 = ASSERT (id1 == id2 && top1 == top2)
790 (id1, top1, combineStgBinderInfo info1 info2)
794 rhsArity :: StgRhs -> Arity
795 rhsArity (StgRhsCon _ _ _) = 0
796 rhsArity (StgRhsClosure _ _ _ _ args _) = length args
799 zapArity id = id `addIdArity` UnknownArity