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