#2422: Unrelated instance foils optimizer
--------------------------+-------------------------------------------------
    Reporter:  sedillard  |        Owner:             
        Type:  bug        |       Status:  new        
    Priority:  normal     |    Milestone:  6.10 branch
   Component:  Compiler   |      Version:  6.8.3      
    Severity:  normal     |   Resolution:             
    Keywords:             |   Difficulty:  Unknown    
    Testcase:             |           Os:  Linux      
Architecture:  x86        |  
--------------------------+-------------------------------------------------
Comment (by simonpj):

 Good example!   This is indeed what is making #2416 go bad, but it's much
 easier to see here.

 I've unraveled what's happening; just recording it here so I don't forget
 again. These remarks are mainly for me, so they may seem a bit cryptic.

 From the instance for `(Storable (a:.a:.v))` we get something like
 {{{
 Rec {
   $f3 = \d. MkStorable ...(pbo d)...
   pbo = \d. let pbo1 = peekByteOff ($f3 d) in \p q r. blah
 end Rec }
 }}}
 where `peekByteOff` is the method selector from the `Storable` class.
 (See `Note [How instance declarations are translated]` in `TcInstDcls` for
 the overall game plan.)  Then the simplifier inlines `$f3`, thereby
 breaking the recursion, to give
 {{{
 pbo = \d. let ...d... in \p q r. blah
 $f3 = \d. MkStorable ...(pbo d)...
 }}}

 Now, when you add the "unrelated" instance, the specialiser kicks in, and
 makes a specialised version of both functions:
 {{{
 $spbo = \p q r. blah blah blah
 $sf3 = MkStorable ...$spbo...
 }}}
 We've specialised for a particular dictionary `d`, and that means we can
 inline the specialised methods into `$spbo`.  Alas, that makes `$spbo`
 big, so now it does not inline into the users of `$sf3`.  Before, it did.
 In effect the unspecialised version looked a lot smaller than the
 specialised version.

 But what about the INLINE pragma, you say?  Well, it's hard to make it
 work right.  If it attaches to the whole `pbo` we'd get
 {{{
 Rec {
   $f3 = \d. MkStorable ...(pbo d)...
   pbo = __inline_me__ (\d. let pbo1 = peekByteOff ($f3 d) in \p q r. blah)
 end Rec }
 }}}
 But (for good reasons) we don't inline inside `__inline_me__`, so we won't
 get to break the recursive loop with `$f3`, which is terrible.  GHC 6.10
 currently pins the pragma on the body thus:
 {{{
 Rec {
   $f3 = \d. MkStorable ...(pbo d)...
   pbo = \d. let pbo1 = peekByteOff ($f3 d) in
         __inline_me__ (\p q r. blah)
 end Rec }
 }}}
 but this does not work right either (because eta expansion loses that
 `__inline_me__`).

 I think the new inlining mechanism will help a lot, but I need to get it
 installed first.  Stay tuned.

 Simon

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2422#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to