GHC.Core.Opt.Arity

ghc-lib-parser-9.14.1.20251220: The GHC API, decoupled from GHC versions

Safe Haskell | Ignore
Language | GHC2021

GHC.Core.Opt.Arity

Contents

- Eta expansion
- Eta reduction
- ArityType
- Bottoming things
- typeArity and the state hack
- Lambdas
  - Join points
  - Coercions and casts

Description

Arity and eta expansion

Synopsis

- manifestArity :: CoreExpr -> Arity
- joinRhsArity :: CoreExpr -> JoinArity
- exprArity :: CoreExpr -> Arity
- findRhsArity :: ArityOpts -> RecFlag -> Id -> CoreExpr -> (Bool, SafeArityType)
- cheapArityType :: HasDebugCallStack => CoreExpr -> ArityType
- data ArityOpts = ArityOpts {
  - ao_ped_bot :: !Bool
  - ao_dicts_cheap :: !Bool
  }
- exprEtaExpandArity :: HasDebugCallStack => ArityOpts -> CoreExpr -> Maybe SafeArityType
- etaExpand :: Arity -> CoreExpr -> CoreExpr
- etaExpandAT :: InScopeSet -> SafeArityType -> CoreExpr -> CoreExpr
- tryEtaReduce :: UnVarSet -> [Var] -> CoreExpr -> SubDemand -> Maybe CoreExpr
- data ArityType
- mkBotArityType :: [OneShotInfo] -> ArityType
- arityTypeArity :: SafeArityType -> Arity
- idArityType :: Id -> ArityType
- exprIsDeadEnd :: CoreExpr -> Bool
- exprBotStrictness_maybe :: CoreExpr -> Maybe (Arity, DmdSig, CprSig)
- arityTypeBotSigs_maybe :: ArityType -> Maybe (Arity, DmdSig, CprSig)
- typeArity :: Type -> Arity
- typeOneShots :: Type -> [OneShotInfo]
- typeOneShot :: Type -> OneShotInfo
- isOneShotBndr :: Var -> Bool
- isStateHackType :: Type -> Bool
- zapLamBndrs :: FullArgCount -> [Var] -> [Var]
- etaExpandToJoinPoint :: JoinArity -> CoreExpr -> ([CoreBndr], CoreExpr)
- etaExpandToJoinPointRule :: JoinArity -> CoreRule -> CoreRule
- pushCoArg :: CoercionR -> CoreArg -> Maybe (CoreArg, MCoercion)
- pushCoArgs :: CoercionR -> [CoreArg] -> Maybe ([CoreArg], MCoercion)
- pushCoValArg :: CoercionR -> Maybe (MCoercionR, MCoercionR)
- pushCoTyArg :: CoercionR -> Type -> Maybe (Type, MCoercionR)
- pushCoercionIntoLambda :: HasDebugCallStack => InScopeSet -> Var -> CoreExpr -> CoercionR -> Maybe (Var, CoreExpr)
- pushCoDataCon :: DataCon -> [CoreExpr] -> MCoercionR -> Maybe (DataCon, [Type], [CoreExpr])
- collectBindersPushingCo :: CoreExpr -> ([Var], CoreExpr)

# Documentation

manifestArity :: CoreExpr -> Arity #

manifestArity sees how many leading value lambdas there are, after looking through casts

joinRhsArity :: CoreExpr -> JoinArity #

exprArity :: CoreExpr -> Arity #

An approximate, even faster, version of `cheapArityType` Roughly exprArity e = arityTypeArity (cheapArityType e) But it's a bit less clever about bottoms

We do not guarantee that exprArity e <= typeArity e You may need to do arity trimming after calling exprArity See Note [Arity trimming] Reason: if we do arity trimming here we have take exprType and that can be expensive if there is a large cast

findRhsArity :: ArityOpts -> RecFlag -> Id -> CoreExpr -> (Bool, SafeArityType) #

cheapArityType :: HasDebugCallStack => CoreExpr -> ArityType #

data ArityOpts #

Constructors

ArityOpts |
Fields ao_ped_bot :: !Bool ao_dicts_cheap :: !Bool

## Eta expansion

exprEtaExpandArity :: HasDebugCallStack => ArityOpts -> CoreExpr -> Maybe SafeArityType #

The Arity returned is the number of value args the expression can be applied to without doing much work

etaExpand :: Arity -> CoreExpr -> CoreExpr #

`etaExpand n e` returns an expression with the same meaning as `e`, but with arity `n`.

Given:

    e' = etaExpand n e

We should have that:

    ty = exprType e = exprType e'

etaExpandAT :: InScopeSet -> SafeArityType -> CoreExpr -> CoreExpr #

## Eta reduction

