52d9f8d7c9a9505cfb3958e58ca9377eaeb09c88
[ghc-hetmet.git] / ghc / compiler / profiling / SCCfinal.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
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 MkId             (  mkSysLocal )
35 import Id               ( idType, emptyIdSet, Id )
36 import SrcLoc           ( noSrcLoc )
37 import Type             ( splitSigmaTy, splitFunTy_maybe )
38 import UniqSupply       ( getUnique, splitUniqSupply, UniqSupply )
39 import Unique           ( Unique )
40 import Util             ( removeDups, assertPanic, trace )
41 import Outputable       
42
43 infixr 9 `thenMM`, `thenMM_`
44 \end{code}
45
46 \begin{code}
47 type CollectedCCs = ([CostCentre],      -- locally defined ones
48                      [CostCentre])      -- ones needing "extern" decls
49
50 stgMassageForProfiling
51         :: FAST_STRING -> 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),
59          stg_binds2)
60           = initMM mod_name us (mapMM do_top_binding stg_binds)
61
62         fixed_ccs
63           = if do_auto_sccs_on_cafs
64             then [] -- don't need "all CAFs" CC (for Prelude, we use PreludeCC)
65             else [all_cafs_cc]
66
67         local_ccs_no_dups  = fst (removeDups cmpCostCentre local_ccs)
68         extern_ccs_no_dups = fst (removeDups cmpCostCentre extern_ccs)
69     in
70     ((fixed_ccs ++ local_ccs_no_dups, extern_ccs_no_dups), stg_binds2)
71   where
72     do_auto_sccs_on_cafs  = opt_AutoSccsOnIndividualCafs  -- only use!
73
74     all_cafs_cc = mkAllCafsCC mod_name grp_name
75
76     ----------
77     do_top_binding :: StgBinding -> MassageM StgBinding
78
79     do_top_binding (StgNonRec b rhs) 
80       = do_top_rhs b rhs                `thenMM` \ rhs' ->
81         returnMM (StgNonRec b rhs')
82
83     do_top_binding (StgRec pairs)
84       = mapMM do_pair pairs             `thenMM` \ pairs2 ->
85         returnMM (StgRec pairs2)
86       where
87         do_pair (b, rhs) 
88            = do_top_rhs b rhs   `thenMM` \ rhs2 ->
89              returnMM (b, rhs2)
90
91     ----------
92     do_top_rhs :: Id -> StgRhs -> MassageM StgRhs
93
94     do_top_rhs binder (StgRhsClosure _ bi fv u [] (StgSCC ty cc (StgCon con args lvs)))
95       | not (isSccCountCostCentre cc)
96         -- Trivial _scc_ around nothing but static data
97         -- Eliminate _scc_ ... and turn into StgRhsCon
98       = returnMM (StgRhsCon dontCareCostCentre con args)
99
100     do_top_rhs binder (StgRhsClosure no_cc bi fv u [] (StgSCC ty cc expr))
101       | (noCostCentreAttached no_cc || currentOrSubsumedCosts no_cc)
102         && not (isSccCountCostCentre cc)
103         -- Top level CAF without a cost centre attached
104         -- Attach and collect cc of trivial _scc_ in body
105       = collectCC cc                                    `thenMM_`
106         set_prevailing_cc cc (do_expr expr)             `thenMM`  \ expr' ->
107         returnMM (StgRhsClosure cc bi fv u [] expr')
108
109     do_top_rhs binder (StgRhsClosure no_cc bi fv u [] body)
110       | noCostCentreAttached no_cc || currentOrSubsumedCosts no_cc
111         -- Top level CAF without a cost centre attached
112         -- Attach CAF cc (collect if individual CAF ccs)
113       = let
114             (collect, caf_cc)
115               = if do_auto_sccs_on_cafs then
116                    (True, mkAutoCC binder mod_name grp_name IsCafCC)
117                 else
118                    (False, all_cafs_cc)
119         in
120         (if collect then collectCC caf_cc else nopMM)   `thenMM_`
121         set_prevailing_cc caf_cc (do_expr body)         `thenMM`  \ body' ->
122         returnMM (StgRhsClosure caf_cc bi fv u [] body')
123
124     do_top_rhs binder (StgRhsClosure cc bi fv u [] body)
125         -- Top level CAF with cost centre attached
126         -- Should this be a CAF cc ??? Does this ever occur ???
127       = trace ("SCCfinal: CAF with cc: " ++ showCostCentre False cc) $
128         collectCC cc                                    `thenMM_`
129         set_prevailing_cc cc (do_expr body)             `thenMM` \ body' ->
130         returnMM (StgRhsClosure cc bi fv u [] body')
131
132     do_top_rhs binder (StgRhsClosure _ bi fv u args (StgSCC ty cc expr))
133       | not (isSccCountCostCentre cc)
134         -- Top level function with trivial _scc_ in body
135         -- Attach and collect cc of trivial _scc_
136       = collectCC cc                                    `thenMM_`
137         set_prevailing_cc cc (do_expr expr)             `thenMM` \ expr' ->
138         returnMM (StgRhsClosure cc bi fv u args expr')
139
140     do_top_rhs binder (StgRhsClosure cc bi fv u args body)
141         -- Top level function, probably subsumed
142       = let
143             (cc_closure, cc_body)
144               = if noCostCentreAttached cc
145                 then (subsumedCosts, useCurrentCostCentre)
146                 else (cc, cc)
147         in
148         set_prevailing_cc cc_body (do_expr body)        `thenMM` \ body' ->
149         returnMM (StgRhsClosure cc_closure bi fv u args body')
150
151     do_top_rhs binder (StgRhsCon cc con args)
152         -- Top-level (static) data is not counted in heap
153         -- profiles; nor do we set CCC from it; so we
154         -- just slam in dontCareCostCentre
155       = returnMM (StgRhsCon dontCareCostCentre con args)
156
157     ------
158     do_expr :: StgExpr -> MassageM StgExpr
159
160     do_expr (StgApp fn args lvs)
161       = boxHigherOrderArgs (StgApp fn) args lvs
162
163     do_expr (StgCon con args lvs)
164       = boxHigherOrderArgs (StgCon con) args lvs
165
166     do_expr (StgPrim op args lvs)
167       = boxHigherOrderArgs (StgPrim op) args lvs
168
169     do_expr (StgSCC ty cc expr) -- Ha, we found a cost centre!
170       = collectCC cc                            `thenMM_`
171         set_prevailing_cc cc (do_expr expr)     `thenMM`  \ expr' ->
172         returnMM (StgSCC ty cc expr')
173
174     do_expr (StgCase expr fv1 fv2 uniq alts)
175       = do_expr expr            `thenMM` \ expr' ->
176         do_alts alts            `thenMM` \ alts' ->
177         returnMM (StgCase expr' fv1 fv2 uniq 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 b is_used e) 
199           = do_expr e                   `thenMM` \ e' ->
200             returnMM (StgBindDefault b is_used 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     do_rhs (StgRhsClosure _ bi fv u [] (StgSCC ty cc (StgCon con args lvs)))
232       | not (isSccCountCostCentre cc)
233       = collectCC cc `thenMM_`
234         returnMM (StgRhsCon cc con args)
235
236     do_rhs (StgRhsClosure _ bi fv u args (StgSCC ty cc expr))
237       | not (isSccCountCostCentre cc)
238       = collectCC cc                            `thenMM_`
239         set_prevailing_cc cc (do_expr expr)     `thenMM` \ expr' ->
240         returnMM (StgRhsClosure cc bi fv u args expr')
241
242     do_rhs (StgRhsClosure cc bi fv u args body)
243       = set_prevailing_cc_maybe cc              $ \ cc' ->
244         set_lambda_cc (do_expr body)            `thenMM` \ body' ->
245         returnMM (StgRhsClosure cc' bi fv u args body')
246
247     do_rhs (StgRhsCon cc con args)
248       = set_prevailing_cc_maybe cc              $ \ cc' ->
249         returnMM (StgRhsCon cc' con args)
250
251         -- ToDo: Box args and sort out any let bindings ???
252         -- Nope: maybe later? WDP 94/06
253 \end{code}
254
255 %************************************************************************
256 %*                                                                      *
257 \subsection{Boxing higher-order args}
258 %*                                                                      *
259 %************************************************************************
260
261 \begin{code}
262 boxHigherOrderArgs
263     :: ([StgArg] -> StgLiveVars -> StgExpr)
264                         -- An application lacking its arguments and live-var info
265     -> [StgArg]         -- arguments which we might box
266     -> StgLiveVars      -- live var info, which we do *not* try
267                         -- to maintain/update (setStgVarInfo will
268                         -- do that)
269     -> MassageM StgExpr
270
271 boxHigherOrderArgs almost_expr args live_vars
272   = returnMM (almost_expr args live_vars)
273
274 {- No boxing for now ... should be moved to desugarer and preserved ... 
275
276 boxHigherOrderArgs almost_expr args live_vars
277   = get_prevailing_cc                   `thenMM` \ cc ->
278     if (isCafCC cc || isDictCC cc) then
279         -- no boxing required inside CAF/DICT cc
280         -- since CAF/DICT functions are subsumed anyway
281         returnMM (almost_expr args live_vars)
282     else
283         mapAccumMM do_arg [] args       `thenMM` \ (let_bindings, new_args) ->
284         returnMM (foldr (mk_stg_let cc) (almost_expr new_args live_vars) let_bindings)
285   where
286     ---------------
287     do_arg bindings atom@(StgLitAtom _) = returnMM (bindings, atom)
288
289     do_arg bindings atom@(StgVarAtom old_var)
290       = let
291             var_type = getIdUniType old_var
292         in
293         if toplevelishId old_var && isFunType (getTauType var_type)
294         then
295             -- make a trivial let-binding for the top-level function
296             getUniqueMM         `thenMM` \ uniq ->
297             let
298                 new_var = mkSysLocal SLIT("ho") uniq var_type noSrcLoc
299             in
300             returnMM ( (new_var, old_var) : bindings, StgVarAtom new_var )
301         else
302             returnMM (bindings, atom)
303
304     ---------------
305     mk_stg_let :: CostCentre -> (Id, Id) -> StgExpr -> StgExpr
306
307     mk_stg_let cc (new_var, old_var) body
308       = let
309             rhs_body    = StgApp (StgVarAtom old_var) [{-args-}] bOGUS_LVs
310             rhs_closure = StgRhsClosure cc stgArgOcc [{-fvs-}] ReEntrant [{-args-}] rhs_body
311         in
312         StgLet (StgNonRec new_var rhs_closure) body
313       where
314         bOGUS_LVs = emptyUniqSet -- easier to print than: panic "mk_stg_let: LVs"
315 -}
316 \end{code}
317
318 %************************************************************************
319 %*                                                                      *
320 \subsection{Boring monad stuff for this}
321 %*                                                                      *
322 %************************************************************************
323
324 \begin{code}
325 type MassageM result
326   =  FAST_STRING        -- module name
327   -> CostCentre         -- prevailing CostCentre
328                         -- if none, subsumedCosts at top-level
329                         -- useCurrentCostCentre at nested levels
330   -> UniqSupply
331   -> CollectedCCs
332   -> (CollectedCCs, result)
333
334 -- the initUs function also returns the final UniqueSupply and CollectedCCs
335
336 initMM :: FAST_STRING   -- module name, which we may consult
337        -> UniqSupply
338        -> MassageM a
339        -> (CollectedCCs, a)
340
341 initMM mod_name init_us m = m mod_name noCostCentre init_us ([],[])
342
343 thenMM  :: MassageM a -> (a -> MassageM b) -> MassageM b
344 thenMM_ :: MassageM a -> (MassageM b) -> MassageM b
345
346 thenMM expr cont mod scope_cc us ccs
347   = case splitUniqSupply us     of { (s1, s2) ->
348     case (expr mod scope_cc s1 ccs)     of { (ccs2, result) ->
349     cont result mod scope_cc s2 ccs2 }}
350
351 thenMM_ expr cont mod scope_cc us ccs
352   = case splitUniqSupply us     of { (s1, s2) ->
353     case (expr mod scope_cc s1 ccs)     of { (ccs2, _) ->
354     cont mod scope_cc s2 ccs2 }}
355
356 returnMM :: a -> MassageM a
357 returnMM result mod scope_cc us ccs = (ccs, result)
358
359 nopMM :: MassageM ()
360 nopMM mod scope_cc us ccs = (ccs, ())
361
362 mapMM :: (a -> MassageM b) -> [a] -> MassageM [b]
363
364 mapMM f [] = returnMM []
365 mapMM f (m:ms)
366   = f m         `thenMM` \ r  ->
367     mapMM f ms  `thenMM` \ rs ->
368     returnMM (r:rs)
369
370 mapAccumMM :: (acc -> x -> MassageM (acc, y)) -> acc -> [x] -> MassageM (acc, [y])
371
372 mapAccumMM f b [] = returnMM (b, [])
373 mapAccumMM f b (m:ms)
374   = f b m               `thenMM` \ (b2, r)  ->
375     mapAccumMM f b2 ms  `thenMM` \ (b3, rs) ->
376     returnMM (b3, r:rs)
377
378 getUniqueMM :: MassageM Unique
379 getUniqueMM mod scope_cc us ccs = (ccs, getUnique us)
380 \end{code}
381
382 \begin{code}
383 set_prevailing_cc :: CostCentre -> MassageM a -> MassageM a
384 set_prevailing_cc cc_to_set_to action mod scope_cc us ccs
385         -- set unconditionally
386   = action mod cc_to_set_to us ccs
387
388 set_prevailing_cc_maybe :: CostCentre -> (CostCentre -> MassageM a) -> MassageM a
389 set_prevailing_cc_maybe cc_to_try action mod scope_cc us ccs
390         -- set only if a real cost centre
391   = let
392         cc_to_use
393           = if noCostCentreAttached cc_to_try || currentOrSubsumedCosts cc_to_try
394             then scope_cc    -- carry on as before
395             else cc_to_try   -- use new cost centre
396     in
397     action cc_to_use mod cc_to_use us ccs
398
399 set_lambda_cc :: MassageM a -> MassageM a
400 set_lambda_cc action mod scope_cc us ccs
401         -- used when moving inside a lambda;
402         -- if we were chugging along as "caf/dict" we change to "ccc"
403   = let
404         cc_to_use
405           = if isCafCC scope_cc || isDictCC scope_cc
406             then useCurrentCostCentre
407             else scope_cc
408     in
409     action mod cc_to_use us ccs
410
411
412 get_prevailing_cc :: MassageM CostCentre
413 get_prevailing_cc mod scope_cc us ccs = (ccs, scope_cc)
414
415 \end{code}
416
417 \begin{code}
418 collectCC :: CostCentre -> MassageM ()
419
420 collectCC cc mod_name scope_cc us (local_ccs, extern_ccs)
421   = ASSERT(not (noCostCentreAttached cc))
422     ASSERT(not (currentOrSubsumedCosts cc))
423     if (cc `ccFromThisModule` mod_name) then
424         ((cc : local_ccs, extern_ccs), ())
425     else -- must declare it "extern"
426         ((local_ccs, cc : extern_ccs), ())
427 \end{code}