wiki:Commentary/Compiler/StrictnessAnalysis/KirstenNotes

Version 13 (modified by kirsten, 7 years ago) (diff)

offsets

Linearity

The solution is to distinguish call demands from product demands. Consider again:

let f = \ x. \ y. ... in
  ...(f 1 2)...(f 3 4)...

The demands placed on f by the first and second call get bothed together to yield SM(SM(T)). But this is incorrect. Consider:

let f = \ x. \ y. ... 
    frob = f 1 in
  ...(f 1 2)...(frob 2)...(frob 3)...

Here, the demands placed on f by the body of frob and by the call to f in the let-body get bothed together: S1(T) & S1(S1(T)) = SM(SM(T)). Note that this is the same as the demand placed on f above, yet we want to distinguish between the two situations, because in the first example, the inner lambda in f's rhs is only called once.

The solution is to treat call demands and product demands differently, and to define the both function for call demands to have the same behavior as lub. Then in the first example, f has demand SM(S1(T)) placed on it, and in the second, SM(T). This is what we want; now, if f has demand D(D(T) placed on it, that implies f is always called with two arguments.

Why does this make sense? Consider what it means if we see an example like:

let baz = lazyF p in
  case p of
    (a,b) -> strictF a b

(where lazyF is lazy in p, and strictF is strict in a and b). p is used both with demand L (in the call to lazyF and with demand S(SS) (in the call to strictF). This means it's perfectly same to strictly evaluate p, so when we both together the two demands, we should get S(SS). On the other hand, if a function is called once with one argument and once with two, we don't want to treat it as a function that's always called with two arguments; we're only interested in functions that are always called with n arguments for a given n. Hence, both should behave the same way as lub for call demands.

Ticky

The following code inserts extra fields into closures when ticky is enabled (and so had to be commented out):

staticTickyHdr :: [CmmLit]
-- The ticky header words in a static closure
-- Was SET_STATIC_TICKY_HDR
staticTickyHdr = 
  | not opt_DoTickyProfiling = []
  | otherwise		     = [zeroCLit]

in compiler/codeGen/CgTicky.hs.

Other relevant functions: emitTickyCounter in compiler/codeGen/CgTicky.hs (called by closureCodeBody in compiler/codeGen/CgClosure.lhs).

Argh! I spent days tracking down this bug: idInfoLabelType in compiler/cmm/CLabel.hs needs to return DataLabel for labels of type RednCount (i.e., labels for ticky counters.) By default, it was returning CodeLabel, which caused the ticky counter labels to get declared with the wrong type in the generated C, which caused C compiler errors.

Declarations for ticky counters

emitTickyCounter spits out C declarations that look like this:

static char c16O_str[] = "main:Main.$wrepeated{v r4}";

static char c16Q_str[] = "i";

StgWord Main_zdwrepeated_ct[] = {
0x0, 0x1U, 0x1U, 0x0, (W_)&c16O_str, (W_)&c16Q_str, 0x0, 0x0, 0x0
};

Here, Main_zdwrepeated_ct is actually an StgEntCounter (this type is declared in includes/StgTicky.h). The counters get used by printRegisteredCounterInfo in rts/Ticky.c, which prints out the ticky reports. The counter fields are accessed using offsets defined in includes/GHCConstants.h (oFFSET_StgEntCounter_*, which I think were wrong before.)