summaryrefslogtreecommitdiff
path: root/compiler/NOTES
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/NOTES')
-rw-r--r--compiler/NOTES171
1 files changed, 171 insertions, 0 deletions
diff --git a/compiler/NOTES b/compiler/NOTES
new file mode 100644
index 0000000000..8c62750008
--- /dev/null
+++ b/compiler/NOTES
@@ -0,0 +1,171 @@
+
+-------------------------
+*** unexpected failure for jtod_circint(opt)
+
+
+ New back end thoughts
+
+-----------------------------------------------------------------------------
+Codegen notes
+
+* jumps to ImpossibleBranch should be removed.
+
+* Profiling:
+ - when updating a closure with an indirection to a function,
+ we should make a permanent indirection.
+
+ - check that we're bumping the scc count appropriately
+
+* check perf & binary sizes against the HEAD
+
+-----------------------------------------------------------------------------
+C backend notes
+
+* use STGCALL macros for foreign calls (doesn't look like volatile regs
+ are handled properly at the mo).
+
+-----------------------------------------------------------------------------
+Cmm parser notes
+
+* switches
+
+* need to cater for unexported procedures/info tables?
+
+* We should be able to get rid of entry labels, use info labels only.
+ - we need a %ENTRY_LBL(info_lbl) macro, so that instead of
+ JMP_(foo_entry) we can write jump %ENTRY_LBL(foo_info).
+
+-----------------------------------------------------------------------------
+
+* Move arg-descr from LFInfo to ClosureInfo?
+ But: only needed for functions
+
+* Move all of CgClosure.link_caf into NewCaf, and newDynCaf
+
+* If the case binder is dead, and the constr is nullary,
+ do we need to assign to Node?
+
+
+-------------------------
+* Relation between separate type sigs and pattern type sigs
+f :: forall a. a->a
+f :: b->b = e -- No: monomorphic
+
+f :: forall a. a->a
+f :: forall a. a->a -- OK
+
+f :: forall a. [a] -> [a]
+f :: forall b. b->b = e ???
+
+
+-------------------------------
+NB: all floats are let-binds, but some non-rec lets
+ may be unlifted (with RHS ok-for-speculation)
+
+
+simplArg: [use strictness]
+ [used for non-top-lvl non-rec RHS or function arg]
+ if strict-type || demanded
+ simplStrictExpr
+ else
+ simplExpr ---> (floats,expr)
+ float all the floats if exposes constr app, return expr
+
+simpl (applied lambda) ==> simplNonRecBind
+simpl (Let (NonRec ...) ..) ==> simplNonRecBind
+
+simpl (Let (Rec ...) ..) ==> simplRecBind
+
+simplRecBind:
+ simplify binders (but not its IdInfo)
+ simplify the pairs one at a time
+ using simplRecPair
+
+simplNonRecBind: [was simplBeta]
+ [used for non-top-lvl non-rec bindings]
+ - check for PreInlineUnconditionally
+ - simplify binder, including its IdInfo
+ - simplArg
+ - if strict-type
+ addCaseBind [which makes a let if ok-for-spec]
+ else
+ completeLazyBind
+
+simplLazyBind: [binder already simplified, but not its IdInfo]
+ [used for both rec and top-lvl non-rec]
+ [must not be strict/unboxed; case not allowed]
+ - check for PreInlineUnconditionally
+ - substituteIdInfo and add result to in-scope
+ [so that rules are available in rec rhs]
+ - simplExpr --> (floats,expr)
+ - float: lifted floats only
+ if exposes constructor or pap (even if non-triv args)
+ or if top level
+ - completeLazyBind
+
+
+completeLazyBind: [given a simplified RHS]
+ [used for both rec and non-rec bindings, top level and not]
+ - try discarding dead
+ - try PostInlineUnconditionally
+ - let-bind coerce arg and repeat
+ - try rhs tylam (float)
+ - try eta expand (float) [not if any float is unlifted && (non-spec || top_lvl || rec)]
+ - let-bind constructor args [not if any float is ..as above..]
+
+ - add unfolding [this is the only place we add an unfolding]
+ add arity
+
+
+
+Right hand sides and arguments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In many ways we want to treat
+ (a) the right hand side of a let(rec), and
+ (b) a function argument
+in the same way. But not always! In particular, we would
+like to leave these arguments exactly as they are, so they
+will match a RULE more easily.
+
+ f (g x, h x)
+ g (+ x)
+
+It's harder to make the rule match if we ANF-ise the constructor,
+or eta-expand the PAP:
+
+ f (let { a = g x; b = h x } in (a,b))
+ g (\y. + x y)
+
+On the other hand if we see the let-defns
+
+ p = (g x, h x)
+ q = + x
+
+then we *do* want to ANF-ise and eta-expand, so that p and q
+can be safely inlined.
+
+Even floating lets out is a bit dubious. For let RHS's we float lets
+out if that exposes a value, so that the value can be inlined more vigorously.
+For example
+
+ r = let x = e in (x,x)
+
+Here, if we float the let out we'll expose a nice constructor. We did experiments
+that showed this to be a generally good thing. But it was a bad thing to float
+lets out unconditionally, because that meant they got allocated more often.
+
+For function arguments, there's less reason to expose a constructor (it won't
+get inlined). Just possibly it might make a rule match, but I'm pretty skeptical.
+So for the moment we don't float lets out of function arguments either.
+
+
+Eta expansion
+~~~~~~~~~~~~~~
+For eta expansion, we want to catch things like
+
+ case e of (a,b) -> \x -> case a of (p,q) -> \y -> r
+
+If the \x was on the RHS of a let, we'd eta expand to bring the two
+lambdas together. And in general that's a good thing to do. Perhaps
+we should eta expand wherever we find a (value) lambda? Then the eta
+expansion at a let RHS can concentrate solely on the PAP case.