2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[CostCentre]{The @CostCentre@ data type}
8 CostCentre, CcKind, IsDupdCC{-ToDo:rm-}, IsCafCC(..),
10 noCCS, subsumedCCS, currentCCS, overheadCCS, dontCareCCS,
11 noCostCentre, noCCAttached,
12 noCCSAttached, isCurrentCCS, isSubsumedCCS, currentOrSubsumedCCS,
14 mkUserCC, mkAutoCC, mkDictCC, mkAllCafsCC, mkAllDictsCC,
15 mkSingletonCCS, cafifyCC, dupifyCC,
16 isCafCC, isDictCC, isDupdCC, isEmptyCC, isCafCCS,
22 pprCostCentreDecl, pprCostCentreStackDecl,
24 cmpCostCentre -- used for removing dups in a list
27 #include "HsVersions.h"
29 import Var ( externallyVisibleId, Id )
30 import CStrings ( stringToC )
31 import Name ( Module, getOccString, moduleString, identToC, pprModule )
33 import Util ( thenCmp )
36 A Cost Centre Stack is something that can be attached to a closure.
39 - the current cost centre stack (CCCS)
40 - a pre-defined cost centre stack (there are several
41 pre-defined CCSs, see below).
47 | CurrentCCS -- Pinned on a let(rec)-bound
48 -- thunk/function/constructor, this says that the
49 -- cost centre to be attached to the object, when it
50 -- is allocated, is whatever is in the
51 -- current-cost-centre-stack register.
53 | SubsumedCCS -- Cost centre stack for top-level subsumed functions
54 -- (CAFs get an AllCafsCC).
55 -- Its execution costs get subsumed into the caller.
56 -- This guy is *only* ever pinned on static closures,
57 -- and is *never* the cost centre for an SCC construct.
59 | OverheadCCS -- We charge costs due to the profiling-system
60 -- doing its work to "overhead".
62 -- Objects whose CCS is "Overhead"
63 -- have their *allocation* charged to "overhead",
64 -- but have the current CCS put into the object
67 -- For example, if we transform "f g" to "let
68 -- g' = g in f g'" (so that something about
69 -- profiling works better...), then we charge
70 -- the *allocation* of g' to OverheadCCS, but
71 -- we put the cost-centre of the call to f
72 -- (i.e., current CCS) into the g' object. When
73 -- g' is entered, the CCS of the call
76 | DontCareCCS -- We need a CCS to stick in static closures
77 -- (for data), but we *don't* expect them to
78 -- accumulate any costs. But we still need
79 -- the placeholder. This CCS is it.
81 | SingletonCCS CostCentre
82 -- This is primarily for CAF cost centres, which
83 -- are attached to top-level thunks right at the
84 -- end of STG processing, before code generation.
85 -- Hence, a CAF cost centre never appears as the
86 -- argument of an _scc_.
87 -- Also, we generate these singleton CCSs statically
88 -- as part of code generation.
90 deriving (Eq, Ord) -- needed for Ord on CLabel
93 A Cost Centre is the argument of an _scc_ expression.
96 type Group = FAST_STRING -- "Group" that this CC is in; eg directory
99 = NoCostCentre -- Having this constructor avoids having
100 -- to use "Maybe CostCentre" all the time.
102 | NormalCC CcKind -- CcKind will include a cost-centre name
103 Module -- Name of module defining this CC.
104 Group -- "Group" that this CC is in.
105 IsDupdCC -- see below
108 | AllCafsCC Module -- Ditto for CAFs.
109 Group -- We record module and group names.
110 -- Again, one "big" CAF cc per module, where all
111 -- CAF costs are attributed unless the user asked for
112 -- per-individual-CAF cost attribution.
114 | AllDictsCC Module -- Ditto for dictionaries.
115 Group -- We record module and group names.
116 -- Again, one "big" DICT cc per module, where all
117 -- DICT costs are attributed unless the user asked for
118 -- per-individual-DICT cost attribution.
119 IsDupdCC -- see below
122 = UserCC FAST_STRING -- Supplied by user: String is the cc name
123 | AutoCC Id -- CC -auto-magically inserted for that Id
127 = AnOriginalCC -- This says how the CC is *used*. Saying that
128 | ADupdCC -- it is ADupdCC doesn't make it a different
129 -- CC, just that it a sub-expression which has
130 -- been moved ("dupd") into a different scope.
132 -- The point about a dupd SCC is that we don't
133 -- count entries to it, because it's not the
136 -- In the papers, it's called "SCCsub",
137 -- i.e. SCCsub CC == SCC ADupdCC,
138 -- but we are trying to avoid confusion between
139 -- "subd" and "subsumed". So we call the former
147 WILL: Would there be any merit to recording ``I am now using a
148 cost-centre from another module''? I don't know if this would help a
149 user; it might be interesting to us to know how much computation is
150 being moved across module boundaries.
152 SIMON: Maybe later...
157 subsumedCCS = SubsumedCCS
158 currentCCS = CurrentCCS
159 overheadCCS = OverheadCCS
160 dontCareCCS = DontCareCCS
162 noCostCentre = NoCostCentre
165 Predicates on Cost-Centre Stacks
168 noCCSAttached NoCCS = True
169 noCCSAttached _ = False
171 noCCAttached NoCostCentre = True
172 noCCAttached _ = False
174 isCurrentCCS CurrentCCS = True
175 isCurrentCCS _ = False
177 isSubsumedCCS SubsumedCCS = True
178 isSubsumedCCS _ = False
180 isCafCCS (SingletonCCS cc) = isCafCC cc
183 isDictCCS (SingletonCCS cc) = isDictCC cc
186 currentOrSubsumedCCS SubsumedCCS = True
187 currentOrSubsumedCCS CurrentCCS = True
188 currentOrSubsumedCCS _ = False
191 Building cost centres
194 mkUserCC :: FAST_STRING -> Module -> Group -> CostCentre
196 mkUserCC cc_name module_name group_name
197 = NormalCC (UserCC cc_name) module_name group_name
198 AnOriginalCC IsNotCafCC{-might be changed-}
200 mkDictCC, mkAutoCC :: Id -> Module -> Group -> IsCafCC -> CostCentre
202 mkDictCC id module_name group_name is_caf
203 = NormalCC (DictCC id) module_name group_name
206 mkAutoCC id module_name group_name is_caf
207 = NormalCC (AutoCC id) module_name group_name
210 mkAllCafsCC m g = AllCafsCC m g
211 mkAllDictsCC m g is_dupd
212 = AllDictsCC m g (if is_dupd then ADupdCC else AnOriginalCC)
214 mkSingletonCCS :: CostCentre -> CostCentreStack
215 mkSingletonCCS cc = SingletonCCS cc
217 cafifyCC, dupifyCC :: CostCentre -> CostCentre
219 cafifyCC cc@(AllDictsCC _ _ _) = cc -- ToDo ???
220 cafifyCC (NormalCC kind m g is_dupd is_caf)
221 = ASSERT(not_a_calf_already is_caf)
222 NormalCC kind m g is_dupd IsCafCC
224 not_a_calf_already IsCafCC = False
225 not_a_calf_already _ = True
226 cafifyCC cc = pprPanic "cafifyCC" (ppr cc)
228 dupifyCC (AllDictsCC m g _) = AllDictsCC m g ADupdCC
229 dupifyCC (NormalCC kind m g is_dupd is_caf)
230 = NormalCC kind m g ADupdCC is_caf
231 dupifyCC cc = pprPanic "dupifyCC" (ppr cc)
233 isEmptyCC, isCafCC, isDictCC, isDupdCC :: CostCentre -> Bool
235 isEmptyCC (NoCostCentre) = True
238 isCafCC (AllCafsCC _ _) = True
239 isCafCC (NormalCC _ _ _ _ IsCafCC) = True
242 isDictCC (AllDictsCC _ _ _) = True
243 isDictCC (NormalCC (DictCC _) _ _ _ _) = True
246 isDupdCC (AllDictsCC _ _ ADupdCC) = True
247 isDupdCC (NormalCC _ _ _ ADupdCC _) = True
250 isSccCountCostCentre :: CostCentre -> Bool
251 -- Is this a cost-centre which records scc counts
254 isSccCountCostCentre NoCostCentre = panic "isSccCount:NoCostCentre"
256 isSccCountCostCentre cc | isCafCC cc = False
257 | isDupdCC cc = False
261 sccAbleCostCentre :: CostCentre -> Bool
262 -- Is this a cost-centre which can be sccd ?
265 sccAbleCostCentre NoCostCentre = panic "sccAbleCC:NoCostCentre"
267 sccAbleCostCentre cc | isCafCC cc = False
270 ccFromThisModule :: CostCentre -> Module -> Bool
272 ccFromThisModule (NormalCC _ m _ _ _) mod_name = m == mod_name
273 ccFromThisModule (AllCafsCC m _) mod_name = m == mod_name
274 ccFromThisModule (AllDictsCC m _ _) mod_name = m == mod_name
278 ccMentionsId :: CostCentre -> Maybe Id
280 ccMentionsId (NormalCC (AutoCC id) _ _ _ _) = Just id
281 ccMentionsId (NormalCC (DictCC id) _ _ _ _) = Just id
282 ccMentionsId other = Nothing
286 instance Eq CostCentre where
287 c1 == c2 = case c1 `cmpCostCentre` c2 of { EQ -> True; _ -> False }
289 instance Ord CostCentre where
290 compare = cmpCostCentre
292 cmpCostCentre :: CostCentre -> CostCentre -> Ordering
294 cmpCostCentre (AllCafsCC m1 _) (AllCafsCC m2 _) = m1 `compare` m2
295 cmpCostCentre (AllDictsCC m1 _ _) (AllDictsCC m2 _ _) = m1 `compare` m2
297 cmpCostCentre (NormalCC k1 m1 _ _ c1) (NormalCC k2 m2 _ _ c2)
298 -- first key is module name, then we use "kinds" (which include
299 -- names) and finally the caf flag
300 = (m1 `compare` m2) `thenCmp` (k1 `cmp_kind` k2) `thenCmp` (c1 `cmp_caf` c2)
302 cmpCostCentre other_1 other_2
304 tag1 = tag_CC other_1
305 tag2 = tag_CC other_2
307 if tag1 _LT_ tag2 then LT else GT
309 tag_CC (NormalCC _ _ _ _ _) = (ILIT(1) :: FAST_INT)
310 tag_CC (AllCafsCC _ _) = ILIT(2)
311 tag_CC (AllDictsCC _ _ _) = ILIT(3)
313 cmp_kind (UserCC n1) (UserCC n2) = n1 `compare` n2
314 cmp_kind (AutoCC i1) (AutoCC i2) = i1 `compare` i2
315 cmp_kind (DictCC i1) (DictCC i2) = i1 `compare` i2
316 cmp_kind other_1 other_2
318 tag1 = tag_CcKind other_1
319 tag2 = tag_CcKind other_2
321 if tag1 _LT_ tag2 then LT else GT
323 tag_CcKind (UserCC _) = (ILIT(1) :: FAST_INT)
324 tag_CcKind (AutoCC _) = ILIT(2)
325 tag_CcKind (DictCC _) = ILIT(3)
327 cmp_caf IsNotCafCC IsCafCC = LT
328 cmp_caf IsNotCafCC IsNotCafCC = EQ
329 cmp_caf IsCafCC IsCafCC = EQ
330 cmp_caf IsCafCC IsNotCafCC = GT
333 -----------------------------------------------------------------------------
334 Printing Cost Centre Stacks.
336 There are two ways to print a CCS:
338 - for debugging output (i.e. -ddump-whatever),
342 instance Outputable CostCentreStack where
343 ppr ccs = case ccs of
344 NoCCS -> ptext SLIT("NO_CCS")
345 CurrentCCS -> ptext SLIT("CCCS")
346 OverheadCCS -> ptext SLIT("CCS_OVERHEAD")
347 DontCareCCS -> ptext SLIT("CCS_DONTZuCARE")
348 SubsumedCCS -> ptext SLIT("CCS_SUBSUMED")
350 getPprStyle $ \sty ->
352 then ptext SLIT("CCS_") <>
353 ptext (identToC (costCentreStr cc))
354 else ptext SLIT("CCS.") <> text (costCentreStr cc)
356 pprCostCentreStackDecl :: CostCentreStack -> SDoc
358 pprCostCentreStackDecl ccs@(SingletonCCS cc)
360 (mod_name, grp_name, is_subsumed, externally_visible) = get_cc_info cc
362 hcat [ ptext SLIT("CCS_DECLARE"), char '(',
363 ppr ccs, comma, -- better be codeStyle
364 ppCostCentreLbl cc, comma,
365 ptext is_subsumed, comma,
366 if externally_visible
368 else ptext SLIT("static"),
372 pprCostCentreStackDecl ccs
373 = pprPanic "pprCostCentreStackDecl: " (ppr ccs)
376 -----------------------------------------------------------------------------
377 Printing Cost Centres.
379 There are several different ways in which we might want to print a
382 - the name of the cost centre, for profiling output (a C string)
383 - the label, i.e. C label for cost centre in .hc file.
384 - the debugging name, for output in -ddump things
385 - the interface name, for printing in _scc_ exprs in iface files.
387 The last 3 are derived from costCentreStr below. The first is given
391 instance Outputable CostCentre where
392 ppr cc = getPprStyle $ \ sty ->
394 then ppCostCentreLbl cc
397 then ppCostCentreIface cc
398 else text (costCentreStr cc)
400 ppCostCentreLbl cc = ptext SLIT("CC_") <> ptext (identToC (costCentreStr cc))
401 ppCostCentreIface cc = doubleQuotes (text (costCentreStr cc))
402 ppCostCentreName cc = doubleQuotes (text (stringToC (costCentreName cc)))
404 costCentreStr (NoCostCentre) = "NO_CC"
405 costCentreStr (AllCafsCC m _) = "CAFs." ++ moduleString m
406 costCentreStr (AllDictsCC m _ d) = "DICTs." ++ moduleString m
407 costCentreStr (NormalCC kind mod_name grp_name is_dupd is_caf)
408 = case is_caf of { IsCafCC -> "CAF:"; _ -> "" }
409 ++ moduleString mod_name
410 ++ case kind of { UserCC name -> _UNPK_ name;
411 AutoCC id -> getOccString id ++ "/AUTO";
412 DictCC id -> getOccString id ++ "/DICT"
415 ++ case is_dupd of { ADupdCC -> "/DUPD"; _ -> "" }
417 -- This is the name to go in the cost centre declaration
418 costCentreName (NoCostCentre) = "NO_CC"
419 costCentreName (AllCafsCC _ _) = "CAFs_in_..."
420 costCentreName (AllDictsCC _ _ _) = "DICTs_in_..."
421 costCentreName (NormalCC kind mod_name grp_name is_dupd is_caf)
422 = case is_caf of { IsCafCC -> "CAF:"; _ -> "" }
423 ++ case kind of { UserCC name -> _UNPK_ name;
424 AutoCC id -> getOccString id;
425 DictCC id -> getOccString id
429 Cost Centre Declarations
433 pprCostCentreDecl is_local (NoCostCentre)
434 = panic "pprCostCentreDecl: no cost centre!"
436 pprCostCentreDecl is_local cc
439 ptext SLIT("CC_DECLARE"),char '(',
441 ppCostCentreName cc, comma,
442 doubleQuotes (pprModule mod_name), comma,
443 doubleQuotes (ptext grp_name), comma,
444 ptext is_subsumed, comma,
445 if externally_visible
447 else ptext SLIT("static"),
450 hcat [ ptext SLIT("CC_EXTERN"),char '(', cc_ident, text ");" ]
452 cc_ident = ppCostCentreLbl cc
454 (mod_name, grp_name, is_subsumed, externally_visible)
458 get_cc_info :: CostCentre ->
461 FAST_STRING, -- subsumed value
462 Bool) -- externally visible
466 AllCafsCC m g -> (m, g, cc_IS_CAF, True)
468 AllDictsCC m g _ -> (m, g, cc_IS_DICT, True)
470 NormalCC (DictCC i) m g is_dupd is_caf
471 -> (m, g, cc_IS_DICT, externallyVisibleId i)
473 NormalCC x m g is_dupd is_caf
474 -> (m, g, do_caf is_caf,
475 case x of { UserCC _ -> True; AutoCC i -> externallyVisibleId i})
477 cc_IS_CAF = SLIT("CC_IS_CAF")
478 cc_IS_DICT = SLIT("CC_IS_DICT")
479 cc_IS_BORING = SLIT("CC_IS_BORING")
481 do_caf IsCafCC = cc_IS_CAF
482 do_caf IsNotCafCC = cc_IS_BORING