haskellfoundation / hs-opt-handbook.github.io

The Haskell Optimization Handbook
https://haskell.foundation/hs-opt-handbook.github.io/
Creative Commons Attribution 4.0 International
173 stars 12 forks source link

Direct Observation: Reading Core chapter #13

Open doyougnu opened 2 years ago

doyougnu commented 2 years ago

from the proposal

1.5 Direct Observation: Reading Core (and relating core to program behavior in detail)
1.5.1 Preliminaries: z-encoding, dumping and navigating core 
1.5.2 What allocation in Core looks like
1.5.3 Bad patterns in Core
1.5.4 Good patterns in Core
1.5.5 Demand analysis
1.5.6 Simplifier data in Core
1.5.7 Occurrence analysis 
1.5.8 Others?
doyougnu commented 1 year ago

In GHC.Types.Name.Occurrence we have the decoder ring:


-- These derived variables have a prefix that no Haskell value could have
mkDataConWrapperOcc = mk_simple_deriv varName  "$W"
mkWorkerOcc         = mk_simple_deriv varName  "$w"
mkMatcherOcc        = mk_simple_deriv varName  "$m"
mkBuilderOcc        = mk_simple_deriv varName  "$b"
mkDefaultMethodOcc  = mk_simple_deriv varName  "$dm"
mkClassOpAuxOcc     = mk_simple_deriv varName  "$c"
mkDictOcc           = mk_simple_deriv varName  "$d"
mkIPOcc             = mk_simple_deriv varName  "$i"
mkSpecOcc           = mk_simple_deriv varName  "$s"
mkForeignExportOcc  = mk_simple_deriv varName  "$f"
mkRepEqOcc          = mk_simple_deriv tvName   "$r"   -- In RULES involving Coercible
mkClassDataConOcc   = mk_simple_deriv dataName "C:"   -- Data con for a class
mkNewTyCoOcc        = mk_simple_deriv tcName   "N:"   -- Coercion for newtypes
mkInstTyCoOcc       = mk_simple_deriv tcName   "D:"   -- Coercion for type functions
mkEqPredCoOcc       = mk_simple_deriv tcName   "$co"
doyougnu commented 1 year ago

Aha $c is a derived name that is either a data con or a auxillary binding from a type class. That is, I think mkClassOpAuxOcc is make TypeClass operator auxillary occurrence. Looks like I forgot an important bit in the decoder ring:

-- Used in derived instances for the names of auxiliary bindings.
-- See Note [Auxiliary binders] in GHC.Tc.Deriv.Generate.
mkCon2TagOcc        = mk_simple_deriv varName  "$con2tag_"
mkTag2ConOcc        = mk_simple_deriv varName  "$tag2con_"
mkMaxTagOcc         = mk_simple_deriv varName  "$maxtag_"
mkDataTOcc          = mk_simple_deriv varName  "$t"
mkDataCOcc          = mk_simple_deriv varName  "$c"
doyougnu commented 1 year ago

$c is unique in that its overloaded then. I wonder why that's the case (and if it matters)

doyougnu commented 1 year ago

Ben's old post: https://bgamari.github.io/posts/2015-01-19-understanding-ghc-core.html

doyougnu commented 1 year ago

$l is a late lambda lift from STG:

-- | Hides away distracting bookkeeping while lambda lifting into a 'LiftM'
-- monad.
module GHC.Stg.Lift.Monad (
...
-- | Similarly to 'withSubstBndr', this function takes a set of variables to
-- abstract over, the binder to lift (and generate a fresh, substituted name
-- for) and a continuation in which that fresh, lifted binder is in scope.
--
-- It takes care of all the details involved with copying and adjusting the
-- binder and fresh name generation.
withLiftedBndr :: DIdSet -> Id -> (Id -> LiftM a) -> LiftM a
withLiftedBndr abs_ids bndr inner = do
  let str = fsLit "$l" `appendFS` occNameFS (getOccName bndr)
  let ty = mkLamTypes (dVarSetElems abs_ids) (idType bndr)
  bndr' <-
        -- See Note [transferPolyIdInfo] in GHC.Types.Id. We need to do this at least
        -- for arity information.
            transferPolyIdInfo bndr (dVarSetElems abs_ids)
        <$> mkSysLocalM str ManyTy ty
  LiftM $ RWS.local
    (\e -> e
      { e_subst = extendSubst bndr bndr' $ extendInScope bndr' $ e_subst e
      , e_expansions = extendVarEnv (e_expansions e) bndr abs_ids
      })
    (unwrapLiftM (inner bndr'))
doyougnu commented 1 year ago

Another good but out of date reference: https://www.scs.stanford.edu/11au-cs240h/notes/ghc-slides.html#(29)

doyougnu commented 1 year ago

gd stands for given dictionary and will be seen with GADT use: https://youtu.be/kyI9fjtgN7w?si=FCJWMImEAtYNK8eo&t=4442

doyougnu commented 1 year ago

$p is from a superclass:

module GHC.Types.Name.Occurrence (
...
mkSuperDictAuxOcc :: Int -> OccName -> OccName
mkSuperDictAuxOcc index cls_tc_occ
  = mk_deriv varName "$cp" [fsLit $ show index, occNameFS cls_tc_occ]

mkSuperDictSelOcc :: Int        -- ^ Index of superclass, e.g. 3
                  -> OccName    -- ^ Class, e.g. @Ord@
                  -> OccName    -- ^ Derived 'Occname', e.g. @$p3Ord@
mkSuperDictSelOcc index cls_tc_occ
  = mk_deriv varName "$p" [fsLit $ show index, occNameFS cls_tc_occ]
doyougnu commented 11 months ago

also see this ticket https://gitlab.haskell.org/ghc/ghc/-/issues/3781#note_535482

doyougnu commented 6 months ago

also see this ticket on the performance impacts on type classes: https://gitlab.haskell.org/ghc/ghc/-/issues/24679 basically GHC never unboxes type class dictionaries (which makes sense) but this can lead to slow downs if the specializer doesn't actually specialize