See Note [ClassOp/DFun selection] in TcInstDcls, which I reproduce below.  Does 
that help?

Simon

Note [ClassOp/DFun selection]

One thing we see a lot is stuff like
    op2 (df d1 d2)
where 'op2' is a ClassOp and 'df' is DFun.  Now, we could inline *both*
'op2' and 'df' to get
     case (MkD ($cop1 d1 d2) ($cop2 d1 d2) ... of
       MkD _ op2 _ _ _ -> op2
And that will reduce to ($cop2 d1 d2) which is what we wanted.

But it's tricky to make this work in practice, because it requires us to
inline both 'op2' and 'df'.  But neither is keen to inline without having
seen the other's result; and it's very easy to get code bloat (from the
big intermediate) if you inline a bit too much.

Instead we use a cunning trick.
* We arrange that 'df' and 'op2' NEVER inline.

* We arrange that 'df' is ALWAYS defined in the sylised form
      df d1 d2 = MkD ($cop1 d1 d2) ($cop2 d1 d2) ...

* We give 'df' a magical unfolding (DFunUnfolding [$cop1, $cop2, ..])
   that lists its methods.

* We make CoreUnfold.exprIsConApp_maybe spot a DFunUnfolding and return
   a suitable constructor application -- inlining df "on the fly" as it
   were.

* We give the ClassOp 'op2' a BuiltinRule that extracts the right piece
   iff its argument satisfies exprIsConApp_maybe.  This is done in
   MkId mkDictSelId

* We make 'df' CONLIKE, so that shared uses stil match; eg
      let d = df d1 d2
      in ...(op2 d)...(op1 d)...
From: cvs-ghc-boun...@haskell.org [mailto:cvs-ghc-boun...@haskell.org] On 
Behalf Of Thomas Schilling
Sent: 15 November 2012 18:01
To: Cvs-ghc@haskell.org
Subject: Optimisation of type class methods / dictionaries

Hi,

I was investigating how GHC optimises dictionaries.  So, I'm using the 
following variant of the Eq type class:

    class XEq a where
      xeq, xne :: a -> a -> Bool
      xne a b = not (a `xeq` b) }

    instance XEq Bool where
      xeq True  True  = True
      xeq False False = True
      xeq _     _     = False

    instance XEq a => XEq [a] where
      xeq []     []     = True
      xeq (x:xs) (y:ys) = xeq x y && xeq xs ys
      xeq _             _ = False

I then compile this with:

     ghc -c -fforce-recomp -O2 -ddump-simpl -ddump-types <filename.hs>


I now have two questions regarding the output of the compiler.


Question 1: Why are the instance method selectors marked as NOINLINE?

Main.xeq [InlPrag=[NEVER]]
  :: forall a_aeV. Main.XEq a_aeV => a_aeV -> a_aeV -> GHC.Types.Bool



Question 2: The optimised code for the list implementation looks as follows:

Main.$fXEq[]_$cxeq [Occ=LoopBreaker]
  :: forall a_an3.
     Main.XEq a_an3 =>
     [a_an3] -> [a_an3] -> GHC.Types.Bool
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType LSS]
Main.$fXEq[]_$cxeq =
  \ (@ a_an3)
    ($dXEq_auY :: Main.XEq a_an3)
    (ds_dw8 :: [a_an3])
    (ds1_dw9 :: [a_an3]) ->
    case ds_dw8 of _ {
      [] ->
        case ds1_dw9 of _ {
          [] -> GHC.Types.True;
          : ipv_swB ipv1_swC -> GHC.Types.False
        };
      : x_an4 xs_an5 ->
        case ds1_dw9 of _ {
          [] -> GHC.Types.False;
          : y_an6 ys_an7 ->
            --- AAA
            case Main.xeq @ a_an3 $dXEq_auY x_an4 y_an6 of _ {
              GHC.Types.False -> GHC.Types.False;
              GHC.Types.True ->
                --- BBB
                Main.$fXEq[]_$cxeq @ a_an3 $dXEq_auY xs_an5 ys_an7
            }
        }
    }

If I turn off optimisation there are two calls to "xeq" which correspond 
exactly to the two calls from the implementation to either side of "&&".  In 
the optimised version, the second "xeq" has been inlined (marker BBB), but not 
the first one (marker AAA).  This is despite "xeq" being marked NOINLINE, by 
the way.  I would expect the code after AAA to look something like:

   case $dXEq_auY of _ {
     Main.D:XEq tpl_B2 _ ->
       case tpl_B2 x_an4 y_an6 of _ {
          ... ->

Adding -fdicts-strict to the command line also doesn't seem to convince the 
compiler to apply the worker/wrapper transformation and create a loop that just 
passes around the implementation of "xeq" instead of the whole dictionary.

Does anyone know what the issue is here?

Thanks,
  / Thomas
_______________________________________________
Cvs-ghc mailing list
Cvs-ghc@haskell.org
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to