[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / compiler / NOTES
1         New back end thoughts
2
3 -----------------------------------------------------------------------------
4 Codegen notes
5
6 * jumps to ImpossibleBranch should be removed.
7
8 * Profiling:
9         - when updating a closure with an indirection to a function,
10           we should make a permanent indirection.
11
12         - check that we're bumping the scc count appropriately
13
14 * check perf & binary sizes against the HEAD
15
16 -----------------------------------------------------------------------------
17 C backend notes
18
19 * use STGCALL macros for foreign calls (doesn't look like volatile regs
20   are handled properly at the mo).
21
22 -----------------------------------------------------------------------------
23 Cmm parser notes
24
25 * switches
26
27 * need to cater for unexported procedures/info tables?
28
29 * We should be able to get rid of entry labels, use info labels only.
30   - we need a %ENTRY_LBL(info_lbl) macro, so that instead of
31      JMP_(foo_entry) we can write jump %ENTRY_LBL(foo_info).
32
33 -----------------------------------------------------------------------------
34
35 * Move arg-descr from LFInfo to ClosureInfo? 
36   But: only needed for functions
37
38 * Move all of CgClosure.link_caf into NewCaf, and newDynCaf
39
40 * If the case binder is dead, and the constr is nullary,
41   do we need to assign to Node?
42
43
44 -------------------------
45 * Relation between separate type sigs and pattern type sigs
46 f :: forall a. a->a
47 f :: b->b = e   -- No: monomorphic
48
49 f :: forall a. a->a
50 f :: forall a. a->a  -- OK
51
52 f :: forall a. [a] -> [a]
53 f :: forall b. b->b = e  ???
54
55
56 -------------------------------
57 NB: all floats are let-binds, but some non-rec lets
58     may be unlifted (with RHS ok-for-speculation)
59
60
61 simplArg:  [use strictness]
62            [used for non-top-lvl non-rec RHS or function arg]
63   if strict-type || demanded
64         simplStrictExpr
65   else
66         simplExpr ---> (floats,expr)
67         float all the floats if exposes constr app, return expr
68
69 simpl (applied lambda)      ==> simplNonRecBind
70 simpl (Let (NonRec ...) ..) ==> simplNonRecBind
71
72 simpl (Let (Rec ...)    ..) ==> simplRecBind
73
74 simplRecBind:
75   simplify binders (but not its IdInfo)
76   simplify the pairs one at a time
77         using simplRecPair
78
79 simplNonRecBind:        [was simplBeta]
80         [used for non-top-lvl non-rec bindings]
81   - check for PreInlineUnconditionally
82   - simplify binder, including its IdInfo
83   - simplArg
84   - if strict-type 
85         addCaseBind [which makes a let if ok-for-spec]
86     else
87         completeLazyBind
88
89 simplLazyBind:  [binder already simplified, but not its IdInfo]
90                 [used for both rec and top-lvl non-rec]
91                 [must not be strict/unboxed; case not allowed]
92   - check for PreInlineUnconditionally
93   - substituteIdInfo and add result to in-scope 
94         [so that rules are available in rec rhs]
95   - simplExpr --> (floats,expr)
96   - float: lifted floats only
97         if exposes constructor or pap (even if non-triv args)
98         or if top level
99   - completeLazyBind
100   
101
102 completeLazyBind:       [given a simplified RHS]
103         [used for both rec and non-rec bindings, top level and not]
104   - try discarding dead
105   - try PostInlineUnconditionally
106   - let-bind coerce arg and repeat
107   - try rhs tylam (float)
108   - try eta expand (float)    [not if any float is unlifted && (non-spec || top_lvl || rec)]
109   - let-bind constructor args [not if any float is ..as above..]
110
111   - add unfolding [this is the only place we add an unfolding]
112     add arity
113
114
115
116 Right hand sides and arguments
117 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118 In many ways we want to treat 
119         (a) the right hand side of a let(rec), and 
120         (b) a function argument
121 in the same way.  But not always!  In particular, we would
122 like to leave these arguments exactly as they are, so they
123 will match a RULE more easily.
124         
125         f (g x, h x)    
126         g (+ x)
127
128 It's harder to make the rule match if we ANF-ise the constructor,
129 or eta-expand the PAP:
130
131         f (let { a = g x; b = h x } in (a,b))
132         g (\y. + x y)
133
134 On the other hand if we see the let-defns
135
136         p = (g x, h x)
137         q = + x
138
139 then we *do* want to ANF-ise and eta-expand, so that p and q
140 can be safely inlined.   
141
142 Even floating lets out is a bit dubious.  For let RHS's we float lets
143 out if that exposes a value, so that the value can be inlined more vigorously.
144 For example
145
146         r = let x = e in (x,x)
147
148 Here, if we float the let out we'll expose a nice constructor. We did experiments
149 that showed this to be a generally good thing.  But it was a bad thing to float
150 lets out unconditionally, because that meant they got allocated more often.
151
152 For function arguments, there's less reason to expose a constructor (it won't
153 get inlined).  Just possibly it might make a rule match, but I'm pretty skeptical.
154 So for the moment we don't float lets out of function arguments either.
155
156
157 Eta expansion
158 ~~~~~~~~~~~~~~
159 For eta expansion, we want to catch things like
160
161         case e of (a,b) -> \x -> case a of (p,q) -> \y -> r
162
163 If the \x was on the RHS of a let, we'd eta expand to bring the two
164 lambdas together.  And in general that's a good thing to do.  Perhaps
165 we should eta expand wherever we find a (value) lambda?  Then the eta
166 expansion at a let RHS can concentrate solely on the PAP case.