HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleghc-9.10.3GHC2021

GHC.Core.Opt.WorkWrap.Utils

  • 4 types
  • 12 values
  • Packageghc-9.10.3
  • Exports16
  • LanguageGHC2021
  • LicenceBSD-3-Clause
  • SourceUtils.hs
valuemkWwBodies
  1. :: WwOpts
  2. -> Id

    The original function

  3. -> [Var]

    Manifest args of original function

  4. -> Type

    Result type of the original function, after being stripped of args

  5. -> [Demand]

    Strictness of original function

  6. -> Cpr

    Info about function result

  7. -> UniqSM (Maybe WwResult)
#

Given a function definition

data T = MkT Int Bool Char
f :: (a, b) -> Int -> T
f = \x y -> E

mkWwBodies _ f ['x::(a,b)','y::Int'] '(a,b)' ['1P(L,L)', '1P(L)'] '1' returns

  • The wrapper body context for the call to the worker function, lacking only the Id for the worker function:

W[_] :: Id -> CoreExpr
W[work_fn] = \x y ->          -- args of the wrapper    (cloned_arg_vars)
  case x of (a, b) ->         -- unbox wrapper args     (wrap_fn_str)
  case y of I# n ->           --
  case <work_fn> a b n of     -- call to the worker fun (call_work)
  (# i, b, c #) -> MkT i b c  -- rebox result           (wrap_fn_cpr)
  • The worker body context that wraps around its hole reboxing defns for x and y, as well as returning CPR transit variables of the unboxed MkT result in an unboxed tuple:

w[_] :: CoreExpr -> CoreExpr
w[fn_rhs] = \a b n ->              -- args of the worker       (work_lam_args)
  let { y = I# n; x = (a, b) } in  -- reboxing wrapper args    (work_fn_str)
  case <fn_rhs> x y of             -- call to the original RHS (call_rhs)
  MkT i b c -> (# i, b, c #)       -- return CPR transit vars  (work_fn_cpr)

NB: The wrap_rhs hole is to be filled with the original wrapper RHS x y -> E. This is so that we can also use w to transform stable unfoldings, the lambda args of which may be different than x and y.

  • Id details for the worker function like demands on arguments and its join arity.

All without looking at E (except for beta reduction, see Note [Join points and beta-redexes]), which allows us to apply the same split to function body and its unfolding(s) alike.

valueneedsVoidWorkerArg :: Id -> [Var] -> [Var] -> Bool
#

Whether the worker needs an additional Void# arg as per Note [Protecting the last value argument] or Note [Preserving float barriers].

datadata DataConPatContext s
#

The information needed to build a pattern for a DataCon to be unboxed. The pattern can be generated from dcpc_dc and dcpc_tc_args via dataConRepInstPat. The coercion dcpc_co is for newtype wrappers.

If we get DataConPatContext dc tys co for some type ty and dataConRepInstPat ... dc tys = (exs, flds), then

  • dc exs flds :: T tys@

  • co :: T tys ~ ty

s will be Demand or Cpr.

datadata UnboxingDecision unboxing_info
#

Describes the outer shape of an argument to be unboxed or left as-is Depending on how s is instantiated (e.g., Demand or Cpr).

Constructors

  • DontUnbox

    We ran out of strictness info. Leave untouched.

  • DoUnbox !unboxing_info

    The argument is used strictly or the returned product was constructed, so unbox it.

  • DropAbsent

    The argument/field was absent. Drop it.

Instances1Outputable
datadata IsRecDataConResult
#

Returned by isRecDataCon. See also Note [Detecting recursive data constructors].

Constructors

Instances3Eq, Show, Outputable

isRecDataCon _ fuel dc, where tc = dataConTyCon dc returns

  • DefinitelyRecursive if the analysis found that tc is reachable through one of dc's arg_tys.

  • NonRecursiveOrUnsure if the analysis found that tc is not reachable through one of dc's fields (so surely non-recursive).

  • NonRecursiveOrUnsure when fuel /= Infinity and fuel expansions of nested data TyCons were not enough to prove non-recursiveness, nor arrive at an occurrence of tc thus proving recursiveness. (So not sure if non-recursive.)

  • NonRecursiveOrUnsure when we hit an abstract TyCon (one without visible DataCons), such as those imported from .hs-boot files. Similarly for stuck type and data families.

If fuel = Infinity and there are no boot files involved, then the result is never Nothing and the analysis is a depth-first search. If fuel = Int f, then the analysis behaves like a depth-limited DFS and returns Nothing if the search was inconclusive.

See Note [Detecting recursive data constructors] for which recursive DataCons we want to flag.

Tries to find a suitable absent filler to bind the given absent identifier to. See Note [Absent fillers].

If mkAbsentFiller _ id == Just e, then e is an absent filler with the same type as id. Otherwise, no suitable filler could be found.

Exactly dataConInstArgTys, but lacks the (ASSERT'ed) precondition that the DataCon may not have existentials. The lack of cloning the existentials this function "dubious"; only use it where type variables aren't substituted for! Why may the data con bind existentials? See Note [Which types are unboxed?]