[project @ 1997-06-05 20:39:04 by sof]
[ghc-hetmet.git] / ghc / compiler / profiling / CostCentre.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[CostCentre]{The @CostCentre@ data type}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module CostCentre (
10         CostCentre, CcKind, IsDupdCC{-ToDo:rm-}, IsCafCC(..),
11         noCostCentre, subsumedCosts,
12         useCurrentCostCentre,
13         noCostCentreAttached, costsAreSubsumed, isCurrentCostCentre,
14         currentOrSubsumedCosts,
15         preludeCafsCostCentre, preludeDictsCostCentre,
16         overheadCostCentre, dontCareCostCentre,
17
18         mkUserCC, mkAutoCC, mkDictCC, mkAllCafsCC, mkAllDictsCC,
19         cafifyCC, dupifyCC,
20         isCafCC, isDictCC, isDupdCC,
21         isSccCountCostCentre,
22         sccAbleCostCentre,
23         ccFromThisModule,
24         ccMentionsId,
25
26         uppCostCentre, uppCostCentreDecl, showCostCentre, -- printing
27
28         cmpCostCentre   -- used for removing dups in a list
29     ) where
30
31 IMP_Ubiq(){-uitous-}
32
33 import Id               ( externallyVisibleId, GenId, showId, SYN_IE(Id) )
34 import CStrings         ( identToC, stringToC )
35 import Name             ( OccName, getOccString, moduleString, nameString )
36 import Outputable       ( PprStyle(..), codeStyle, ifaceStyle )
37 import Pretty
38 import Util             ( panic, panic#, assertPanic, cmpPString, thenCmp, Ord3(..) )
39
40 pprIdInUnfolding = panic "Whoops"
41 \end{code}
42
43 \begin{code}
44 data CostCentre
45   = NoCostCentre        -- Having this constructor avoids having
46                         -- to use "Maybe CostCentre" all the time.
47
48   | NormalCC    CcKind   -- CcKind will include a cost-centre name
49                 FAST_STRING      -- Name of module defining this CC.
50                 FAST_STRING   -- "Group" that this CC is in.
51                 IsDupdCC -- see below
52                 IsCafCC  -- see below
53
54   | CurrentCC           -- Pinned on a let(rec)-bound thunk/function/constructor,
55                         -- this says that the cost centre to be attached to
56                         -- the object, when it is allocated, is whatever is in the
57                         -- current-cost-centre register.
58                         -- This guy is *never* the cost centre for an SCC construct,
59                         -- and is only used for *local* (non-top-level) definitions.
60
61   | SubsumedCosts       -- Cost centre for top-level subsumed functions
62                         -- (CAFs get an AllCafsCC).
63                         -- Its execution costs get subsumed into the caller.
64                         -- This guy is *only* ever pinned on static closures,
65                         -- and is *never* the cost centre for an SCC construct.
66
67   | AllCafsCC   FAST_STRING     -- Ditto for CAFs.
68                 FAST_STRING  -- We record module and group names.
69                         -- Again, one "big" CAF cc per module, where all
70                         -- CAF costs are attributed unless the user asked for
71                         -- per-individual-CAF cost attribution.
72
73   | AllDictsCC  FAST_STRING     -- Ditto for dictionaries.
74                 FAST_STRING  -- We record module and group names.
75                         -- Again, one "big" DICT cc per module, where all
76                         -- DICT costs are attributed unless the user asked for
77                         -- per-individual-DICT cost attribution.
78                 IsDupdCC -- see below
79
80   | OverheadCC          -- We charge costs due to the profiling-system
81                         -- doing its work to "overhead".
82                         --
83                         -- Objects whose cost-centre is "Overhead"
84                         -- have their *allocation* charged to "overhead",
85                         -- but have the current CC put into the object
86                         -- itself.
87                         --
88                         -- For example, if we transform "f g" to "let
89                         -- g' = g in f g'" (so that something about
90                         -- profiling works better...), then we charge
91                         -- the *allocation* of g' to OverheadCC, but
92                         -- we put the cost-centre of the call to f
93                         -- (i.e., current CC) into the g' object.  When
94                         -- g' is entered, the cost-centre of the call
95                         -- to f will be set.
96
97   | PreludeCafsCC       -- In compiling the prelude, we do sometimes
98   | PreludeDictsCC      -- need a CC to blame; i.e., when there's a CAF,
99                         -- or other costs that really shouldn't be
100                         -- subsumed/blamed-on-the-caller.  These costs
101                         -- should be *small*.  We treat PreludeCafsCC
102                         -- as if it were shorthand for
103                         -- (AllCafsCC <PreludeSomething> _).  Analogously
104                         -- for PreludeDictsCC...
105         IsDupdCC        -- see below/above
106
107   | DontCareCC          -- We need a cost-centre to stick in static closures
108                         -- (for data), but we *don't* expect them to
109                         -- accumulate any costs.  But we still need
110                         -- the placeholder.  This CC is it.
111
112 data CcKind
113   = UserCC  FAST_STRING -- Supplied by user: String is the cc name
114   | AutoCC  Id          -- CC -auto-magically inserted for that Id
115   | DictCC  Id
116
117 data IsDupdCC
118   = AnOriginalCC        -- This says how the CC is *used*.  Saying that
119   | ADupdCC             -- it is ADupdCC doesn't make it a different
120                         -- CC, just that it a sub-expression which has
121                         -- been moved ("dupd") into a different scope.
122                         -- In the papers, it's called "SCCsub",
123                         --  i.e. SCCsub CC == SCC ADupdCC,
124                         -- but we are trying to avoid confusion between
125                         -- "subd" and "subsumed".  So we call the former
126                         -- "dupd".
127
128 data IsCafCC
129   = IsCafCC
130   | IsNotCafCC
131 \end{code}
132
133 WILL: Would there be any merit to recording ``I am now using a
134 cost-centre from another module''?  I don't know if this would help a
135 user; it might be interesting to us to know how much computation is
136 being moved across module boundaries.
137
138 SIMON: Maybe later...
139
140 \begin{code}
141 noCostCentre  = NoCostCentre
142 subsumedCosts = SubsumedCosts
143 useCurrentCostCentre = CurrentCC
144 overheadCostCentre = OverheadCC
145 preludeCafsCostCentre = PreludeCafsCC
146 dontCareCostCentre = DontCareCC
147 preludeDictsCostCentre is_dupd
148   = PreludeDictsCC (if is_dupd then ADupdCC else AnOriginalCC)
149
150 noCostCentreAttached NoCostCentre  = True
151 noCostCentreAttached _             = False
152
153 isCurrentCostCentre CurrentCC = True
154 isCurrentCostCentre _         = False
155
156 costsAreSubsumed SubsumedCosts  = True
157 costsAreSubsumed _              = False
158
159 currentOrSubsumedCosts SubsumedCosts    = True
160 currentOrSubsumedCosts CurrentCC        = True
161 currentOrSubsumedCosts _                = False
162
163 mkUserCC :: FAST_STRING -> FAST_STRING -> FAST_STRING -> CostCentre
164
165 mkUserCC cc_name module_name group_name
166   = NormalCC (UserCC cc_name) module_name group_name
167              AnOriginalCC IsNotCafCC{-might be changed-}
168
169 mkDictCC, mkAutoCC :: Id -> FAST_STRING -> FAST_STRING -> IsCafCC -> CostCentre
170
171 mkDictCC id module_name group_name is_caf
172   = NormalCC (DictCC id) module_name group_name
173              AnOriginalCC is_caf
174
175 mkAutoCC id module_name group_name is_caf
176   = NormalCC (AutoCC id) module_name group_name
177              AnOriginalCC is_caf
178
179 mkAllCafsCC  m g   = AllCafsCC  m g
180 mkAllDictsCC m g is_dupd
181   = AllDictsCC m g (if is_dupd then ADupdCC else AnOriginalCC)
182
183 cafifyCC, dupifyCC  :: CostCentre -> CostCentre
184
185 cafifyCC cc@(AllDictsCC _ _ _) = cc -- ToDo ???
186 cafifyCC cc@(PreludeDictsCC _) = cc --    ditto
187 cafifyCC (NormalCC kind m g is_dupd is_caf)
188   = ASSERT(not_a_calf_already is_caf)
189     NormalCC kind m g is_dupd IsCafCC
190   where
191     not_a_calf_already IsCafCC = False
192     not_a_calf_already _       = True
193 cafifyCC cc = panic ("cafifyCC"++(showCostCentre PprDebug False cc))
194
195 dupifyCC (AllDictsCC m g _) = AllDictsCC m g ADupdCC
196 dupifyCC (PreludeDictsCC _) = PreludeDictsCC ADupdCC
197 dupifyCC (NormalCC kind m g is_dupd is_caf)
198   = NormalCC kind m g ADupdCC is_caf
199 dupifyCC cc = panic ("dupifyCC"++(showCostCentre PprDebug False cc))
200
201 isCafCC, isDictCC, isDupdCC :: CostCentre -> Bool
202
203 isCafCC (AllCafsCC _ _)            = True
204 isCafCC PreludeCafsCC              = True
205 isCafCC (NormalCC _ _ _ _ IsCafCC) = True
206 isCafCC _                          = False
207
208 isDictCC (AllDictsCC _ _ _)             = True
209 isDictCC (PreludeDictsCC _)             = True
210 isDictCC (NormalCC (DictCC _) _ _ _ _)  = True
211 isDictCC _                              = False
212
213 isDupdCC (AllDictsCC _ _ ADupdCC)   = True
214 isDupdCC (PreludeDictsCC ADupdCC)   = True
215 isDupdCC (NormalCC _ _ _ ADupdCC _) = True
216 isDupdCC _                          = False
217
218 isSccCountCostCentre :: CostCentre -> Bool
219   -- Is this a cost-centre which records scc counts
220
221 #if DEBUG
222 isSccCountCostCentre NoCostCentre  = panic "isSccCount:NoCostCentre"
223 isSccCountCostCentre SubsumedCosts = panic "isSccCount:SubsumedCosts"
224 isSccCountCostCentre CurrentCC     = panic "isSccCount:CurrentCC"
225 isSccCountCostCentre DontCareCC    = panic "isSccCount:DontCareCC"
226 #endif
227 isSccCountCostCentre OverheadCC       = False
228 isSccCountCostCentre cc | isCafCC cc  = False
229                         | isDupdCC cc = False
230                         | isDictCC cc = True
231                         | otherwise   = True
232
233 sccAbleCostCentre :: CostCentre -> Bool
234   -- Is this a cost-centre which can be sccd ?
235
236 #if DEBUG
237 sccAbleCostCentre NoCostCentre  = panic "sccAbleCC:NoCostCentre"
238 sccAbleCostCentre SubsumedCosts = panic "sccAbleCC:SubsumedCosts"
239 sccAbleCostCentre CurrentCC     = panic "sccAbleCC:CurrentCC"
240 sccAbleCostCentre DontCareCC    = panic "sccAbleCC:DontCareCC"
241 #endif
242 sccAbleCostCentre OverheadCC      = False
243 sccAbleCostCentre cc | isCafCC cc = False
244                      | otherwise  = True
245
246 ccFromThisModule :: CostCentre -> FAST_STRING{-module name-} -> Bool
247
248 ccFromThisModule (NormalCC _ m _ _ _) mod_name = m == mod_name
249 ccFromThisModule (AllCafsCC  m _)     mod_name = m == mod_name
250 ccFromThisModule (AllDictsCC m _ _)   mod_name = m == mod_name
251 ccFromThisModule PreludeCafsCC        _        = False
252 ccFromThisModule (PreludeDictsCC _)   _        = False
253 ccFromThisModule OverheadCC           _        = False
254 ccFromThisModule DontCareCC           _        = False
255   -- shouldn't ask about any others!
256 \end{code}
257
258 \begin{code}
259 ccMentionsId :: CostCentre -> Maybe Id
260
261 ccMentionsId (NormalCC (AutoCC id) _ _ _ _) = Just id
262 ccMentionsId (NormalCC (DictCC id) _ _ _ _) = Just id
263 ccMentionsId other                          = Nothing
264 \end{code}
265
266 \begin{code}
267 cmpCostCentre :: CostCentre -> CostCentre -> TAG_
268
269 cmpCostCentre (AllCafsCC  m1 _)   (AllCafsCC  m2 _)   = _CMP_STRING_ m1 m2
270 cmpCostCentre (AllDictsCC m1 _ _) (AllDictsCC m2 _ _) = _CMP_STRING_ m1 m2
271 cmpCostCentre PreludeCafsCC       PreludeCafsCC       = EQ_
272 cmpCostCentre (PreludeDictsCC _)  (PreludeDictsCC _)  = EQ_
273 cmpCostCentre OverheadCC          OverheadCC          = EQ_
274 cmpCostCentre DontCareCC          DontCareCC          = EQ_
275
276 cmpCostCentre (NormalCC k1 m1 _ _ c1) (NormalCC k2 m2 _ _ c2)
277     -- first key is module name, then we use "kinds" (which include
278     -- names) and finally the caf flag
279   = _CMP_STRING_ m1 m2 `thenCmp` cmp_kind k1 k2 `thenCmp` cmp_caf c1 c2
280
281 cmpCostCentre other_1 other_2
282   = let
283         tag1 = tag_CC other_1
284         tag2 = tag_CC other_2
285     in
286     if tag1 _LT_ tag2 then LT_ else GT_
287   where
288     tag_CC (NormalCC _ _ _ _ _) = (ILIT(1) :: FAST_INT)
289     tag_CC (AllCafsCC  _ _)     = ILIT(2)
290     tag_CC (AllDictsCC _ _ _)   = ILIT(3)
291     tag_CC PreludeCafsCC        = ILIT(4)
292     tag_CC (PreludeDictsCC _)   = ILIT(5)
293     tag_CC OverheadCC           = ILIT(6)
294     tag_CC DontCareCC           = ILIT(7)
295
296     -- some BUG avoidance here...
297     tag_CC NoCostCentre  = panic# "tag_CC:NoCostCentre"
298     tag_CC SubsumedCosts = panic# "tag_CC:SubsumedCosts"
299     tag_CC CurrentCC     = panic# "tag_CC:SubsumedCosts"
300
301
302 cmp_kind (UserCC n1) (UserCC n2) = _CMP_STRING_ n1 n2
303 cmp_kind (AutoCC i1) (AutoCC i2) = cmp i1 i2
304 cmp_kind (DictCC i1) (DictCC i2) = cmp i1 i2
305 cmp_kind other_1     other_2
306   = let
307         tag1 = tag_CcKind other_1
308         tag2 = tag_CcKind other_2
309     in
310     if tag1 _LT_ tag2 then LT_ else GT_
311   where
312     tag_CcKind (UserCC _) = (ILIT(1) :: FAST_INT)
313     tag_CcKind (AutoCC _) = ILIT(2)
314     tag_CcKind (DictCC _) = ILIT(3)
315
316 cmp_caf IsNotCafCC IsCafCC     = LT_
317 cmp_caf IsNotCafCC IsNotCafCC  = EQ_
318 cmp_caf IsCafCC    IsCafCC     = EQ_
319 cmp_caf IsCafCC    IsNotCafCC  = GT_
320 \end{code}
321
322 \begin{code}
323 showCostCentre    :: PprStyle -> Bool -> CostCentre -> String
324 uppCostCentre     :: PprStyle -> Bool -> CostCentre -> Doc
325 uppCostCentreDecl :: PprStyle -> Bool -> CostCentre -> Doc
326
327 {-      PprUnfolding is gone now
328 showCostCentre PprUnfolding print_as_string cc
329   = ASSERT(not print_as_string) -- we never "print as string w/ Unfolding"
330     ASSERT(not (noCostCentreAttached cc))
331     ASSERT(not (currentOrSubsumedCosts cc))
332     uppShow 80 (upp_cc_uf cc)
333 -}
334
335 showCostCentre sty print_as_string cc
336   = show (uppCostCentre sty print_as_string cc)
337
338 uppCostCentre sty print_as_string NoCostCentre
339   | friendly_style sty  = empty
340   | print_as_string     = text "\"NO_CC\""
341   | otherwise           = ptext SLIT("NO_CC")
342
343 uppCostCentre sty print_as_string SubsumedCosts
344   | print_as_string     = text "\"SUBSUMED\""
345   | otherwise           = ptext SLIT("CC_SUBSUMED")
346
347 uppCostCentre sty print_as_string CurrentCC
348   | print_as_string     = text "\"CURRENT_CC\""
349   | otherwise           = ptext SLIT("CCC")
350
351 uppCostCentre sty print_as_string OverheadCC
352   | print_as_string     = text "\"OVERHEAD\""
353   | otherwise           = ptext SLIT("CC_OVERHEAD")
354
355 uppCostCentre sty print_as_string cc
356   = let
357         prefix_CC = ptext SLIT("CC_")
358
359         basic_thing = do_cc cc
360
361         basic_thing_string
362           = if friendly_sty then basic_thing else stringToC basic_thing
363     in
364     if print_as_string then
365         hcat [char '"', text basic_thing_string, char '"']
366
367     else if friendly_sty then
368         text basic_thing
369     else
370         hcat [prefix_CC, identToC (_PK_ basic_thing)]
371   where
372     friendly_sty = friendly_style sty
373
374     ----------------
375     do_cc DontCareCC         = "DONT_CARE"
376     do_cc (AllCafsCC  m _)   = if print_as_string
377                                then "CAFs_in_..."
378                                else "CAFs." ++ _UNPK_ m
379     do_cc (AllDictsCC m _ d) = do_dupd d (
380                                if print_as_string
381                                then "DICTs_in_..."
382                                else "DICTs." ++ _UNPK_ m)
383     do_cc PreludeCafsCC      = if print_as_string
384                                then "CAFs_in_..."
385                                else "CAFs"
386     do_cc (PreludeDictsCC d) = do_dupd d (
387                                if print_as_string
388                                then "DICTs_in_..."
389                                else "DICTs")
390
391     do_cc (NormalCC kind mod_name grp_name is_dupd is_caf)
392       = let
393             basic_kind  = do_kind kind
394             module_kind = do_caf is_caf (moduleString mod_name ++ '/':
395                                                basic_kind)
396             grp_str   = if (_NULL_ grp_name) then mod_name else grp_name
397             full_kind = do_caf is_caf
398                          (moduleString mod_name  ++ 
399                           ('/' : _UNPK_ grp_str) ++ 
400                           ('/' : basic_kind))
401         in
402         case sty of
403           PprForC -> do_caf is_caf basic_kind
404           _ ->
405             if friendly_sty then
406               do_dupd is_dupd full_kind
407             else
408               module_kind
409       where
410         do_caf IsCafCC ls = "CAF:" ++ ls
411         do_caf _       ls = ls
412
413         do_kind (UserCC name) = _UNPK_ name
414         do_kind (AutoCC id)   = do_id id ++ (if friendly_sty then "/AUTO" else "")
415         do_kind (DictCC id)   = do_id id ++ (if friendly_sty then "/DICT" else "")
416
417         {-
418          do_id is only applied in a (not print_as_string) context for local ids,
419          hence using the occurrence name is enough.
420         -}
421         do_id :: Id -> String
422         do_id id = getOccString id
423
424     ---------------
425     do_dupd ADupdCC str = if friendly_sty then str ++ "/DUPD" else str
426     do_dupd _       str = str
427
428 friendly_style sty -- i.e., probably for human consumption
429   = case sty of
430       PprForUser _ -> True
431       PprDebug   -> True
432       PprShowAll -> True
433       _          -> False
434 {-
435 friendly_style sty -- i.e., probably for human consumption
436   = not (codeStyle sty || ifaceStyle sty)
437 -}
438 \end{code}
439
440 Printing unfoldings is sufficiently weird that we do it separately.
441 This should only apply to CostCentres that can be ``set to'' (cf
442 @sccAbleCostCentre@).  That excludes CAFs and 
443 `overhead'---which are added at the very end---but includes dictionaries.
444 Dict \tr{_scc_}s may cross module boundaries to show ``scope'' info;
445 even if we won't ultimately do a \tr{SET_CCC} from it.
446 \begin{code}
447 upp_cc_uf (PreludeDictsCC d)
448   = hsep [ptext SLIT("_PRELUDE_DICTS_CC_"), upp_dupd d]
449 upp_cc_uf (AllDictsCC m g d)
450   = hsep [ptext SLIT("_ALL_DICTS_CC_"), 
451             char '"',ptext m,char '"',
452             char '"',ptext g,char '"',
453             upp_dupd d]
454
455 upp_cc_uf cc@(NormalCC cc_kind m g is_dupd is_caf)
456   = ASSERT(sccAbleCostCentre cc)
457     hsep [pp_kind cc_kind, 
458             char '"', ptext m, char '"', 
459             char '"', ptext g, char '"',
460             upp_dupd is_dupd, pp_caf is_caf]
461   where
462     pp_kind (UserCC name) = hcat [ptext SLIT("_USER_CC_ "), char '"', ptext name, char '"']
463     pp_kind (AutoCC id)   = (<>) (ptext SLIT("_AUTO_CC_ ")) (show_id id)
464     pp_kind (DictCC id)   = (<>) (ptext SLIT("_DICT_CC_ ")) (show_id id)
465
466     show_id id = pprIdInUnfolding {-no_in_scopes-} id
467
468     pp_caf IsCafCC    = ptext SLIT("_CAF_CC_")
469     pp_caf IsNotCafCC = ptext SLIT("_N_")
470
471 #ifdef DEBUG
472 upp_cc_uf other = panic ("upp_cc_uf:"++(showCostCentre PprDebug True other))
473 #endif
474
475 upp_dupd AnOriginalCC = ptext SLIT("_N_")
476 upp_dupd ADupdCC      = ptext SLIT("_D_")
477 \end{code}
478
479 \begin{code}
480 uppCostCentreDecl sty is_local cc
481 #ifdef DEBUG
482   | noCostCentreAttached cc || currentOrSubsumedCosts cc
483   = panic "uppCostCentreDecl: no cost centre!"
484   | otherwise
485 #endif
486   = if is_local then
487         hcat [
488             ptext SLIT("CC_DECLARE"),char '(',
489             upp_ident, comma,
490             uppCostCentre sty True {-as String!-} cc, comma,
491             pp_str mod_name, comma,
492             pp_str grp_name, comma,
493             text is_subsumed, comma,
494             if externally_visible then empty else ptext SLIT("static"),
495             text ");"]
496     else
497         hcat [ ptext SLIT("CC_EXTERN"),char '(', upp_ident, text ");" ]
498   where
499     upp_ident = uppCostCentre sty False{-as identifier!-} cc
500
501     pp_str s  = doubleQuotes (ptext s)
502
503     (mod_name, grp_name, is_subsumed, externally_visible)
504       = case cc of
505           AllCafsCC m g -> (m, g, cc_IS_CAF, True)
506
507           AllDictsCC m g _ -> (m, g, cc_IS_DICT, True)
508
509           NormalCC (DictCC i) m g is_dupd is_caf
510             -> (m, g, cc_IS_DICT, externallyVisibleId i)
511
512           NormalCC x m g is_dupd is_caf
513             -> (m, g, do_caf is_caf,
514                 case x of { UserCC _ -> True; AutoCC i -> externallyVisibleId i})
515       where
516         cc_IS_CAF      = "CC_IS_CAF"
517         cc_IS_DICT     = "CC_IS_DICT"
518         cc_IS_SUBSUMED = "CC_IS_SUBSUMED"
519         cc_IS_BORING   = "CC_IS_BORING"
520
521         do_caf IsCafCC       = cc_IS_CAF
522         do_caf IsNotCafCC    = cc_IS_BORING
523 \end{code}