This email relates to the paper "Optimising generics is easy" 
www.cs.uu.nl/research/techreps/repo/CS-2009/2009-022.pdf.  Copying cvs-ghc who 
will, I think, be interested.  Maybe someone will have some good ideas.

Jose writes (about a case where inlining doesn't work well):

| I put a minimal source code for this test and resulting Core 
| (with GHC 6.13.20091115) in 
https://subversion.cs.uu.nl/repos/staff.jpm.public/Inline/. 
| UpdateInt behaves great: in UpdateInt.core.O1.hs, there are no traces of 
| generic representations in testOne, testTwo, testThree and testFour.

| UpdateString, however, does not behave so well. In UpdateString.core.O1.hs, 
| Test.testLogic_updateString still has loads of generic representations. 

OK, I've had a look.  It's easy to see what is happening.  Compile UpdateString 
with -ddump-simpl, and look at the core.  You see stuff like

Rec { $j1_rx32 = \x. <big nested case expression>
    ; f = \y. ....($j1_rx32 <big constructor expression>)
              ---($j1_rx32 <big constructor expression)....
    }

So here the $j (which is a "join point") isn't inlined because it's big, 
although if it *were* inlined there would be much goodness because the case 
expressions would cancel with the explicit constructors.

Why did this happen despite lots of INLINE pragmas?  I have not followed all 
the details, but I'm guessing that if we have, say

        {-# INLINE from #-}
        from = \x. case x of from_alts
        {-# INLINE to #-}
        to = \x. case x of to_alts

and we try to optimize this calle:
        from (to x)
then after inlining from and to we'll get
        case (case x of to_alts) of from_alts
And now the case-of-case transform happens, which creates the join points to 
avoid duplicating from_alts into every branch of to_alts.  You may say that 
we've already said that it's ok to duplicate from (and hence from_alts) but we 
duplicated it once when we inlined it, and then we forget the origin of the 
code.  And indeed, in the worse case you could get a quadratic blow up; and 
there are only two functions involved.  So I'm not unhappy with that.

However, it does make me wonder whether we could not do a better job on the 
above Rec {..}.  Two thoughts occur.

1. We could beef up SpecConstr.  It doesn't fire at the moment for some reason, 
even with -O2

2. If we have 
       f = \x. case x of { C1 x11..x1n -> e1; ... Ck xk1 ... xkm -> ek }
   maybe we should worker-wrapper it to
        f1 x1 .. x1n = e1
       ...
       fn xk1 .. xkm = en
        f = \x of pi -> fi xi
   and now inline f.

(2) is very similar to the way join points work right now, but it would make it 
multi-level. 

Interesting

Simon


_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to