{-# LANGUAGE CPP #-}
module GHC.Core.Opt.WorkWrap.Utils
( mkWwBodies, mkWWstr, mkWorkerArgs
, DataConPatContext(..), UnboxingDecision(..), splitArgType_maybe, wantToUnbox
, findTypeShape
, isWorkerSmallEnough
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core
import GHC.Core.Utils ( exprType, mkCast, mkDefaultCase, mkSingleAltCase
, dataConRepFSInstPat )
import GHC.Types.Id
import GHC.Types.Id.Info ( JoinArity )
import GHC.Core.DataCon
import GHC.Types.Demand
import GHC.Types.Cpr
import GHC.Core.Make ( mkAbsentErrorApp, mkCoreUbxTup
, mkCoreApp, mkCoreLet )
import GHC.Types.Id.Make ( voidArgId, voidPrimId )
import GHC.Builtin.Types ( tupleDataCon, unboxedUnitTy )
import GHC.Types.Literal ( absentLiteralOf, rubbishLit )
import GHC.Types.Var.Env ( mkInScopeSet )
import GHC.Types.Var.Set ( VarSet )
import GHC.Core.Type
import GHC.Core.Multiplicity
import GHC.Core.Predicate ( isClassPred )
import GHC.Types.RepType ( isVoidTy, typePrimRep )
import GHC.Core.Coercion
import GHC.Core.FamInstEnv
import GHC.Types.Basic ( Boxity(..) )
import GHC.Core.TyCon
import GHC.Core.TyCon.RecWalk
import GHC.Types.Unique.Supply
import GHC.Types.Unique
import GHC.Types.Name ( getOccFS )
import GHC.Data.Maybe
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Data.FastString
import GHC.Data.List.SetOps
type WwResult
= ([Demand],
JoinArity,
Id -> CoreExpr,
CoreExpr -> CoreExpr)
mkWwBodies :: DynFlags
-> FamInstEnvs
-> VarSet
-> Id
-> [Demand]
-> Cpr
-> UniqSM (Maybe WwResult)
mkWwBodies :: DynFlags
-> FamInstEnvs
-> VarSet
-> Id
-> [Demand]
-> Cpr
-> UniqSM (Maybe WwResult)
mkWwBodies DynFlags
dflags FamInstEnvs
fam_envs VarSet
rhs_fvs Id
fun_id [Demand]
demands Cpr
cpr_info
= do { let empty_subst :: TCvSubst
empty_subst = InScopeSet -> TCvSubst
mkEmptyTCvSubst (VarSet -> InScopeSet
mkInScopeSet VarSet
rhs_fvs)
; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
<- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
empty_subst Kind
fun_ty [Demand]
demands
; (Bool
useful1, [Id]
work_args, CoreExpr -> CoreExpr
wrap_fn_str, CoreExpr -> CoreExpr
work_fn_str)
<- DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag [Id]
wrap_args
; (Bool
useful2, CoreExpr -> CoreExpr
wrap_fn_cpr, CoreExpr -> CoreExpr
work_fn_cpr, Kind
cpr_res_ty)
<- Bool
-> FamInstEnvs
-> Kind
-> Cpr
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CprAnal DynFlags
dflags) FamInstEnvs
fam_envs Kind
res_ty Cpr
cpr_info
; let ([Id]
work_lam_args, [Id]
work_call_args) = DynFlags -> [Id] -> Kind -> ([Id], [Id])
mkWorkerArgs DynFlags
dflags [Id]
work_args Kind
cpr_res_ty
worker_args_dmds :: [Demand]
worker_args_dmds = [Id -> Demand
idDemandInfo Id
v | Id
v <- [Id]
work_call_args, Id -> Bool
isId Id
v]
wrapper_body :: Id -> CoreExpr
wrapper_body = CoreExpr -> CoreExpr
wrap_fn_args (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_cpr (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_str (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Id] -> CoreExpr -> CoreExpr
applyToVars [Id]
work_call_args (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id -> CoreExpr
forall b. Id -> Expr b
Var
worker_body :: CoreExpr -> CoreExpr
worker_body = [Id] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
work_lam_args(CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_str (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_cpr (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_args
; if DynFlags -> Int -> [Id] -> Bool
isWorkerSmallEnough DynFlags
dflags ([Demand] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Demand]
demands) [Id]
work_args
Bool -> Bool -> Bool
&& Bool -> Bool
not ([Id] -> Bool
too_many_args_for_join_point [Id]
wrap_args)
Bool -> Bool -> Bool
&& ((Bool
useful1 Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
only_one_void_argument) Bool -> Bool -> Bool
|| Bool
useful2)
then Maybe WwResult -> UniqSM (Maybe WwResult)
forall (m :: * -> *) a. Monad m => a -> m a
return (WwResult -> Maybe WwResult
forall a. a -> Maybe a
Just ([Demand]
worker_args_dmds, [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
work_call_args,
Id -> CoreExpr
wrapper_body, CoreExpr -> CoreExpr
worker_body))
else Maybe WwResult -> UniqSM (Maybe WwResult)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe WwResult
forall a. Maybe a
Nothing
}
where
fun_ty :: Kind
fun_ty = Id -> Kind
idType Id
fun_id
mb_join_arity :: Maybe Int
mb_join_arity = Id -> Maybe Int
isJoinId_maybe Id
fun_id
has_inlineable_prag :: Bool
has_inlineable_prag = Unfolding -> Bool
isStableUnfolding (Id -> Unfolding
realIdUnfolding Id
fun_id)
only_one_void_argument :: Bool
only_one_void_argument
| [Demand
d] <- [Demand]
demands
, Just (Kind
_, Kind
arg_ty1, Kind
_) <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
fun_ty
, Demand -> Bool
isAbsDmd Demand
d Bool -> Bool -> Bool
&& Kind -> Bool
isVoidTy Kind
arg_ty1
= Bool
True
| Bool
otherwise
= Bool
False
too_many_args_for_join_point :: [Id] -> Bool
too_many_args_for_join_point [Id]
wrap_args
| Just Int
join_arity <- Maybe Int
mb_join_arity
, [Id]
wrap_args [Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthExceeds` Int
join_arity
= WARN(True, text "Unable to worker/wrapper join point with arity " <+>
int join_arity <+> text "but" <+>
int (length wrap_args) <+> text "args")
Bool
True
| Bool
otherwise
= Bool
False
isWorkerSmallEnough :: DynFlags -> Int -> [Var] -> Bool
isWorkerSmallEnough :: DynFlags -> Int -> [Id] -> Bool
isWorkerSmallEnough DynFlags
dflags Int
old_n_args [Id]
vars
= (Id -> Bool) -> [Id] -> Int
forall a. (a -> Bool) -> [a] -> Int
count Id -> Bool
isId [Id]
vars Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
old_n_args (DynFlags -> Int
maxWorkerArgs DynFlags
dflags)
mkWorkerArgs :: DynFlags -> [Var]
-> Type
-> ([Var],
[Var])
mkWorkerArgs :: DynFlags -> [Id] -> Kind -> ([Id], [Id])
mkWorkerArgs DynFlags
dflags [Id]
args Kind
res_ty
| (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Id -> Bool
isId [Id]
args Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
needsAValueLambda
= ([Id]
args, [Id]
args)
| Bool
otherwise
= ([Id]
args [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidArgId], [Id]
args [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidPrimId])
where
needsAValueLambda :: Bool
needsAValueLambda =
Bool
lifted
Bool -> Bool -> Bool
|| Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_FunToThunk DynFlags
dflags)
lifted :: Bool
lifted =
case HasDebugCallStack => Kind -> Maybe Bool
Kind -> Maybe Bool
isLiftedType_maybe Kind
res_ty of
Just Bool
lifted -> Bool
lifted
Maybe Bool
Nothing -> Bool
True
mkWWargs :: TCvSubst
-> Type
-> [Demand]
-> UniqSM ([Var],
CoreExpr -> CoreExpr,
CoreExpr -> CoreExpr,
Type)
mkWWargs :: TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
fun_ty [Demand]
demands
| [Demand] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Demand]
demands
= ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst Kind
fun_ty)
| (Demand
dmd:[Demand]
demands') <- [Demand]
demands
, Just (Kind
mult, Kind
arg_ty, Kind
fun_ty') <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
fun_ty
= do { Unique
uniq <- UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let arg_ty' :: Scaled Kind
arg_ty' = HasCallStack => TCvSubst -> Scaled Kind -> Scaled Kind
TCvSubst -> Scaled Kind -> Scaled Kind
substScaledTy TCvSubst
subst (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
mult Kind
arg_ty)
id :: Id
id = Unique -> Scaled Kind -> Demand -> Id
mk_wrap_arg Unique
uniq Scaled Kind
arg_ty' Demand
dmd
; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
<- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
fun_ty' [Demand]
demands'
; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id
id Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
wrap_args,
Id -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Id
id (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_args,
(CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
work_fn_args (Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr Id
id),
Kind
res_ty) }
| Just (Id
tv, Kind
fun_ty') <- Kind -> Maybe (Id, Kind)
splitForAllTyCoVar_maybe Kind
fun_ty
= do { Unique
uniq <- UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let (TCvSubst
subst', Id
tv') = TCvSubst -> Id -> Unique -> (TCvSubst, Id)
cloneTyVarBndr TCvSubst
subst Id
tv Unique
uniq
; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
<- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst' Kind
fun_ty' [Demand]
demands
; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id
tv' Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
wrap_args,
Id -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Id
tv' (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_args,
(CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
work_fn_args (Kind -> CoreExpr
forall b. Kind -> Expr b
mkTyArg (Id -> Kind
mkTyVarTy Id
tv')),
Kind
res_ty) }
| Just (Coercion
co, Kind
rep_ty) <- Kind -> Maybe (Coercion, Kind)
topNormaliseNewType_maybe Kind
fun_ty
= do { ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
<- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
rep_ty [Demand]
demands
; let co' :: Coercion
co' = HasCallStack => TCvSubst -> Coercion -> Coercion
TCvSubst -> Coercion -> Coercion
substCo TCvSubst
subst Coercion
co
; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Id]
wrap_args,
\CoreExpr
e -> CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast (CoreExpr -> CoreExpr
wrap_fn_args CoreExpr
e) (Coercion -> Coercion
mkSymCo Coercion
co'),
\CoreExpr
e -> CoreExpr -> CoreExpr
work_fn_args (CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
e Coercion
co'),
Kind
res_ty) }
| Bool
otherwise
= WARN( True, ppr fun_ty )
([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst Kind
fun_ty)
where
apply_or_bind_then :: (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
k CoreExpr
arg (Lam Id
bndr CoreExpr
body)
= CoreBind -> CoreExpr -> CoreExpr
mkCoreLet (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
bndr CoreExpr
arg) (CoreExpr -> CoreExpr
k CoreExpr
body)
apply_or_bind_then CoreExpr -> CoreExpr
k CoreExpr
arg CoreExpr
fun
= CoreExpr -> CoreExpr
k (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreApp (String -> SDoc
text String
"mkWWargs") CoreExpr
fun CoreExpr
arg
applyToVars :: [Var] -> CoreExpr -> CoreExpr
applyToVars :: [Id] -> CoreExpr -> CoreExpr
applyToVars [Id]
vars CoreExpr
fn = CoreExpr -> [Id] -> CoreExpr
forall b. Expr b -> [Id] -> Expr b
mkVarApps CoreExpr
fn [Id]
vars
mk_wrap_arg :: Unique -> Scaled Type -> Demand -> Id
mk_wrap_arg :: Unique -> Scaled Kind -> Demand -> Id
mk_wrap_arg Unique
uniq (Scaled Kind
w Kind
ty) Demand
dmd
= FastString -> Unique -> Kind -> Kind -> Id
mkSysLocalOrCoVar (String -> FastString
fsLit String
"w") Unique
uniq Kind
w Kind
ty
Id -> Demand -> Id
`setIdDemandInfo` Demand
dmd
data DataConPatContext
= DataConPatContext
{ DataConPatContext -> DataCon
dcpc_dc :: !DataCon
, DataConPatContext -> [Kind]
dcpc_tc_args :: ![Type]
, DataConPatContext -> Coercion
dcpc_co :: !Coercion
}
splitArgType_maybe :: FamInstEnvs -> Type -> Maybe DataConPatContext
splitArgType_maybe :: FamInstEnvs -> Kind -> Maybe DataConPatContext
splitArgType_maybe FamInstEnvs
fam_envs Kind
ty
| let (Coercion
co, Kind
ty1) = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
ty
Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
ty, Kind
ty)
, Just (TyCon
tc, [Kind]
tc_args) <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty1
, Just DataCon
con <- TyCon -> Maybe DataCon
tyConSingleAlgDataCon_maybe TyCon
tc
= DataConPatContext -> Maybe DataConPatContext
forall a. a -> Maybe a
Just DataConPatContext { dcpc_dc :: DataCon
dcpc_dc = DataCon
con
, dcpc_tc_args :: [Kind]
dcpc_tc_args = [Kind]
tc_args
, dcpc_co :: Coercion
dcpc_co = Coercion
co }
splitArgType_maybe FamInstEnvs
_ Kind
_ = Maybe DataConPatContext
forall a. Maybe a
Nothing
splitResultType_maybe :: FamInstEnvs -> ConTag -> Type -> Maybe DataConPatContext
splitResultType_maybe :: FamInstEnvs -> Int -> Kind -> Maybe DataConPatContext
splitResultType_maybe FamInstEnvs
fam_envs Int
con_tag Kind
ty
| let (Coercion
co, Kind
ty1) = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
ty
Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
ty, Kind
ty)
, Just (TyCon
tc, [Kind]
tc_args) <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty1
, TyCon -> Bool
isDataTyCon TyCon
tc
, let cons :: [DataCon]
cons = TyCon -> [DataCon]
tyConDataCons TyCon
tc
, [DataCon]
cons [DataCon] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtLeast` Int
con_tag
, let con :: DataCon
con = [DataCon]
cons [DataCon] -> Int -> DataCon
forall a. Outputable a => [a] -> Int -> a
`getNth` (Int
con_tag Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
fIRST_TAG)
, [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (DataCon -> [Id]
dataConExTyCoVars DataCon
con)
, (Scaled Kind -> Bool) -> [Scaled Kind] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Scaled Kind -> Bool
forall a. Scaled a -> Bool
isLinear (DataCon -> [Kind] -> [Scaled Kind]
dataConInstArgTys DataCon
con [Kind]
tc_args)
= DataConPatContext -> Maybe DataConPatContext
forall a. a -> Maybe a
Just DataConPatContext { dcpc_dc :: DataCon
dcpc_dc = DataCon
con
, dcpc_tc_args :: [Kind]
dcpc_tc_args = [Kind]
tc_args
, dcpc_co :: Coercion
dcpc_co = Coercion
co }
splitResultType_maybe FamInstEnvs
_ Int
_ Kind
_ = Maybe DataConPatContext
forall a. Maybe a
Nothing
isLinear :: Scaled a -> Bool
isLinear :: forall a. Scaled a -> Bool
isLinear (Scaled Kind
w a
_ ) =
case Kind
w of
Kind
One -> Bool
True
Kind
_ -> Bool
False
data UnboxingDecision s
= StopUnboxing
| Unbox !DataConPatContext [s]
wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> UnboxingDecision Demand
wantToUnbox :: FamInstEnvs -> Bool -> Kind -> Demand -> UnboxingDecision Demand
wantToUnbox FamInstEnvs
fam_envs Bool
has_inlineable_prag Kind
ty Demand
dmd =
case FamInstEnvs -> Kind -> Maybe DataConPatContext
splitArgType_maybe FamInstEnvs
fam_envs Kind
ty of
Just dcpc :: DataConPatContext
dcpc@DataConPatContext{ dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc }
| Demand -> Bool
isStrUsedDmd Demand
dmd Bool -> Bool -> Bool
|| HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType Kind
ty
, let arity :: Int
arity = DataCon -> Int
dataConRepArity DataCon
dc
, Just [Demand]
cs <- Demand -> Int -> Maybe [Demand]
split_prod_dmd_arity Demand
dmd Int
arity
, Bool -> Bool
not (Bool
has_inlineable_prag Bool -> Bool -> Bool
&& Kind -> Bool
isClassPred Kind
ty)
, [Demand]
cs [Demand] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
arity
, let cs' :: [Demand]
cs' = DataCon -> [Demand] -> [Demand]
addDataConStrictness DataCon
dc [Demand]
cs
-> DataConPatContext -> [Demand] -> UnboxingDecision Demand
forall s. DataConPatContext -> [s] -> UnboxingDecision s
Unbox DataConPatContext
dcpc [Demand]
cs'
Maybe DataConPatContext
_ -> UnboxingDecision Demand
forall s. UnboxingDecision s
StopUnboxing
where
split_prod_dmd_arity :: Demand -> Int -> Maybe [Demand]
split_prod_dmd_arity Demand
dmd Int
arity
| Demand -> Bool
isSeqDmd Demand
dmd = [Demand] -> Maybe [Demand]
forall a. a -> Maybe a
Just (Int -> Demand -> [Demand]
forall a. Int -> a -> [a]
replicate Int
arity Demand
absDmd)
| Card
_ :* Prod [Demand]
ds <- Demand
dmd = [Demand] -> Maybe [Demand]
forall a. a -> Maybe a
Just [Demand]
ds
| Bool
otherwise = Maybe [Demand]
forall a. Maybe a
Nothing
mkWWstr :: DynFlags
-> FamInstEnvs
-> Bool
-> [Var]
-> UniqSM (Bool,
[Var],
CoreExpr -> CoreExpr,
CoreExpr -> CoreExpr)
mkWWstr :: DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag [Id]
args
= [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go [Id]
args
where
go_one :: Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go_one Id
arg = DynFlags
-> FamInstEnvs
-> Bool
-> Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag Id
arg
go :: [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go [] = (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
go (Id
arg : [Id]
args) = do { (Bool
useful1, [Id]
args1, CoreExpr -> CoreExpr
wrap_fn1, CoreExpr -> CoreExpr
work_fn1) <- Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go_one Id
arg
; (Bool
useful2, [Id]
args2, CoreExpr -> CoreExpr
wrap_fn2, CoreExpr -> CoreExpr
work_fn2) <- [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go [Id]
args
; (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
useful1 Bool -> Bool -> Bool
|| Bool
useful2
, [Id]
args1 [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
args2
, CoreExpr -> CoreExpr
wrap_fn1 (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn2
, CoreExpr -> CoreExpr
work_fn1 (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn2) }
mkWWstr_one :: DynFlags -> FamInstEnvs
-> Bool
-> Var
-> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one :: DynFlags
-> FamInstEnvs
-> Bool
-> Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag Id
arg
| Id -> Bool
isTyVar Id
arg
= (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [Id
arg], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
| Demand -> Bool
isAbsDmd Demand
dmd
, Just CoreExpr -> CoreExpr
work_fn <- DynFlags
-> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let DynFlags
dflags FamInstEnvs
fam_envs Id
arg Demand
dmd
= (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, [], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
work_fn)
| Unbox DataConPatContext
dcpc [Demand]
cs <- FamInstEnvs -> Bool -> Kind -> Demand -> UnboxingDecision Demand
wantToUnbox FamInstEnvs
fam_envs Bool
has_inlineable_prag Kind
arg_ty Demand
dmd
= DynFlags
-> FamInstEnvs
-> Id
-> [Demand]
-> DataConPatContext
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one DynFlags
dflags FamInstEnvs
fam_envs Id
arg [Demand]
cs DataConPatContext
dcpc
| Bool
otherwise
= (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [Id
arg], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
where
arg_ty :: Kind
arg_ty = Id -> Kind
idType Id
arg
dmd :: Demand
dmd = Id -> Demand
idDemandInfo Id
arg
unbox_one :: DynFlags -> FamInstEnvs -> Var
-> [Demand]
-> DataConPatContext
-> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one :: DynFlags
-> FamInstEnvs
-> Id
-> [Demand]
-> DataConPatContext
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one DynFlags
dflags FamInstEnvs
fam_envs Id
arg [Demand]
cs
DataConPatContext { dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Kind]
dcpc_tc_args = [Kind]
tc_args
, dcpc_co :: DataConPatContext -> Coercion
dcpc_co = Coercion
co }
= do { (Unique
case_bndr_uniq:[Unique]
pat_bndrs_uniqs) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let ex_name_fss :: [FastString]
ex_name_fss = (Id -> FastString) -> [Id] -> [FastString]
forall a b. (a -> b) -> [a] -> [b]
map Id -> FastString
forall a. NamedThing a => a -> FastString
getOccFS ([Id] -> [FastString]) -> [Id] -> [FastString]
forall a b. (a -> b) -> a -> b
$ DataCon -> [Id]
dataConExTyCoVars DataCon
dc
([Id]
ex_tvs', [Id]
arg_ids) =
[FastString]
-> [Unique] -> Kind -> DataCon -> [Kind] -> ([Id], [Id])
dataConRepFSInstPat ([FastString]
ex_name_fss [FastString] -> [FastString] -> [FastString]
forall a. [a] -> [a] -> [a]
++ FastString -> [FastString]
forall a. a -> [a]
repeat FastString
ww_prefix) [Unique]
pat_bndrs_uniqs (Id -> Kind
idMult Id
arg) DataCon
dc [Kind]
tc_args
arg_ids' :: [Id]
arg_ids' = String -> (Id -> Demand -> Id) -> [Id] -> [Demand] -> [Id]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"unbox_one" Id -> Demand -> Id
setIdDemandInfo [Id]
arg_ids [Demand]
cs
unbox_fn :: CoreExpr -> CoreExpr
unbox_fn = CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
arg) Coercion
co (Id -> Kind
idMult Id
arg) Unique
case_bndr_uniq
DataCon
dc ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids')
arg_no_unf :: Id
arg_no_unf = Id -> Id
zapStableUnfolding Id
arg
rebox_fn :: CoreExpr -> CoreExpr
rebox_fn = CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg_no_unf CoreExpr
con_app)
con_app :: CoreExpr
con_app = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids') CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
; (Bool
_, [Id]
worker_args, CoreExpr -> CoreExpr
wrap_fn, CoreExpr -> CoreExpr
work_fn) <- DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
False ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids')
; (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, [Id]
worker_args, CoreExpr -> CoreExpr
unbox_fn (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn, CoreExpr -> CoreExpr
work_fn (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
rebox_fn) }
nop_fn :: CoreExpr -> CoreExpr
nop_fn :: CoreExpr -> CoreExpr
nop_fn CoreExpr
body = CoreExpr
body
addDataConStrictness :: DataCon -> [Demand] -> [Demand]
addDataConStrictness :: DataCon -> [Demand] -> [Demand]
addDataConStrictness DataCon
con [Demand]
ds
| Maybe Id
Nothing <- DataCon -> Maybe Id
dataConWrapId_maybe DataCon
con
= [Demand]
ds
addDataConStrictness DataCon
con [Demand]
ds
= String
-> (Demand -> StrictnessMark -> Demand)
-> [Demand]
-> [StrictnessMark]
-> [Demand]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"addDataConStrictness" Demand -> StrictnessMark -> Demand
add [Demand]
ds [StrictnessMark]
strs
where
strs :: [StrictnessMark]
strs = DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
con
add :: Demand -> StrictnessMark -> Demand
add Demand
dmd StrictnessMark
str | StrictnessMark -> Bool
isMarkedStrict StrictnessMark
str = Demand -> Demand
strictifyDmd Demand
dmd
| Bool
otherwise = Demand
dmd
findTypeShape :: FamInstEnvs -> Type -> TypeShape
findTypeShape :: FamInstEnvs -> Kind -> TypeShape
findTypeShape FamInstEnvs
fam_envs Kind
ty
= RecTcChecker -> Kind -> TypeShape
go (Int -> RecTcChecker -> RecTcChecker
setRecTcMaxBound Int
2 RecTcChecker
initRecTc) Kind
ty
where
go :: RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty
| Just (Kind
_, Kind
_, Kind
res) <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
ty
= TypeShape -> TypeShape
TsFun (RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
res)
| Just (TyCon
tc, [Kind]
tc_args) <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty
= RecTcChecker -> TyCon -> [Kind] -> TypeShape
go_tc RecTcChecker
rec_tc TyCon
tc [Kind]
tc_args
| Just (Id
_, Kind
ty') <- Kind -> Maybe (Id, Kind)
splitForAllTyCoVar_maybe Kind
ty
= RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty'
| Bool
otherwise
= TypeShape
TsUnk
go_tc :: RecTcChecker -> TyCon -> [Kind] -> TypeShape
go_tc RecTcChecker
rec_tc TyCon
tc [Kind]
tc_args
| Just (Coercion
_, Kind
rhs, MCoercion
_) <- FamInstEnvs -> TyCon -> [Kind] -> Maybe (Coercion, Kind, MCoercion)
topReduceTyFamApp_maybe FamInstEnvs
fam_envs TyCon
tc [Kind]
tc_args
= RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
rhs
| Just DataCon
con <- TyCon -> Maybe DataCon
tyConSingleAlgDataCon_maybe TyCon
tc
, Just RecTcChecker
rec_tc <- if TyCon -> Bool
isTupleTyCon TyCon
tc
then RecTcChecker -> Maybe RecTcChecker
forall a. a -> Maybe a
Just RecTcChecker
rec_tc
else RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_tc TyCon
tc
= [TypeShape] -> TypeShape
TsProd ((Kind -> TypeShape) -> [Kind] -> [TypeShape]
forall a b. (a -> b) -> [a] -> [b]
map (RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc) (DataCon -> [Kind] -> [Kind]
dubiousDataConInstArgTys DataCon
con [Kind]
tc_args))
| Just (Kind
ty', Coercion
_) <- TyCon -> [Kind] -> Maybe (Kind, Coercion)
instNewTyCon_maybe TyCon
tc [Kind]
tc_args
, Just RecTcChecker
rec_tc <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_tc TyCon
tc
= RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty'
| Bool
otherwise
= TypeShape
TsUnk
dubiousDataConInstArgTys :: DataCon -> [Type] -> [Type]
dubiousDataConInstArgTys :: DataCon -> [Kind] -> [Kind]
dubiousDataConInstArgTys DataCon
dc [Kind]
tc_args = [Kind]
arg_tys
where
univ_tvs :: [Id]
univ_tvs = DataCon -> [Id]
dataConUnivTyVars DataCon
dc
ex_tvs :: [Id]
ex_tvs = DataCon -> [Id]
dataConExTyCoVars DataCon
dc
subst :: TCvSubst
subst = TCvSubst -> [Id] -> TCvSubst
extendTCvInScopeList ([Id] -> [Kind] -> TCvSubst
HasDebugCallStack => [Id] -> [Kind] -> TCvSubst
zipTvSubst [Id]
univ_tvs [Kind]
tc_args) [Id]
ex_tvs
arg_tys :: [Kind]
arg_tys = (Scaled Kind -> Kind) -> [Scaled Kind] -> [Kind]
forall a b. (a -> b) -> [a] -> [b]
map (HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst (Kind -> Kind) -> (Scaled Kind -> Kind) -> Scaled Kind -> Kind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing) (DataCon -> [Scaled Kind]
dataConRepArgTys DataCon
dc)
mkWWcpr :: Bool
-> FamInstEnvs
-> Type
-> Cpr
-> UniqSM (Bool,
CoreExpr -> CoreExpr,
CoreExpr -> CoreExpr,
Type)
mkWWcpr :: Bool
-> FamInstEnvs
-> Kind
-> Cpr
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr Bool
opt_CprAnal FamInstEnvs
fam_envs Kind
body_ty Cpr
cpr
| Bool -> Bool
not Bool
opt_CprAnal = (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)
| Bool
otherwise
= case Cpr -> Maybe (Int, [Cpr])
asConCpr Cpr
cpr of
Maybe (Int, [Cpr])
Nothing -> (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)
Just (Int
con_tag, [Cpr]
_cprs)
| Just DataConPatContext
dcpc <- FamInstEnvs -> Int -> Kind -> Maybe DataConPatContext
splitResultType_maybe FamInstEnvs
fam_envs Int
con_tag Kind
body_ty
-> DataConPatContext
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr_help DataConPatContext
dcpc
| Bool
otherwise
-> WARN( True, text "mkWWcpr: non-algebraic or open body type" <+> ppr body_ty )
(Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)
mkWWcpr_help :: DataConPatContext
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Type)
mkWWcpr_help :: DataConPatContext
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr_help (DataConPatContext { dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Kind]
dcpc_tc_args = [Kind]
tc_args
, dcpc_co :: DataConPatContext -> Coercion
dcpc_co = Coercion
co })
| [Scaled Kind
arg_ty] <- DataCon -> [Kind] -> [Scaled Kind]
dataConInstArgTys DataCon
dc [Kind]
tc_args
, [StrictnessMark
str_mark] <- DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
dc
, HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType (Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing Scaled Kind
arg_ty)
, Scaled Kind -> Bool
forall a. Scaled a -> Bool
isLinear Scaled Kind
arg_ty
= do { (Unique
work_uniq : Unique
arg_uniq : [Unique]
_) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let arg_id :: Id
arg_id = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
arg_uniq StrictnessMark
str_mark Scaled Kind
arg_ty
con_app :: CoreExpr
con_app = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args [Id
arg_id] CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
; (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
True
, \ CoreExpr
wkr_call -> CoreExpr -> Id -> CoreExpr -> CoreExpr
mkDefaultCase CoreExpr
wkr_call Id
arg_id CoreExpr
con_app
, \ CoreExpr
body -> CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
body Coercion
co Kind
One Unique
work_uniq DataCon
dc [Id
arg_id] (Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr Id
arg_id)
, Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing Scaled Kind
arg_ty ) }
| Bool
otherwise
= do { (Unique
work_uniq : Unique
wild_uniq : [Unique]
pat_bndrs_uniqs) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let case_mult :: Kind
case_mult = Kind
One
([Id]
_exs, [Id]
arg_ids) =
[FastString]
-> [Unique] -> Kind -> DataCon -> [Kind] -> ([Id], [Id])
dataConRepFSInstPat (FastString -> [FastString]
forall a. a -> [a]
repeat FastString
ww_prefix) [Unique]
pat_bndrs_uniqs Kind
case_mult DataCon
dc [Kind]
tc_args
wrap_wild :: Id
wrap_wild = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
wild_uniq StrictnessMark
MarkedStrict (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
case_mult Kind
ubx_tup_ty)
ubx_tup_ty :: Kind
ubx_tup_ty = CoreExpr -> Kind
exprType CoreExpr
ubx_tup_app
ubx_tup_app :: CoreExpr
ubx_tup_app = [Kind] -> [CoreExpr] -> CoreExpr
mkCoreUbxTup ((Id -> Kind) -> [Id] -> [Kind]
forall a b. (a -> b) -> [a] -> [b]
map Id -> Kind
idType [Id]
arg_ids) ((Id -> CoreExpr) -> [Id] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr [Id]
arg_ids)
con_app :: CoreExpr
con_app = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args [Id]
arg_ids CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
tup_con :: DataCon
tup_con = Boxity -> Int -> DataCon
tupleDataCon Boxity
Unboxed ([Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
arg_ids)
; MASSERT( null _exs )
; (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True
, \ CoreExpr
wkr_call -> CoreExpr -> Id -> AltCon -> [Id] -> CoreExpr -> CoreExpr
mkSingleAltCase CoreExpr
wkr_call Id
wrap_wild
(DataCon -> AltCon
DataAlt DataCon
tup_con) [Id]
arg_ids CoreExpr
con_app
, \ CoreExpr
body -> CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
body Coercion
co Kind
case_mult Unique
work_uniq DataCon
dc [Id]
arg_ids CoreExpr
ubx_tup_app
, Kind
ubx_tup_ty ) }
mkUnpackCase :: CoreExpr -> Coercion -> Mult -> Unique -> DataCon -> [Id] -> CoreExpr -> CoreExpr
mkUnpackCase :: CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase (Tick CoreTickish
tickish CoreExpr
e) Coercion
co Kind
mult Unique
uniq DataCon
con [Id]
args CoreExpr
body
= CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
tickish (CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
e Coercion
co Kind
mult Unique
uniq DataCon
con [Id]
args CoreExpr
body)
mkUnpackCase CoreExpr
scrut Coercion
co Kind
mult Unique
uniq DataCon
boxing_con [Id]
unpk_args CoreExpr
body
= CoreExpr -> Id -> AltCon -> [Id] -> CoreExpr -> CoreExpr
mkSingleAltCase CoreExpr
casted_scrut Id
bndr
(DataCon -> AltCon
DataAlt DataCon
boxing_con) [Id]
unpk_args CoreExpr
body
where
casted_scrut :: CoreExpr
casted_scrut = CoreExpr
scrut CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion
co
bndr :: Id
bndr = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
uniq StrictnessMark
MarkedStrict (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
mult (CoreExpr -> Kind
exprType CoreExpr
casted_scrut))
mk_absent_let :: DynFlags -> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let :: DynFlags
-> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let DynFlags
dflags FamInstEnvs
fam_envs Id
arg Demand
dmd
| Bool -> Bool
not (HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType Kind
arg_ty)
= (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
lifted_arg CoreExpr
lifted_rhs))
| [PrimRep
UnliftedRep] <- HasDebugCallStack => Kind -> [PrimRep]
Kind -> [PrimRep]
typePrimRep Kind
arg_ty
= (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg CoreExpr
unlifted_rhs))
| Just TyCon
tc <- Kind -> Maybe TyCon
tyConAppTyCon_maybe Kind
nty
, Just Literal
lit <- TyCon -> Maybe Literal
absentLiteralOf TyCon
tc
= (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit Literal
lit CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co)))
| Kind
nty Kind -> Kind -> Bool
`eqType` Kind
unboxedUnitTy
= (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
voidPrimId CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co)))
| Bool
otherwise
= WARN( True, text "No absent value for" <+> ppr arg_ty )
Maybe (CoreExpr -> CoreExpr)
forall a. Maybe a
Nothing
where
lifted_arg :: Id
lifted_arg = Id
arg Id -> StrictSig -> Id
`setIdStrictness` StrictSig
botSig Id -> CprSig -> Id
`setIdCprInfo` Int -> Cpr -> CprSig
mkCprSig Int
0 Cpr
botCpr
lifted_rhs :: CoreExpr
lifted_rhs | Demand -> Bool
isStrictDmd Demand
dmd = CoreExpr -> [Kind] -> CoreExpr
forall b. Expr b -> [Kind] -> Expr b
mkTyApps (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (Bool -> Literal
rubbishLit Bool
True)) [Kind
arg_ty]
| Bool
otherwise = Kind -> String -> CoreExpr
mkAbsentErrorApp Kind
arg_ty String
msg
unlifted_rhs :: CoreExpr
unlifted_rhs = CoreExpr -> [Kind] -> CoreExpr
forall b. Expr b -> [Kind] -> Expr b
mkTyApps (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (Bool -> Literal
rubbishLit Bool
False)) [Kind
arg_ty]
arg_ty :: Kind
arg_ty = Id -> Kind
idType Id
arg
(Coercion
co, Kind
nty) = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
arg_ty
Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
arg_ty, Kind
arg_ty)
msg :: String
msg = DynFlags -> SDoc -> String
showSDoc (DynFlags -> GeneralFlag -> DynFlags
gopt_set DynFlags
dflags GeneralFlag
Opt_SuppressUniques)
([SDoc] -> SDoc
vcat
[ String -> SDoc
text String
"Arg:" SDoc -> SDoc -> SDoc
<+> Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
arg
, String -> SDoc
text String
"Type:" SDoc -> SDoc -> SDoc
<+> Kind -> SDoc
forall a. Outputable a => a -> SDoc
ppr Kind
arg_ty
, SDoc
file_msg
])
file_msg :: SDoc
file_msg = case DynFlags -> Maybe String
outputFile DynFlags
dflags of
Maybe String
Nothing -> SDoc
empty
Just String
f -> String -> SDoc
text String
"In output file " SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (String -> SDoc
text String
f)
ww_prefix :: FastString
ww_prefix :: FastString
ww_prefix = String -> FastString
fsLit String
"ww"
mk_ww_local :: Unique -> StrictnessMark -> Scaled Type -> Id
mk_ww_local :: Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
uniq StrictnessMark
str (Scaled Kind
w Kind
ty)
= StrictnessMark -> Id -> Id
setCaseBndrEvald StrictnessMark
str (Id -> Id) -> Id -> Id
forall a b. (a -> b) -> a -> b
$
FastString -> Unique -> Kind -> Kind -> Id
mkSysLocalOrCoVar FastString
ww_prefix Unique
uniq Kind
w Kind
ty