tryEtaReduce :: UnVarSet -> [Var] -> CoreExpr -> SubDemand -> Maybe CoreExpr #

`tryEtaReduce [x,y,z] e sd` returns `Just e'` if `x y z -> e` is evaluated according to `sd` and can soundly and gainfully be eta-reduced to `e'`. See Note [Eta reduction soundness] and Note [Eta reduction makes sense] when that is the case.

## ArityType

data ArityType #

The analysis lattice of arity analysis. It is isomorphic to

       data ArityType'
         = AEnd Divergence
         | ALam OneShotInfo ArityType'

Which is easier to display the Hasse diagram for:

     ALam OneShotLam at
             |
         AEnd topDiv
             |
     ALam NoOneShotInfo at
             |
         AEnd exnDiv
             |
         AEnd botDiv

where the `at` fields of `ALam` are inductively subject to the same order. That is, `ALam os at1 < ALam os at2` iff `at1 < at2`.

Why the strange Top element? See Note [Combining case branches: optimistic one-shot-ness]

We rely on this lattice structure for fixed-point iteration in `findRhsArity`. For the semantics of `ArityType`, see Note [ArityType].

#### Instances

Instances details

Outputable ArityType # | This is the BNF of the generated output:
    @

    We format
AT [o1,..,on] topDiv`as` o1..on.T`and` AT [o1,..,on] botDiv`as` o1..on.⊥`, respectively. More concretely,` AT [NOI,OS,OS] topDiv`is formatted as` ?11.T`. If the one-shot info is empty, we omit the leading` .@.
Instance details Defined in GHC.Core.Opt.Arity Methods ppr :: ArityType -> SDoc #
Eq ArityType # |
Instance details Defined in GHC.Core.Opt.Arity Methods (==) :: ArityType -> ArityType -> Bool # (/=) :: ArityType -> ArityType -> Bool #

mkBotArityType :: [OneShotInfo] -> ArityType #

arityTypeArity :: SafeArityType -> Arity #

The number of value args for the arity type

idArityType :: Id -> ArityType #

## Bottoming things

exprIsDeadEnd :: CoreExpr -> Bool #

exprBotStrictness_maybe :: CoreExpr -> Maybe (Arity, DmdSig, CprSig) #

arityTypeBotSigs_maybe :: ArityType -> Maybe (Arity, DmdSig, CprSig) #

## typeArity and the state hack

typeArity :: Type -> Arity #

(typeArity ty) says how many arrows GHC can expose in `ty`, after looking through newtypes. More generally, (typeOneShots ty) returns ty's [OneShotInfo], based only on the type itself, using typeOneShot on the argument type to access the "state hack".

typeOneShots :: Type -> [OneShotInfo] #

typeOneShot :: Type -> OneShotInfo #

isOneShotBndr :: Var -> Bool #

Returns whether the lambda associated with the `Id` is certainly applied at most once This one is the "business end", called externally. It works on type variables as well as Ids, returning True Its main purpose is to encapsulate the Horrible State Hack See Note [The state-transformer hack] in GHC.Core.Opt.Arity

isStateHackType :: Type -> Bool #

# Lambdas

zapLamBndrs :: FullArgCount -> [Var] -> [Var] #

## Join points

etaExpandToJoinPoint :: JoinArity -> CoreExpr -> ([CoreBndr], CoreExpr) #

Split an expression into the given number of binders and a body, eta-expanding if necessary. Counts value *and* type binders.

etaExpandToJoinPointRule :: JoinArity -> CoreRule -> CoreRule #

## Coercions and casts

pushCoArg :: CoercionR -> CoreArg -> Maybe (CoreArg, MCoercion) #

pushCoArgs :: CoercionR -> [CoreArg] -> Maybe ([CoreArg], MCoercion) #

pushCoValArg :: CoercionR -> Maybe (MCoercionR, MCoercionR) #

If `pushCoValArg co = Just (co_arg, co_res)`, then

    (\x.body) |> co  =  (\y. let { x = y |> co_arg } in body) |> co_res)

or, equivalently

    (fun |> co) arg  =  (fun (arg |> co_arg)) |> co_res

If the LHS is well-typed, then so is the RHS. In particular, the argument `arg |> co_arg` is guaranteed to have a fixed `RuntimeRep`, in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.

pushCoTyArg :: CoercionR -> Type -> Maybe (Type, MCoercionR) #

pushCoercionIntoLambda :: HasDebugCallStack => InScopeSet -> Var -> CoreExpr -> CoercionR -> Maybe (Var, CoreExpr) #

pushCoDataCon :: DataCon -> [CoreExpr] -> MCoercionR -> Maybe (DataCon, [Type], [CoreExpr]) #

collectBindersPushingCo :: CoreExpr -> ([Var], CoreExpr) #