#5809: Arity analysis could be better
---------------------------------+------------------------------------------
    Reporter:  simonmar          |       Owner:  simonpj                
        Type:  bug               |      Status:  new                    
    Priority:  normal            |   Milestone:  7.6.1                  
   Component:  Compiler          |     Version:  7.5                    
    Keywords:                    |          Os:  Unknown/Multiple       
Architecture:  Unknown/Multiple  |     Failure:  Runtime performance bug
  Difficulty:  Unknown           |    Testcase:                         
   Blockedby:                    |    Blocking:                         
     Related:                    |  
---------------------------------+------------------------------------------
 Here's an example I tripped over while optimising Hoopl.  Given the
 following source code:

 {{{
 -- | if the graph being analyzed is open at the entry, there must
 --   be no other entry point, or all goes horribly wrong...
 analyzeFwd
    :: forall n f e .  NonLocal n =>
       FwdPass FuelUniqSM n f
    -> MaybeC e [Label]
    -> Graph n e C -> Fact e f
    -> FactBase f
 analyzeFwd FwdPass { fp_lattice = lattice,
                      fp_transfer = FwdTransfer3 (ftr, mtr, ltr) }
   entries g in_fact = graph g in_fact
   where
     graph :: Graph n e C -> Fact e f -> FactBase f
     graph (GMany entry blockmap NothingO)
       = case (entries, entry) of
          (NothingC, JustO entry)   -> block entry `cat` body (successors
 entry)
          (JustC entries, NothingO) -> body entries
          _ -> error "bogus GADT pattern match failure"
      where
        body  :: [Label] -> Fact C f -> Fact C f
        body entries f
          = fixpoint_anal Fwd lattice do_block entries blockmap f
          where
            do_block :: forall x . Block n C x -> FactBase f -> Fact x f
            do_block b fb = block b entryFact
              where entryFact = getFact lattice (entryLabel b) fb

     block :: forall e x . Block n e x -> f -> Fact x f
     block BNil            = id
     block (BlockCO n b)   = ftr n `cat` block b
     block (BlockCC l b n) = ftr l `cat` block b `cat` ltr n
     block (BlockOC   b n) =             block b `cat` ltr n

     block (BMiddle n)     = mtr n
     block (BCat b1 b2)    = block b1 `cat` block b2
     block (BHead h n)     = block h  `cat` mtr n
     block (BTail n t)     = mtr  n   `cat` block t

     {-# INLINE cat #-}
     cat ft1 ft2 = \f -> ft2 (ft1 f)
 }}}

 GHC does not eta-expand `block`, resulting in terrible code.

 {{{
       block_s2bB [Occ=LoopBreaker]
         :: forall e1_aPa x_aPb.
            Compiler.Hoopl.Graph.Block n_aGr e1_aPa x_aPb
            -> f_aGs -> Compiler.Hoopl.Dataflow.Fact x_aPb f_aGs
       [LclId, Arity=1, Str=DmdType S]
       block_s2bB =
         \ (@ e1_a1g7)
           (@ x_a1g8)
           (ds1_d1Le :: Compiler.Hoopl.Graph.Block n_aGr e1_a1g7 x_a1g8) ->
           case ds1_d1Le of _ {
             Compiler.Hoopl.Graph.BlockCO rb1_d1QD rb2_d1QE n_aPo b_aPp ->
               let {
                 a4_s2ri [Dmd=Just L]
                   :: f_aGs
                      -> Compiler.Hoopl.Dataflow.Fact
 Compiler.Hoopl.Graph.O f_aGs
                 [LclId, Str=DmdType]
                 a4_s2ri =
                   block_s2bB
                     @ Compiler.Hoopl.Graph.O @ Compiler.Hoopl.Graph.O
 b_aPp } in
               let {
                 ft1_aPC [Dmd=Just L] :: f_aGs -> f_aGs
                 [LclId, Str=DmdType]
                 ft1_aPC = ww2_s2Dc n_aPo } in
               (\ (f_aPE :: f_aGs) -> a4_s2ri (ft1_aPC f_aPE))
               `cast` (<f_aGs>
                       -> Compiler.Hoopl.Dataflow.TFCo:R:FactOf
                            (Sym
                               (Compiler.Hoopl.Dataflow.TFCo:R:FactOf
                                  <f_aGs>) ; Compiler.Hoopl.Dataflow.Fact
 (Sym rb2_d1QE) <f_aGs>)
                       :: (f_aGs
                           -> Compiler.Hoopl.Dataflow.Fact
                                Compiler.Hoopl.Graph.O
 (Compiler.Hoopl.Dataflow.R:FactOf f_aGs))
                            ~#
                          (f_aGs
                           -> Compiler.Hoopl.Dataflow.R:FactOf
                                (Compiler.Hoopl.Dataflow.Fact x_a1g8
 f_aGs)));
 }}}

 In order to eta-expand `block`, GHC would have to realise that `graph` is
 always called with 2 arguments, which means that `block` is always called
 with 2 arguments (even though it calls itself recursively with only one
 argument).

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5809>
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