[project @ 1999-03-02 14:34:33 by sof]
[ghc-hetmet.git] / ghc / compiler / simplStg / SRT.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1998
3 %
4
5 Run through the STG code and compute the Static Reference Table for
6 each let-binding.  At the same time, we figure out which top-level
7 bindings have no CAF references, and record the fact in their IdInfo.
8
9 \begin{code}
10 module SRT where
11
12 import Id       ( Id, setIdCafInfo, getIdCafInfo, externallyVisibleId,
13                   idAppIsBottom
14                 )
15 import IdInfo   ( CafInfo(..) )
16 import StgSyn
17
18 import UniqFM
19 import UniqSet
20 \end{code}
21
22 \begin{code}
23 computeSRTs :: [StgBinding] -> [(StgBinding,[Id])]
24 computeSRTs binds = srtBinds emptyUFM binds
25 \end{code}
26
27 \begin{code}
28 srtBinds :: UniqFM CafInfo -> [StgBinding] -> [(StgBinding,[Id])] 
29 srtBinds rho [] = []
30 srtBinds rho (b:bs) = 
31         srtTopBind rho b   =: \(b, srt, rho) ->
32         (b,srt) : srtBinds rho bs
33 \end{code}
34
35 -----------------------------------------------------------------------------
36 Circular algorithm for simultaneously figuring out CafInfo and SRT
37 layout.
38
39 Our functions have type
40
41         :: UniqFM CafInfo       -- which top-level ids don't refer to any CAfs
42         -> SrtOffset            -- next free offset within the SRT
43 {- * -} -> StgExpr              -- expression to analyse
44
45         -> (StgExpr,            -- (e) newly annotated expression
46             UniqSet Id,         -- (g) set of *all* global references
47             [Id],               -- (s) SRT required for this expression
48             SrtOffset)          -- (o) new offset
49
50 (g) is a set containing all local top-level and imported ids referred
51 to by the expression (e).
52
53 The set of all global references is used to build the environment,
54 which is passed in again.  The environment is used to build the final
55 SRT.
56
57 We build a single SRT for a recursive binding group, which is why the
58 SRT building is done at the binding level rather than the
59 StgRhsClosure level.
60
61 Hence, the only argument which we can look at before returning is the
62 expression (marked with {- * -} above).
63
64 The SRT is built up in reverse order, to avoid too many expensive
65 appends.  We therefore reverse the SRT before returning it, so that
66 the offsets will be from the beginning of the SRT.
67
68 -----------------------------------------------------------------------------
69 Top-level Bindings
70
71 The environment contains a mapping from local top-level bindings to
72 CafInfo.  The CafInfo is either
73
74         NoCafRefs      - indicating that the id is not a CAF and furthermore
75                          that it doesn't refer, even indirectly, to any CAFs.
76         
77         MayHaveCafRefs - everything else.
78
79 A function whose CafInfo is NoCafRefs will have an empty SRT, and its
80 closure will not appear in the SRT of any other function (unless we're
81 compiling without optimisation and the CafInfos haven't been emitted
82 in the interface files).
83
84 Top-Level recursive groups
85
86 This gets a bit complicated, but the general idea is that we want a
87 single SRT for the whole group, and we'd rather not have recursive
88 references in it if at all possible.
89
90 We collect all the global references for the group, and filter out
91 those that are binders in the group and not CAFs themselves.  This set
92 of references is then used to infer the CafInfo for each of the
93 binders in the group.  Why is it done this way?
94
95         - if all the bindings in the group just refer to each other,
96           and none of them are CAFs, we'd like to get an empty SRT.
97
98         - if any of the bindings in the group refer to a CAF, this will
99           appear in the SRT.
100
101 Hmm, that probably makes no sense.
102
103 \begin{code}
104 srtTopBind 
105         :: UniqFM CafInfo
106         -> StgBinding
107         -> (StgBinding,                 -- the new binding
108             [Id],                       -- the SRT for this binding
109             UniqFM CafInfo)             -- the new environment
110
111 srtTopBind rho (StgNonRec binder rhs) =
112
113    -- no need to use circularity for non-recursive bindings
114    srtRhs rho 0{-initial offset-} rhs           =: \(rhs, g, srt, off) ->
115    let
116         filtered_g = filter (mayHaveCafRefs rho) (uniqSetToList g)
117         caf_info   = mk_caf_info rhs filtered_g
118         binder'    = setIdCafInfo binder caf_info
119         rho'       = addToUFM rho binder' caf_info
120         extra_refs = filter (`notElem` srt) filtered_g
121         bind_srt   = reverse (extra_refs ++ srt)
122    in
123    case rhs of
124         StgRhsClosure _ _ _ _ _ _ _ ->
125             (StgNonRec binder' (attach_srt_rhs rhs 0 (length bind_srt)), 
126              bind_srt, rho')
127
128         -- don't output an SRT for the constructor, but just remember
129         -- whether it had any caf references or not.
130         StgRhsCon _ _ _    -> (StgNonRec binder' rhs, [], rho')
131
132
133 srtTopBind rho (StgRec bs) =
134     (attach_srt_bind (StgRec (reverse new_bs')) 0 (length bind_srt), 
135         bind_srt, rho')
136   where
137     (binders,rhss) = unzip bs
138     
139     non_caf_binders = [ b | (b, rhs) <- bs, not (caf_rhs rhs) ]
140
141     -- circular: rho' is calculated from g below
142     (new_bs, g, srt, _) = doBinds bs [] emptyUniqSet [] 0
143
144     -- filter out ourselves from the global references: it makes no
145     -- sense to refer recursively to our SRT unless the recursive
146     -- reference is required by a nested SRT.
147     filtered_g = filter (\id -> id `notElem` non_caf_binders && 
148                                 mayHaveCafRefs rho id) (uniqSetToList g)
149     extra_refs = filter (`notElem` srt) filtered_g
150     bind_srt = reverse (extra_refs ++ srt)
151     caf_infos = map (\rhs -> mk_caf_info rhs filtered_g) rhss
152     rho' = addListToUFM rho (zip binders caf_infos)
153     binders' = zipWith setIdCafInfo binders caf_infos
154
155     new_bs' = zip binders' (map snd new_bs)
156
157     doBinds [] new_binds g srt off = (reverse new_binds, g, srt, off)
158     doBinds ((binder,rhs):binds) new_binds g srt off =
159         srtRhs rho' off rhs =: \(rhs, rhs_g, rhs_srt, off) ->
160         let 
161             g'   = unionUniqSets rhs_g g
162             srt' = rhs_srt ++ srt
163         in
164         doBinds binds ((binder,rhs):new_binds) g' srt' off
165
166 caf_rhs (StgRhsClosure _ _ _ free_vars _ [] body) = True
167 caf_rhs _ = False
168 \end{code}
169
170 -----------------------------------------------------------------------------
171 Non-top-level bindings
172
173 \begin{code}
174 srtBind :: UniqFM CafInfo -> Int -> StgBinding
175         -> (StgBinding, UniqSet Id, [Id], Int)
176
177 srtBind rho off (StgNonRec binder rhs) =
178   srtRhs rho off rhs   =: \(rhs, g, srt, off) ->
179   (StgNonRec binder rhs, g, srt, off)
180
181 srtBind rho off (StgRec binds) =
182     (StgRec new_binds, g, srt, new_off)
183   where
184     -- process each binding
185     (new_binds, g, srt, new_off) = doBinds binds emptyUniqSet [] off []
186
187     doBinds [] g srt off new_binds = (reverse new_binds, g, srt, off)
188     doBinds ((binder,rhs):binds) g srt off new_binds =
189         srtRhs rho off rhs   =: \(rhs, g', srt', off) ->
190         doBinds binds (unionUniqSets g g') (srt'++srt) off
191                 ((binder,rhs):new_binds)
192 \end{code}
193
194 -----------------------------------------------------------------------------
195 Right Hand Sides
196
197 \begin{code}
198 srtRhs :: UniqFM CafInfo -> Int -> StgRhs
199         -> (StgRhs, UniqSet Id, [Id], Int)
200
201 srtRhs rho off (StgRhsClosure cc bi old_srt free_vars u args body) =
202     srtExpr rho off body        =: \(body, g, srt, off) ->
203     (StgRhsClosure cc bi old_srt free_vars u args body, g, srt, off)
204
205 srtRhs rho off e@(StgRhsCon cc con args) =
206     (e, getGlobalRefs rho args, [], off)
207 \end{code}
208
209 -----------------------------------------------------------------------------
210 Expressions
211
212 \begin{code}
213 srtExpr :: UniqFM CafInfo -> Int -> StgExpr 
214         -> (StgExpr, UniqSet Id, [Id], Int)
215
216 srtExpr rho off e@(StgApp f args) =
217    (e, getGlobalRefs rho (StgVarArg f:args), [], off)
218
219 srtExpr rho off e@(StgCon con args ty) =
220    (e, getGlobalRefs rho args, [], off)
221
222 srtExpr rho off (StgCase scrut live1 live2 uniq _{-srt-} alts) =
223    srtCaseAlts rho off alts     =: \(alts, alts_g, alts_srt, alts_off) ->
224    let
225         extra_refs = filter (`notElem` alts_srt)
226                         (filter (mayHaveCafRefs rho) (uniqSetToList alts_g))
227         this_srt = extra_refs ++ alts_srt
228         scrut_off = alts_off + length extra_refs
229    in
230    srtExpr rho scrut_off scrut  =: \(scrut, scrut_g, scrut_srt, case_off) ->
231    let
232         g = unionUniqSets alts_g scrut_g
233         srt = scrut_srt ++ this_srt
234         srt_info = case length this_srt of
235                         0   -> NoSRT
236                         len -> SRT off len
237    in
238    (StgCase scrut live1 live2 uniq srt_info alts, g, srt, case_off)
239
240 srtExpr rho off (StgLet bind body) =
241    srtLet rho off bind body StgLet
242
243    -- let-no-escapes are delicate, see below
244 srtExpr rho off (StgLetNoEscape live1 live2 bind body) =
245    srtLet rho off bind body (StgLetNoEscape live1 live2) 
246                 =: \(expr, g, srt, off') ->
247    let
248         -- find the SRT for the *whole* expression
249         length = off' - off
250         all_srt | length == 0 = NoSRT
251                 | otherwise   = SRT off length
252    in
253    (fixLNE_srt all_srt expr, g, srt, off')
254
255 srtExpr rho off (StgSCC cc expr) =
256    srtExpr rho off expr         =: \(expr, g, srt, off) ->
257    (StgSCC cc expr, g, srt, off)
258 \end{code}
259
260 -----------------------------------------------------------------------------
261 Let-expressions
262
263 This is quite complicated stuff...
264
265 \begin{code}
266 srtLet rho off bind body let_constr
267
268  -- If the bindings are all constructors, then we don't need to
269  -- buid an SRT at all...
270  | all_con_binds bind =
271    srtBind rho off bind         =: \(bind, bind_g, bind_srt, off) ->
272    srtExpr rho off body         =: \(body, body_g, body_srt, off) ->
273    let
274         g   = unionUniqSets bind_g body_g
275         srt = body_srt ++ bind_srt
276    in
277    (let_constr bind body, g, srt, off)
278
279  -- we have some closure bindings...
280  | otherwise =
281
282     -- first, find the sub-SRTs in the binding
283    srtBind rho off bind         =: \(bind, bind_g, bind_srt, bind_off) ->
284
285    -- Construct the SRT for this binding from its sub-SRTs and any new global
286    -- references which aren't already contained in one of the sub-SRTs (and
287    -- which are "live").  
288    let
289        extra_refs = filter (`notElem` bind_srt) 
290                         (filter (mayHaveCafRefs rho) (uniqSetToList bind_g))
291        this_srt = extra_refs ++ bind_srt
292
293         -- Add the length of the new entries to the     
294         -- current offset to get the next free offset in the global SRT.
295        body_off = bind_off + length extra_refs
296    in
297
298    -- now find the SRTs in the body
299    srtExpr rho body_off body    =: \(body, body_g, body_srt, let_off) ->
300
301    let
302         -- union all the global references together
303        let_g   = unionUniqSets bind_g body_g
304
305         -- concatenate the sub-SRTs
306        let_srt = body_srt ++ this_srt
307
308         -- attach the SRT info to the binding
309        bind' = attach_srt_bind bind off (length this_srt)
310    in
311    (let_constr bind' body, let_g, let_srt, let_off)
312 \end{code}
313
314 -----------------------------------------------------------------------------
315 Case Alternatives
316
317 \begin{code}
318 srtCaseAlts :: UniqFM CafInfo -> Int -> StgCaseAlts ->
319         (StgCaseAlts, UniqSet Id, [Id], Int)
320
321 srtCaseAlts rho off (StgAlgAlts  t alts dflt) =
322    srtAlgAlts rho off alts [] emptyUniqSet []  
323                                   =: \(alts, alts_g, alts_srt, off) ->
324    srtDefault rho off dflt        =: \(dflt, dflt_g, dflt_srt, off) ->
325    let
326         g   = unionUniqSets alts_g dflt_g
327         srt = dflt_srt ++ alts_srt
328    in
329    (StgAlgAlts t alts dflt, g, srt, off)
330
331 srtCaseAlts rho off (StgPrimAlts t alts dflt) =
332    srtPrimAlts rho off alts [] emptyUniqSet []  
333                                    =: \(alts, alts_g, alts_srt, off) ->
334    srtDefault rho off dflt         =: \(dflt, dflt_g, dflt_srt, off) ->
335    let
336         g   = unionUniqSets alts_g dflt_g
337         srt = dflt_srt ++ alts_srt
338    in
339    (StgPrimAlts t alts dflt, g, srt, off)
340
341 srtAlgAlts rho off [] new_alts g srt = (reverse new_alts, g, srt, off)
342 srtAlgAlts rho off ((con,args,used,rhs):alts) new_alts g srt =
343    srtExpr rho off rhs          =: \(rhs, rhs_g, rhs_srt, off) ->
344    let
345         g'   = unionUniqSets rhs_g g
346         srt' = rhs_srt ++ srt
347    in
348    srtAlgAlts rho off alts ((con,args,used,rhs) : new_alts) g' srt'
349
350 srtPrimAlts rho off [] new_alts g srt = (reverse new_alts, g, srt, off)
351 srtPrimAlts rho off ((lit,rhs):alts) new_alts g srt =
352    srtExpr rho off rhs          =: \(rhs, rhs_g, rhs_srt, off) ->
353    let
354         g'   = unionUniqSets rhs_g g
355         srt' = rhs_srt ++ srt
356    in
357    srtPrimAlts rho off alts ((lit,rhs) : new_alts) g' srt'
358
359 srtDefault rho off StgNoDefault = (StgNoDefault,emptyUniqSet,[],off)
360 srtDefault rho off (StgBindDefault rhs) =
361    srtExpr rho off rhs          =: \(rhs, g, srt, off) ->
362    (StgBindDefault rhs, g, srt, off)
363 \end{code}
364
365 -----------------------------------------------------------------------------
366
367 Decide whether a closure looks like a CAF or not.  In an effort to
368 keep the number of CAFs (and hence the size of the SRTs) down, we
369 would also like to look at the expression and decide whether it
370 requires a small bounded amount of heap, so we can ignore it as a CAF.
371 In these cases, we need to use an additional CAF list to keep track of
372 non-collectable CAFs.
373
374 We mark real CAFs as `MayHaveCafRefs' because this information is used
375 to decide whether a particular closure needs to be referenced in an
376 SRT or not.
377
378 \begin{code}
379 mk_caf_info 
380         :: StgRhs                       -- right-hand-side of the definition
381         -> [Id]                         -- static references
382         -> CafInfo
383
384 -- special case for expressions which are always bottom,
385 -- such as 'error "..."'.  We don't need to record it as
386 -- a CAF, since it can only be entered once.
387 mk_caf_info (StgRhsClosure _ _ _ free_vars _ [] e) srt
388         | isBottomingExpr e && null srt = NoCafRefs
389
390 mk_caf_info (StgRhsClosure _ _ _ free_vars upd args body) srt 
391         | isUpdatable upd = MayHaveCafRefs -- a real live CAF
392         | null srt  = NoCafRefs          -- function w/ no static references
393         | otherwise = MayHaveCafRefs     -- function w/ some static references
394
395 mk_caf_info rcon@(StgRhsCon cc con args) srt 
396         | null srt   = NoCafRefs         -- constructor w/ no static references
397         | otherwise  = MayHaveCafRefs    -- otherwise, treat as a CAF
398
399
400 isBottomingExpr (StgLet bind expr) = isBottomingExpr expr
401 isBottomingExpr (StgApp f args)    = idAppIsBottom f (length args)
402 isBottomingExpr _                  = False
403 \end{code}
404
405 -----------------------------------------------------------------------------
406
407 Here we decide which Id's to place in the static reference table.  An
408 internal top-level id will be in the environment with the appropriate
409 CafInfo, so we use that if available.  An imported top-level Id will
410 have the CafInfo attached.  Otherwise, we just ignore the Id.
411
412 \begin{code}
413 getGlobalRefs :: UniqFM CafInfo -> [StgArg] -> UniqSet Id
414 getGlobalRefs rho args = mkUniqSet (concat (map (globalRefArg rho) args))
415
416 globalRefArg :: UniqFM CafInfo -> StgArg -> [Id]
417
418 globalRefArg rho (StgVarArg id)
419
420   | otherwise =
421     case lookupUFM rho id of {
422         Just _ -> [id];                 -- can't look at the caf_info yet...
423         Nothing ->
424
425     if externallyVisibleId id 
426         then case getIdCafInfo id of
427                 MayHaveCafRefs -> [id]
428                 NoCafRefs      -> []
429         else []
430    }
431
432 globalRefArg rho _ = []
433 \end{code}
434
435 \begin{code}
436 mayHaveCafRefs rho id =
437   case lookupUFM rho id of
438         Just MayHaveCafRefs -> True
439         Just NoCafRefs      -> False
440         Nothing             -> True
441 \end{code}
442
443 -----------------------------------------------------------------------------
444 Misc stuff
445
446 \begin{code}
447 attach_srt_bind :: StgBinding -> Int -> Int -> StgBinding
448 attach_srt_bind (StgNonRec binder rhs) off len = 
449         StgNonRec binder (attach_srt_rhs rhs off len)
450 attach_srt_bind (StgRec binds) off len =
451         StgRec [ (v,attach_srt_rhs rhs off len) | (v,rhs) <- binds ]
452
453 attach_srt_rhs :: StgRhs -> Int -> Int -> StgRhs
454 attach_srt_rhs (StgRhsCon cc con args) off length
455   = StgRhsCon cc con args
456 attach_srt_rhs (StgRhsClosure cc bi _ free upd args rhs) off length
457   = StgRhsClosure cc bi srt free upd args rhs
458   where
459         srt | length == 0 = NoSRT
460             | otherwise   = SRT off length
461
462
463 all_con_binds (StgNonRec x rhs) = con_rhs rhs
464 all_con_binds (StgRec bs) = all con_rhs (map snd bs)
465
466 con_rhs (StgRhsCon _ _ _) = True
467 con_rhs _ = False
468
469
470 a =: k  = k a
471 \end{code}
472
473 -----------------------------------------------------------------------------
474 Fix up the SRT's in a let-no-escape.
475
476 (for a description of let-no-escapes, see CgLetNoEscape.lhs)
477
478 Here's the problem: a let-no-escape isn't represented by an activation
479 record on the stack.  It seems either very difficult or impossible to
480 get the liveness bitmap right in the info table, so we don't do it
481 this way (the liveness mask isn't constant).
482
483 So, the question is how does the garbage collector get access to the
484 SRT for the rhs of the let-no-escape?  It can't see an info table, so
485 it must get the SRT from somewhere else.  Here's an example:
486
487    let-no-escape x = .... f ....
488    in  case blah of
489            p -> .... x ... g ....
490
491 (f and g are global).  Suppose we garbage collect while evaluating
492 'blah'.  The stack will contain an activation record for the case,
493 which will point to an SRT containing [g] (according to our SRT
494 algorithm above).  But, since the case continuation can call x, and
495 hence f, the SRT should really be [f,g].
496
497 another example:
498
499    let-no-escape {-rec-} z =  \x -> case blah of
500                                       p1 ->  .... f ...
501                                       p2 ->  case blah2 of
502                                                 p -> .... (z x') ...
503    in ....
504
505 if we GC while evaluating blah2, then the case continuation on the
506 stack needs to refer to [f] in its SRT, because we can reach f by
507 calling z recursively.
508
509 FIX:
510
511 The following code fixes up a let-no-escape expression after we've run
512 the SRT algorithm.  It needs to know the SRT for the *whole*
513 expression (this is plugged in instead of the SRT for case exprsesions
514 in the body).  The good news is that we only need to traverse nested
515 case expressions, since the let-no-escape bound variable can't occur
516 in the rhs of a let or in a case scrutinee.
517
518 For recursive let-no-escapes, the body is processed as for
519 non-recursive let-no-escapes, but case expressions in the rhs of each
520 binding have their SRTs replaced with the SRT for the binding group
521 (*not* the SRT of the whole let-no-escape expression).
522
523 \begin{code}
524 fixLNE_srt :: SRT -> StgExpr -> StgExpr
525 fixLNE_srt all_srt (StgLetNoEscape live1 live2 (StgNonRec id rhs) body)
526   = StgLetNoEscape live1 live2 (StgNonRec id rhs) (fixLNE [id] all_srt body)
527   
528 fixLNE_srt all_srt (StgLetNoEscape live1 live2 (StgRec pairs) body)
529   = StgLetNoEscape live1 live2
530         (StgRec (map fixLNE_rec pairs)) (fixLNE binders all_srt body)
531   where
532         binders = map fst pairs
533         fixLNE_rec (id,StgRhsClosure cc bi srt fvs uf args e) = 
534            (id, StgRhsClosure cc bi srt fvs uf args (fixLNE binders srt e))
535         fixLNE_rec (id,con) = (id,con)
536
537 fixLNE :: [Id] -> SRT -> StgExpr -> StgExpr
538
539 fixLNE ids srt expr@(StgCase scrut live rhs_live bndr old_srt alts)
540   | any (`elementOfUniqSet` rhs_live) ids
541     = StgCase scrut live rhs_live bndr srt (fixLNE_alts ids srt alts)
542   | otherwise = expr
543   -- can't be in the scrutinee, because it's a let-no-escape!
544
545 fixLNE ids srt expr@(StgLetNoEscape live rhs_live bind body)
546   | any (`elementOfUniqSet` rhs_live) ids =
547         StgLetNoEscape live rhs_live (fixLNE_bind ids srt bind)
548                                      (fixLNE      ids srt body)
549   | any (`elementOfUniqSet` live) ids = 
550         StgLetNoEscape live rhs_live bind (fixLNE ids srt body)
551   | otherwise = expr
552
553 fixLNE ids srt (StgLet bind body)  = StgLet bind (fixLNE ids srt body)
554 fixLNE ids srt (StgSCC cc expr)    = StgSCC cc (fixLNE ids srt expr)
555 fixLNE ids srt expr                = expr
556
557 fixLNE_alts ids srt (StgAlgAlts t alts dflt)
558   = StgAlgAlts  t (map (fixLNE_algalt  ids srt) alts) (fixLNE_dflt ids srt dflt)
559
560 fixLNE_alts ids srt (StgPrimAlts t alts dflt)
561   = StgPrimAlts t (map (fixLNE_primalt ids srt) alts) (fixLNE_dflt ids srt dflt)
562
563 fixLNE_algalt  ids srt (con,args,used,rhs) = (con,args,used, fixLNE ids srt rhs)
564 fixLNE_primalt ids srt (lit,rhs)           = (lit,           fixLNE ids srt rhs)
565
566 fixLNE_dflt    ids srt (StgNoDefault)      = StgNoDefault
567 fixLNE_dflt    ids srt (StgBindDefault rhs) = StgBindDefault (fixLNE ids srt rhs)
568
569 fixLNE_bind ids srt (StgNonRec bndr rhs) 
570   = StgNonRec bndr (fixLNE_rhs ids srt rhs)
571 fixLNE_bind ids srt (StgRec pairs) 
572   = StgRec [ (bndr, fixLNE_rhs ids srt rhs) | (bndr,rhs) <- pairs ]
573
574 fixLNE_rhs ids srt rhs@(StgRhsClosure cc bi old_srt fvs uf args expr)
575   | any (`elem` fvs) ids 
576       = StgRhsClosure cc bi srt fvs uf args (fixLNE ids srt expr)
577   | otherwise     = rhs
578 fixLNE_rhs ids srt rhs@(StgRhsCon cc con args) = rhs
579
580 \end{code}