• Simon Peyton Jones's avatar
    [project @ 1999-11-01 17:09:54 by simonpj] · 30b5ebe4
    Simon Peyton Jones authored
    A regrettably-gigantic commit that puts in place what Simon PJ
    has been up to for the last month or so, on and off.
    The basic idea was to restore unfoldings to *occurrences* of
    variables without introducing a space leak.  I wanted to make
    sure things improved relative to 4.04, and that proved depressingly
    hard.  On the way I discovered several quite serious bugs in the
    Here's a summary of what's gone on.
    * No commas between for-alls in RULES.  This makes the for-alls have
      the same syntax as in types.
    * Arrange that simplConArgs works in one less pass than before.
      This exposed a bug: a bogus call to completeBeta.
    * Add a top-level flag in CoreUnfolding, used in callSiteInline
    * Extend w/w to use etaExpandArity, so it does eta/coerce expansion
    * Implement inline phases.   The meaning of the inline pragmas is
      described in CoreUnfold.lhs.  You can say things like
    	{#- INLINE 2 build #-}
      to mean "inline build in phase 2"
    * Don't float anything out of an INLINE.
      Don't float things to top level unless they also escape a value lambda.
    	[see comments with SetLevels.lvlMFE
      Without at least one of these changes, I found that
    	{-# INLINE concat #-}
    	concat = __inline (/\a -> foldr (++) [])
      was getting floated to
    	concat = __inline( /\a -> lvl a )
    	lvl = ...inlined version of foldr...
      Subsequently I found that not floating constants out of an INLINE
      gave really bad code like
    	__inline (let x = e in \y -> ...)
      so I now let things float out of INLINE
    * Implement the "reverse-mapping" idea for CSE; actually it turned out to be easier
      to implement it in SetLevels, and may benefit full laziness too.
    * It's a good idea to inline inRange. Consider
    	index (l,h) i = case inRange (l,h) i of
    		  	  True ->  l+i
    			  False -> error
      inRange itself isn't strict in h, but if it't inlined then 'index'
      *does* become strict in h.  Interesting!
    * Big change to the way unfoldings and occurrence info is propagated in the simplifier
      The plan is described in Subst.lhs with the Subst type
      Occurrence info is now in a separate IdInfo field than user pragmas
    * I found that
    	(coerce T (coerce S (\x.e))) y
      didn't simplify in one round. First we get to
    	(\x.e) y
      and only then do the beta. Solution: cancel the coerces in the continuation
    * Amazingly, CoreUnfold wasn't counting the cost of a function an application.
    * Disable rules in initial simplifier run.  Otherwise full laziness
      doesn't get a chance to lift out a MFE before a rule (e.g. fusion)
      zaps it.  queens is a case in point
    * Improve float-out stuff significantly.  The big change is that if we have
    	\x -> ... /\a -> ...let p = ..a.. in let q = ...p...
      where p's rhs doesn't x, we abstract a from p, so that we can get p past x.
      (We did that before.)  But we also substitute (p a) for p in q, and then
      we can do the same thing for q.  (We didn't do that, so q got stuck.)
      This is much better.  It involves doing a substitution "as we go" in SetLevels,