Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Synopsis
- data WwOpts = MkWwOpts {
- wo_fam_envs :: !FamInstEnvs
- wo_simple_opts :: !SimpleOpts
- wo_cpr_anal :: !Bool
- wo_module :: !Module
- wo_unlift_strict :: !Bool
- initWwOpts :: Module -> DynFlags -> FamInstEnvs -> WwOpts
- mkWwBodies :: WwOpts -> Id -> [Var] -> Type -> [Demand] -> Cpr -> UniqSM (Maybe WwResult)
- mkWWstr :: WwOpts -> [Var] -> [StrictnessMark] -> UniqSM (Bool, [(Var, StrictnessMark)], CoreExpr -> CoreExpr, [CoreExpr])
- mkWWstr_one :: WwOpts -> Var -> StrictnessMark -> UniqSM (Bool, [(Var, StrictnessMark)], CoreExpr -> CoreExpr, CoreExpr)
- needsVoidWorkerArg :: Id -> [Var] -> [Var] -> Bool
- addVoidWorkerArg :: [Var] -> [StrictnessMark] -> ([Var], [Var], [StrictnessMark])
- data DataConPatContext = DataConPatContext {}
- data UnboxingDecision s
- = StopUnboxing
- | DropAbsent
- | Unbox !DataConPatContext [s]
- | Unlift
- wantToUnboxArg :: Bool -> FamInstEnvs -> Type -> Demand -> UnboxingDecision Demand
- findTypeShape :: FamInstEnvs -> Type -> TypeShape
- data IsRecDataConResult
- isRecDataCon :: FamInstEnvs -> IntWithInf -> DataCon -> IsRecDataConResult
- mkAbsentFiller :: WwOpts -> Id -> StrictnessMark -> Maybe CoreExpr
- isWorkerSmallEnough :: Int -> Int -> [Var] -> Bool
- dubiousDataConInstArgTys :: DataCon -> [Type] -> [Type]
- isGoodWorker :: Bool -> Bool
- badWorker :: Bool
- goodWorker :: Bool
Documentation
MkWwOpts | |
|
initWwOpts :: Module -> DynFlags -> FamInstEnvs -> WwOpts Source #
:: WwOpts | |
-> Id | The original function |
-> [Var] | Manifest args of original function |
-> Type | Result type of the original function, after being stripped of args |
-> [Demand] | Strictness of original function |
-> Cpr | Info about function result |
-> UniqSM (Maybe WwResult) |
Given a function definition
data T = MkT Int Bool Char f :: (a, b) -> Int -> T f = \x y -> E
mkWwBodies _
returnsf
['x::(a,b)','y::Int'] '(a,b)' ['1P(L,L)', '1P(L)'] '1'
- 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.
mkWWstr :: WwOpts -> [Var] -> [StrictnessMark] -> UniqSM (Bool, [(Var, StrictnessMark)], CoreExpr -> CoreExpr, [CoreExpr]) Source #
mkWWstr_one :: WwOpts -> Var -> StrictnessMark -> UniqSM (Bool, [(Var, StrictnessMark)], CoreExpr -> CoreExpr, CoreExpr) Source #
needsVoidWorkerArg :: Id -> [Var] -> [Var] -> Bool Source #
Whether the worker needs an additional `Void#` arg as per Note [Protecting the last value argument] or Note [Preserving float barriers].
addVoidWorkerArg :: [Var] -> [StrictnessMark] -> ([Var], [Var], [StrictnessMark]) Source #
Inserts a `Void#` arg before the first argument.
Why as the first argument? See Note [SpecConst needs to add void args first] in SpecConstr.
data DataConPatContext Source #
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
data UnboxingDecision s Source #
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
).
StopUnboxing | We ran out of strictness info. Leave untouched. |
DropAbsent | The argument/field was absent. Drop it. |
Unbox !DataConPatContext [s] | The argument is used strictly or the returned product was constructed, so
unbox it.
The |
Unlift | The argument can't be unboxed, but we want it to be passed evaluated to the worker. |
:: Bool | Consider unlifting |
-> FamInstEnvs | |
-> Type | Type of the argument |
-> Demand | How the arg was used |
-> UnboxingDecision Demand |
Unwraps the Boxity
decision encoded in the given SubDemand
and returns
a DataConPatContext
as well the nested demands on fields of the DataCon
to unbox.
findTypeShape :: FamInstEnvs -> Type -> TypeShape Source #
data IsRecDataConResult Source #
Returned by isRecDataCon
.
See also Note [Detecting recursive data constructors].
DefinitelyRecursive | The algorithm detected a loop |
NonRecursiveOrUnsure | The algorithm detected no loop, went out of fuel or hit an .hs-boot file |
Instances
Show IsRecDataConResult Source # | |
Defined in GHC.Core.Opt.WorkWrap.Utils showsPrec :: Int -> IsRecDataConResult -> ShowS # show :: IsRecDataConResult -> String # showList :: [IsRecDataConResult] -> ShowS # | |
Outputable IsRecDataConResult Source # | |
Defined in GHC.Core.Opt.WorkWrap.Utils ppr :: IsRecDataConResult -> SDoc # | |
Eq IsRecDataConResult Source # | |
Defined in GHC.Core.Opt.WorkWrap.Utils (==) :: IsRecDataConResult -> IsRecDataConResult -> Bool # (/=) :: IsRecDataConResult -> IsRecDataConResult -> Bool # |
isRecDataCon :: FamInstEnvs -> IntWithInf -> DataCon -> IsRecDataConResult Source #
isRecDataCon _ fuel dc
, where tc = dataConTyCon dc
returns
DefinitelyRecursive
if the analysis found thattc
is reachable through one ofdc
'sarg_tys
.NonRecursiveOrUnsure
if the analysis found thattc
is not reachable through one ofdc
's fields (so surely non-recursive).NonRecursiveOrUnsure
whenfuel /= Infinity
andfuel
expansions of nested data TyCons were not enough to prove non-recursivenss, nor arrive at an occurrence oftc
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 =
and there are no boot files involved, then the result
is never Infinity
Nothing
and the analysis is a depth-first search. If fuel =
, then the analysis behaves like a depth-limited DFS and returns Int
fNothing
if the search was inconclusive.
See Note [Detecting recursive data constructors] for which recursive DataCons we want to flag.
mkAbsentFiller :: WwOpts -> Id -> StrictnessMark -> Maybe CoreExpr Source #
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.
dubiousDataConInstArgTys :: DataCon -> [Type] -> [Type] Source #
Exactly dataConInstArgTys
, but lacks the (ASSERT'ed) precondition that
the DataCon
may not have existentials. The lack of cloning the existentials
compared to dataConInstExAndArgVars
makes this function "dubious";
only use it where type variables aren't substituted for!
isGoodWorker :: Bool -> Bool Source #
goodWorker :: Bool Source #