42f0a32950cd4233107b74d2d939e5c55b67c76a
[ghc-hetmet.git] / ghc / compiler / profiling / SCCfinal.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[SCCfinal]{Modify and collect code generation for final STG program}
5
6 This is now a sort-of-normal STG-to-STG pass (WDP 94/06), run by stg2stg.
7
8 * Traverses the STG program collecting the cost centres. These are
9   required to declare the cost centres at the start of code
10   generation.
11
12   Note: because of cross-module unfolding, some of these cost centres
13   may be from other modules.  But will still have to give them
14   "extern" declarations.
15
16 * Puts on CAF cost-centres if the user has asked for individual CAF
17   cost-centres.
18
19 * Ditto for individual DICT cost-centres.
20
21 * Boxes top-level inherited functions passed as arguments.
22
23 * "Distributes" given cost-centres to all as-yet-unmarked RHSs.
24
25 \begin{code}
26 module SCCfinal ( stgMassageForProfiling ) where
27
28 #include "HsVersions.h"
29
30 import StgSyn
31
32 import CmdLineOpts      ( opt_AutoSccsOnIndividualCafs )
33 import CostCentre       -- lots of things
34 import Const            ( Con(..) )
35 import Id               ( Id, mkSysLocal )
36 import OccName          ( Module )
37 import UniqSupply       ( uniqFromSupply, splitUniqSupply, UniqSupply )
38 import Unique           ( Unique )
39 import Util             ( removeDups )
40 import Outputable       
41
42 infixr 9 `thenMM`, `thenMM_`
43 \end{code}
44
45 \begin{code}
46 type CollectedCCs = ([CostCentre],      -- locally defined ones
47                      [CostCentre],      -- ones needing "extern" decls
48                      [CostCentreStack]) -- singleton stacks (for CAFs)
49
50 stgMassageForProfiling
51         :: Module -> FAST_STRING        -- module name, group name
52         -> UniqSupply                   -- unique supply
53         -> [StgBinding]                 -- input
54         -> (CollectedCCs, [StgBinding])
55
56 stgMassageForProfiling mod_name grp_name us stg_binds
57   = let
58         ((local_ccs, extern_ccs, cc_stacks),
59          stg_binds2)
60           = initMM mod_name us (mapMM do_top_binding stg_binds)
61
62         (fixed_ccs, fixed_cc_stacks)
63           = if opt_AutoSccsOnIndividualCafs
64             then ([],[])  -- don't need "all CAFs" CC 
65                           -- (for Prelude, we use PreludeCC)
66             else ([all_cafs_cc], [all_cafs_ccs])
67
68         local_ccs_no_dups  = fst (removeDups cmpCostCentre local_ccs)
69         extern_ccs_no_dups = fst (removeDups cmpCostCentre extern_ccs)
70     in
71     ((fixed_ccs ++ local_ccs_no_dups, 
72       extern_ccs_no_dups, 
73       fixed_cc_stacks ++ cc_stacks), stg_binds2)
74   where
75
76     all_cafs_cc  = mkAllCafsCC mod_name grp_name
77     all_cafs_ccs = mkSingletonCCS all_cafs_cc
78
79     ----------
80     do_top_binding :: StgBinding -> MassageM StgBinding
81
82     do_top_binding (StgNonRec b rhs) 
83       = do_top_rhs b rhs                `thenMM` \ rhs' ->
84         returnMM (StgNonRec b rhs')
85
86     do_top_binding (StgRec pairs)
87       = mapMM do_pair pairs             `thenMM` \ pairs2 ->
88         returnMM (StgRec pairs2)
89       where
90         do_pair (b, rhs) 
91            = do_top_rhs b rhs   `thenMM` \ rhs2 ->
92              returnMM (b, rhs2)
93
94     ----------
95     do_top_rhs :: Id -> StgRhs -> MassageM StgRhs
96
97     do_top_rhs binder (StgRhsClosure _ bi srt fv u [] (StgSCC cc (StgCon (DataCon con) args _)))
98       | not (isSccCountCostCentre cc)
99         -- Trivial _scc_ around nothing but static data
100         -- Eliminate _scc_ ... and turn into StgRhsCon
101       = returnMM (StgRhsCon dontCareCCS con args)
102
103 {- Can't do this one with cost-centre stacks:  --SDM
104     do_top_rhs binder (StgRhsClosure no_cc bi srt fv u [] (StgSCC ty cc expr))
105       | (noCCSAttached no_cc || currentOrSubsumedCCS no_cc)
106         && not (isSccCountCostCentre cc)
107         -- Top level CAF without a cost centre attached
108         -- Attach and collect cc of trivial _scc_ in body
109       = collectCC cc                                    `thenMM_`
110         set_prevailing_cc cc (do_expr expr)             `thenMM`  \ expr' ->
111         returnMM (StgRhsClosure cc bi srt fv u [] expr')
112 -}
113
114     do_top_rhs binder (StgRhsClosure no_cc bi srt fv u [] body)
115       | noCCSAttached no_cc || currentOrSubsumedCCS no_cc
116         -- Top level CAF without a cost centre attached
117         -- Attach CAF cc (collect if individual CAF ccs)
118       = (if opt_AutoSccsOnIndividualCafs 
119                 then let cc = mkAutoCC binder mod_name grp_name CafCC
120                          ccs = mkSingletonCCS cc
121                      in
122                      collectCC  cc  `thenMM_`
123                      collectCCS ccs `thenMM_`
124                      returnMM ccs
125                 else 
126                      returnMM all_cafs_ccs)             `thenMM`  \ caf_ccs ->
127         set_prevailing_cc caf_ccs (do_expr body)        `thenMM`  \ body' ->
128         returnMM (StgRhsClosure caf_ccs bi srt fv u [] body')
129
130     do_top_rhs binder (StgRhsClosure cc bi srt fv u [] body)
131         -- Top level CAF with cost centre attached
132         -- Should this be a CAF cc ??? Does this ever occur ???
133       = pprPanic "SCCfinal: CAF with cc:" (ppr cc)
134
135 {- can't do this with cost-centre stacks:  --SDM
136     do_top_rhs binder (StgRhsClosure _ bi srt fv u args (StgSCC cc expr))
137       | not (isSccCountCostCentre cc)
138         -- Top level function with trivial _scc_ in body
139         -- Attach and collect cc of trivial _scc_
140       = collectCC cc                                    `thenMM_`
141         set_prevailing_cc cc (do_expr expr)             `thenMM` \ expr' ->
142         returnMM (StgRhsClosure cc bi srt fv u args expr')
143 -}
144
145     do_top_rhs binder (StgRhsClosure no_ccs bi srt fv u args body)
146         -- Top level function, probably subsumed
147       | noCCSAttached no_ccs
148       = set_prevailing_cc currentCCS (do_expr body)     `thenMM` \ body' ->
149         returnMM (StgRhsClosure subsumedCCS bi srt fv u args body')
150
151       | otherwise
152       = pprPanic "SCCfinal: CAF with cc:" (ppr no_ccs)
153
154     do_top_rhs binder (StgRhsCon ccs con args)
155         -- Top-level (static) data is not counted in heap
156         -- profiles; nor do we set CCCS from it; so we
157         -- just slam in dontCareCostCentre
158       = returnMM (StgRhsCon dontCareCCS con args)
159
160     ------
161     do_expr :: StgExpr -> MassageM StgExpr
162
163     do_expr (StgApp fn args)
164       = boxHigherOrderArgs (StgApp fn) args
165
166     do_expr (StgCon con args res_ty)
167       = boxHigherOrderArgs (\args -> StgCon con args res_ty) args
168
169     do_expr (StgSCC cc expr)    -- Ha, we found a cost centre!
170       = collectCC cc                                    `thenMM_`
171         set_prevailing_cc currentCCS (do_expr expr)     `thenMM`  \ expr' ->
172         returnMM (StgSCC cc expr')
173
174     do_expr (StgCase expr fv1 fv2 bndr srt alts)
175       = do_expr expr            `thenMM` \ expr' ->
176         do_alts alts            `thenMM` \ alts' ->
177         returnMM (StgCase expr' fv1 fv2 bndr srt alts')
178       where
179         do_alts (StgAlgAlts ty alts def) 
180           = mapMM do_alt alts   `thenMM` \ alts' ->
181             do_deflt def        `thenMM` \ def' ->
182             returnMM (StgAlgAlts ty alts' def')
183           where
184             do_alt (id, bs, use_mask, e)
185               = do_expr e `thenMM` \ e' ->
186                 returnMM (id, bs, use_mask, e')
187
188         do_alts (StgPrimAlts ty alts def) 
189           = mapMM do_alt alts   `thenMM` \ alts' ->
190             do_deflt def        `thenMM` \ def' ->
191             returnMM (StgPrimAlts ty alts' def')
192           where
193             do_alt (l,e)
194               = do_expr e `thenMM` \ e' ->
195                 returnMM (l,e')
196
197         do_deflt StgNoDefault = returnMM StgNoDefault
198         do_deflt (StgBindDefault e) 
199           = do_expr e                   `thenMM` \ e' ->
200             returnMM (StgBindDefault e')
201
202     do_expr (StgLet b e)
203       = do_binding b                    `thenMM` \ b' ->
204         do_expr e                       `thenMM` \ e' ->
205         returnMM (StgLet b' e')
206
207     do_expr (StgLetNoEscape lvs1 lvs2 rhs body)
208       = do_binding rhs                  `thenMM` \ rhs' ->
209         do_expr body                    `thenMM` \ body' ->
210         returnMM (StgLetNoEscape lvs1 lvs2 rhs' body')
211
212     ----------
213     do_binding :: StgBinding -> MassageM StgBinding
214
215     do_binding (StgNonRec b rhs) 
216       = do_rhs rhs                      `thenMM` \ rhs' ->
217         returnMM (StgNonRec b rhs')
218
219     do_binding (StgRec pairs)
220       = mapMM do_pair pairs `thenMM` \ new_pairs ->
221         returnMM (StgRec new_pairs)
222       where
223         do_pair (b, rhs)
224           = do_rhs rhs  `thenMM` \ rhs' ->
225             returnMM (b, rhs')
226
227     do_rhs :: StgRhs -> MassageM StgRhs
228         -- We play much the same game as we did in do_top_rhs above;
229         -- but we don't have to worry about cafs etc.
230
231 {-
232     do_rhs (StgRhsClosure closure_cc bi srt fv u [] (StgSCC ty cc (StgCon (DataCon con) args _)))
233       | not (isSccCountCostCentre cc)
234       = collectCC cc `thenMM_`
235         returnMM (StgRhsCon cc con args)
236 -}
237
238 {-
239     do_rhs (StgRhsClosure _ bi srt fv u args (StgSCC ty cc expr))
240       | not (isSccCountCostCentre cc)
241       = collectCC cc                            `thenMM_`
242         set_prevailing_cc cc (do_expr expr)     `thenMM` \ expr' ->
243         returnMM (StgRhsClosure cc bi srt fv u args expr')
244 -}
245
246     do_rhs (StgRhsClosure cc bi srt fv u args body)
247       = set_prevailing_cc_maybe cc              $ \ cc' ->
248         set_lambda_cc (do_expr body)            `thenMM` \ body' ->
249         returnMM (StgRhsClosure cc' bi srt fv u args body')
250
251     do_rhs (StgRhsCon cc con args)
252       = set_prevailing_cc_maybe cc              $ \ cc' ->
253         returnMM (StgRhsCon cc' con args)
254
255         -- ToDo: Box args and sort out any let bindings ???
256         -- Nope: maybe later? WDP 94/06
257 \end{code}
258
259 %************************************************************************
260 %*                                                                      *
261 \subsection{Boxing higher-order args}
262 %*                                                                      *
263 %************************************************************************
264
265 \begin{code}
266 boxHigherOrderArgs
267     :: ([StgArg] -> StgExpr)
268                         -- An application lacking its arguments and live-var info
269     -> [StgArg]         -- arguments which we might box
270     -> MassageM StgExpr
271
272 boxHigherOrderArgs almost_expr args
273   = returnMM (almost_expr args)
274
275 {- No boxing for now ... should be moved to desugarer and preserved ... 
276
277 boxHigherOrderArgs almost_expr args live_vars
278   = get_prevailing_cc                   `thenMM` \ cc ->
279     if (isCafCC cc || isDictCC cc) then
280         -- no boxing required inside CAF/DICT cc
281         -- since CAF/DICT functions are subsumed anyway
282         returnMM (almost_expr args live_vars)
283     else
284         mapAccumMM do_arg [] args       `thenMM` \ (let_bindings, new_args) ->
285         returnMM (foldr (mk_stg_let cc) (almost_expr new_args live_vars) let_bindings)
286   where
287     ---------------
288     do_arg bindings atom@(StgLitAtom _) = returnMM (bindings, atom)
289
290     do_arg bindings atom@(StgVarAtom old_var)
291       = let
292             var_type = getIdUniType old_var
293         in
294         if toplevelishId old_var && isFunType (getTauType var_type)
295         then
296             -- make a trivial let-binding for the top-level function
297             getUniqueMM         `thenMM` \ uniq ->
298             let
299                 new_var = mkSysLocal SLIT("sf") uniq var_type
300             in
301             returnMM ( (new_var, old_var) : bindings, StgVarAtom new_var )
302         else
303             returnMM (bindings, atom)
304
305     ---------------
306     mk_stg_let :: CostCentre -> (Id, Id) -> StgExpr -> StgExpr
307
308     mk_stg_let cc (new_var, old_var) body
309       = let
310             rhs_body    = StgApp (StgVarAtom old_var) [{-args-}]
311             rhs_closure = StgRhsClosure cc stgArgOcc NoSRT [{-fvs-}] ReEntrant [{-args-}] rhs_body
312         in
313         StgLet (StgNonRec new_var rhs_closure) body
314       where
315         bOGUS_LVs = emptyUniqSet -- easier to print than: panic "mk_stg_let: LVs"
316 -}
317 \end{code}
318
319 %************************************************************************
320 %*                                                                      *
321 \subsection{Boring monad stuff for this}
322 %*                                                                      *
323 %************************************************************************
324
325 \begin{code}
326 type MassageM result
327   =  Module             -- module name
328   -> CostCentreStack    -- prevailing CostCentre
329                         -- if none, subsumedCosts at top-level
330                         -- useCurrentCostCentre at nested levels
331   -> UniqSupply
332   -> CollectedCCs
333   -> (CollectedCCs, result)
334
335 -- the initUs function also returns the final UniqueSupply and CollectedCCs
336
337 initMM :: Module        -- module name, which we may consult
338        -> UniqSupply
339        -> MassageM a
340        -> (CollectedCCs, a)
341
342 initMM mod_name init_us m = m mod_name noCCS init_us ([],[],[])
343
344 thenMM  :: MassageM a -> (a -> MassageM b) -> MassageM b
345 thenMM_ :: MassageM a -> (MassageM b) -> MassageM b
346
347 thenMM expr cont mod scope_cc us ccs
348   = case splitUniqSupply us     of { (s1, s2) ->
349     case (expr mod scope_cc s1 ccs)     of { (ccs2, result) ->
350     cont result mod scope_cc s2 ccs2 }}
351
352 thenMM_ expr cont mod scope_cc us ccs
353   = case splitUniqSupply us     of { (s1, s2) ->
354     case (expr mod scope_cc s1 ccs)     of { (ccs2, _) ->
355     cont mod scope_cc s2 ccs2 }}
356
357 returnMM :: a -> MassageM a
358 returnMM result mod scope_cc us ccs = (ccs, result)
359
360 nopMM :: MassageM ()
361 nopMM mod scope_cc us ccs = (ccs, ())
362
363 mapMM :: (a -> MassageM b) -> [a] -> MassageM [b]
364
365 mapMM f [] = returnMM []
366 mapMM f (m:ms)
367   = f m         `thenMM` \ r  ->
368     mapMM f ms  `thenMM` \ rs ->
369     returnMM (r:rs)
370
371 mapAccumMM :: (acc -> x -> MassageM (acc, y)) -> acc -> [x] -> MassageM (acc, [y])
372
373 mapAccumMM f b [] = returnMM (b, [])
374 mapAccumMM f b (m:ms)
375   = f b m               `thenMM` \ (b2, r)  ->
376     mapAccumMM f b2 ms  `thenMM` \ (b3, rs) ->
377     returnMM (b3, r:rs)
378
379 getUniqueMM :: MassageM Unique
380 getUniqueMM mod scope_cc us ccs = (ccs, uniqFromSupply us)
381 \end{code}
382
383 I'm not sure about all this prevailing CC stuff  --SDM
384
385 \begin{code}
386 set_prevailing_cc :: CostCentreStack -> MassageM a -> MassageM a
387 set_prevailing_cc cc_to_set_to action mod scope_cc us ccs
388         -- set unconditionally
389   = action mod cc_to_set_to us ccs
390
391 set_prevailing_cc_maybe :: CostCentreStack -> (CostCentreStack -> MassageM a) -> MassageM a
392 set_prevailing_cc_maybe cc_to_try action mod scope_cc us ccs
393         -- set only if a real cost centre
394   = let
395         cc_to_use
396           = if noCCSAttached cc_to_try
397             then scope_cc    -- carry on as before
398             else cc_to_try   -- use new cost centre
399     in
400     action cc_to_use mod cc_to_use us ccs
401
402 set_lambda_cc :: MassageM a -> MassageM a
403 set_lambda_cc action mod scope_cc us ccs
404         -- used when moving inside a lambda; 
405         -- if we were chugging along as "caf/dict" we change to "ccc"
406   = let
407         cc_to_use = currentCCS
408         {-
409           = if isCafCC scope_cc || isDictCC scope_cc
410             then useCurrentCostCentre
411             else scope_cc
412         -}
413     in
414     action mod cc_to_use us ccs
415
416
417 get_prevailing_cc :: MassageM CostCentreStack
418 get_prevailing_cc mod scope_cc us ccs = (ccs, scope_cc)
419
420 \end{code}
421
422 \begin{code}
423 collectCC :: CostCentre -> MassageM ()
424
425 collectCC cc mod_name scope_cc us (local_ccs, extern_ccs, ccss)
426   = ASSERT(not (noCCAttached cc))
427     if (cc `ccFromThisModule` mod_name) then
428         ((cc : local_ccs, extern_ccs, ccss), ())
429     else -- must declare it "extern"
430         ((local_ccs, cc : extern_ccs, ccss), ())
431
432 collectCCS :: CostCentreStack -> MassageM ()
433
434 collectCCS ccs mod_name scope_cc us (local_ccs, extern_ccs, ccss)
435   = ASSERT(not (noCCSAttached ccs))
436     ((local_ccs, extern_ccs, ccs : ccss), ())
437 \end{code}