[GHC] #2273: inlining defeats seq

GHC trac at galois.com
Wed May 14 04:06:12 EDT 2008


#2273: inlining defeats seq
----------------------+-----------------------------------------------------
 Reporter:  igloo     |          Owner:         
     Type:  bug       |         Status:  new    
 Priority:  normal    |      Milestone:         
Component:  Compiler  |        Version:  6.9    
 Severity:  normal    |     Resolution:         
 Keywords:            |     Difficulty:  Unknown
 Testcase:            |   Architecture:  Unknown
       Os:  Unknown   |  
----------------------+-----------------------------------------------------
Comment (by simonpj):

 Thanks Ian -- nice report.  What is happening is this.  After inlining seq
 we get something like this:
 {{{
   let level = case x of { A -> 1; B -> 2 }
   in case level of { _ -> ...level... }
 }}}
 Now GHC thinks that the case-expression for `level` is cheap (which it
 is), and therefore ok to duplicate, so it inlines it
 {{{
   let level = case x of { A -> 1; B -> 2 }
   in case (case x of { A -> 1; B -> 2 }) of { _ -> ...level... }
 }}}
 Now there's only one remaining occurrence of `level` so that gets inlined
 too.  Disaster.

 This example has made me realise that what is ''really'' wrong here is
 that `seq` should really have a type more like
 {{{
   fseq :: a -> (a -> b) -> b
 }}}
 Then we'd have
 {{{
   level `fseq` (\level -> ...level...)
 }}}
 Now the inner `level` is nothing to do with the outer `level` and all will
 be well. So here we are saying what we mean: "evaluate `level` and use the
 evaluated version inside here".

 This version of `seq` is just reversed strict function application, of
 course.  Which is very like strict `let`.  So with bang patterns we could
 also write
 {{{
   let !level2 = level in ...level2...
 }}}
 This is satisfactorily explicit, but we must use a new name (`level2`).
 Perhaps that's not unreasonable.

 Both `fseq` and a strict let could desugar to
 {{{
    case level of level2 { _ -> ...level2... }
 }}}
 Meanwhile I think a good fix will be to change the desugarer to desugar
 saturated applications of `seq` to this same form.  Not very robust to
 abstraction, but better than what we have now.

 `seq` is subtler than it looks.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2273#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list