------------------------- *** 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.