{-# LANGUAGE CPP #-}
module GHC.Core.Opt.Arity
(
manifestArity, joinRhsArity, exprArity
, findRhsArity, cheapArityType
, ArityOpts(..)
, exprEtaExpandArity, etaExpand, etaExpandAT
, tryEtaReduce
, ArityType, mkBotArityType
, arityTypeArity, idArityType
, exprIsDeadEnd, exprBotStrictness_maybe, arityTypeBotSigs_maybe
, typeArity, typeOneShots, typeOneShot
, isOneShotBndr
, isStateHackType
, zapLamBndrs
, etaExpandToJoinPoint, etaExpandToJoinPointRule
, pushCoArg, pushCoArgs, pushCoValArg, pushCoTyArg
, pushCoercionIntoLambda, pushCoDataCon, collectBindersPushingCo
)
where
import GHC.Prelude
import GHC.Core
import GHC.Core.FVs
import GHC.Core.Utils
import GHC.Core.DataCon
import GHC.Core.TyCon ( tyConArity )
import GHC.Core.TyCon.RecWalk ( initRecTc, checkRecTc )
import GHC.Core.Predicate ( isDictTy, isEvVar, isCallStackPredTy, isCallStackTy )
import GHC.Core.Multiplicity
import GHC.Core.Subst as Core
import GHC.Core.Type as Type
import GHC.Core.Coercion as Type
import GHC.Core.TyCo.Compare( eqType )
import GHC.Types.Demand
import GHC.Types.Cpr( CprSig, mkCprSig, botCpr )
import GHC.Types.Id
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Basic
import GHC.Types.Tickish
import GHC.Builtin.Types.Prim
import GHC.Builtin.Uniques
import GHC.Data.FastString
import GHC.Data.Graph.UnVar
import GHC.Data.Pair
import GHC.Utils.GlobalVars( unsafeHasNoStateHack )
import GHC.Utils.Constants (debugIsOn)
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Misc
import Data.Maybe( isJust )
manifestArity :: CoreExpr -> Arity
manifestArity :: CoreExpr -> Int
manifestArity (Lam TyVar
v CoreExpr
e) | TyVar -> Bool
isId TyVar
v = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ CoreExpr -> Int
manifestArity CoreExpr
e
| Bool
otherwise = CoreExpr -> Int
manifestArity CoreExpr
e
manifestArity (Tick CoreTickish
t CoreExpr
e) | Bool -> Bool
not (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t) = CoreExpr -> Int
manifestArity CoreExpr
e
manifestArity (Cast CoreExpr
e Coercion
_) = CoreExpr -> Int
manifestArity CoreExpr
e
manifestArity CoreExpr
_ = Int
0
joinRhsArity :: CoreExpr -> JoinArity
joinRhsArity :: CoreExpr -> Int
joinRhsArity (Lam TyVar
_ CoreExpr
e) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ CoreExpr -> Int
joinRhsArity CoreExpr
e
joinRhsArity CoreExpr
_ = Int
0
exprBotStrictness_maybe :: CoreExpr -> Maybe (Arity, DmdSig, CprSig)
exprBotStrictness_maybe :: CoreExpr -> Maybe (Int, DmdSig, CprSig)
exprBotStrictness_maybe CoreExpr
e = SafeArityType -> Maybe (Int, DmdSig, CprSig)
arityTypeBotSigs_maybe (HasDebugCallStack => CoreExpr -> SafeArityType
CoreExpr -> SafeArityType
cheapArityType CoreExpr
e)
arityTypeBotSigs_maybe :: ArityType -> Maybe (Arity, DmdSig, CprSig)
arityTypeBotSigs_maybe :: SafeArityType -> Maybe (Int, DmdSig, CprSig)
arityTypeBotSigs_maybe (AT [ATLamInfo]
lams Divergence
div)
| Divergence -> Bool
isDeadEndDiv Divergence
div = (Int, DmdSig, CprSig) -> Maybe (Int, DmdSig, CprSig)
forall a. a -> Maybe a
Just ( Int
arity
, Int -> Divergence -> DmdSig
mkVanillaDmdSig Int
arity Divergence
botDiv
, Int -> Cpr -> CprSig
mkCprSig Int
arity Cpr
botCpr)
| Bool
otherwise = Maybe (Int, DmdSig, CprSig)
forall a. Maybe a
Nothing
where
arity :: Int
arity = [ATLamInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ATLamInfo]
lams
typeArity :: Type -> Arity
typeArity :: Type -> Int
typeArity = [OneShotInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([OneShotInfo] -> Int) -> (Type -> [OneShotInfo]) -> Type -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> [OneShotInfo]
typeOneShots
typeOneShots :: Type -> [OneShotInfo]
typeOneShots :: Type -> [OneShotInfo]
typeOneShots Type
ty
= RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
initRecTc Type
ty
where
go :: RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
ty
| Just (TyVar
tcv, Type
ty') <- Type -> Maybe (TyVar, Type)
splitForAllTyCoVar_maybe Type
ty
= if TyVar -> Bool
isCoVar TyVar
tcv
then TyVar -> OneShotInfo
idOneShotInfo TyVar
tcv OneShotInfo -> [OneShotInfo] -> [OneShotInfo]
forall a. a -> [a] -> [a]
: RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
ty'
else RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
ty'
| Just (FunTyFlag
_,Type
_,Type
arg,Type
res) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
ty
= Type -> OneShotInfo
typeOneShot Type
arg OneShotInfo -> [OneShotInfo] -> [OneShotInfo]
forall a. a -> [a] -> [a]
: RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts Type
res
| Just (TyCon
tc,[Type]
tys) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
ty
, Just (Type
ty', Coercion
_) <- TyCon -> [Type] -> Maybe (Type, Coercion)
instNewTyCon_maybe TyCon
tc [Type]
tys
, Just RecTcChecker
rec_nts' <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_nts TyCon
tc
= RecTcChecker -> Type -> [OneShotInfo]
go RecTcChecker
rec_nts' Type
ty'
| Bool
otherwise
= []
typeOneShot :: Type -> OneShotInfo
typeOneShot :: Type -> OneShotInfo
typeOneShot Type
ty
| Type -> Bool
isStateHackType Type
ty = OneShotInfo
OneShotLam
| Bool
otherwise = OneShotInfo
NoOneShotInfo
idStateHackOneShotInfo :: Id -> OneShotInfo
idStateHackOneShotInfo :: TyVar -> OneShotInfo
idStateHackOneShotInfo TyVar
id
| Type -> Bool
isStateHackType (TyVar -> Type
idType TyVar
id) = OneShotInfo
OneShotLam
| Bool
otherwise = TyVar -> OneShotInfo
idOneShotInfo TyVar
id
isOneShotBndr :: Var -> Bool
isOneShotBndr :: TyVar -> Bool
isOneShotBndr TyVar
var
| TyVar -> Bool
isTyVar TyVar
var = Bool
True
| OneShotInfo
OneShotLam <- TyVar -> OneShotInfo
idStateHackOneShotInfo TyVar
var = Bool
True
| Bool
otherwise = Bool
False
isStateHackType :: Type -> Bool
isStateHackType :: Type -> Bool
isStateHackType Type
ty
| Bool
unsafeHasNoStateHack
= Bool
False
| Bool
otherwise
= case Type -> Maybe TyCon
tyConAppTyCon_maybe Type
ty of
Just TyCon
tycon -> TyCon
tycon TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
statePrimTyCon
Maybe TyCon
_ -> Bool
False
zapLamBndrs :: FullArgCount -> [Var] -> [Var]
zapLamBndrs :: Int -> [TyVar] -> [TyVar]
zapLamBndrs Int
arg_count [TyVar]
bndrs
| Bool
no_need_to_zap = [TyVar]
bndrs
| Bool
otherwise = Int -> [TyVar] -> [TyVar]
zap_em Int
arg_count [TyVar]
bndrs
where
no_need_to_zap :: Bool
no_need_to_zap = (TyVar -> Bool) -> [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all TyVar -> Bool
isOneShotBndr (Int -> [TyVar] -> [TyVar]
forall a. Int -> [a] -> [a]
drop Int
arg_count [TyVar]
bndrs)
zap_em :: FullArgCount -> [Var] -> [Var]
zap_em :: Int -> [TyVar] -> [TyVar]
zap_em Int
0 [TyVar]
bs = [TyVar]
bs
zap_em Int
_ [] = []
zap_em Int
n (TyVar
b:[TyVar]
bs) | TyVar -> Bool
isTyVar TyVar
b = TyVar
b TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: Int -> [TyVar] -> [TyVar]
zap_em (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [TyVar]
bs
| Bool
otherwise = TyVar -> TyVar
zapLamIdInfo TyVar
b TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: Int -> [TyVar] -> [TyVar]
zap_em (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [TyVar]
bs
data ArityType
= AT ![ATLamInfo] !Divergence
deriving SafeArityType -> SafeArityType -> Bool
(SafeArityType -> SafeArityType -> Bool)
-> (SafeArityType -> SafeArityType -> Bool) -> Eq SafeArityType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SafeArityType -> SafeArityType -> Bool
== :: SafeArityType -> SafeArityType -> Bool
$c/= :: SafeArityType -> SafeArityType -> Bool
/= :: SafeArityType -> SafeArityType -> Bool
Eq
type ATLamInfo = (Cost,OneShotInfo)
type SafeArityType = ArityType
data Cost = IsCheap | IsExpensive
deriving( Cost -> Cost -> Bool
(Cost -> Cost -> Bool) -> (Cost -> Cost -> Bool) -> Eq Cost
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Cost -> Cost -> Bool
== :: Cost -> Cost -> Bool
$c/= :: Cost -> Cost -> Bool
/= :: Cost -> Cost -> Bool
Eq )
allCosts :: (a -> Cost) -> [a] -> Cost
allCosts :: forall a. (a -> Cost) -> [a] -> Cost
allCosts a -> Cost
f [a]
xs = (a -> Cost -> Cost) -> Cost -> [a] -> Cost
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Cost -> Cost -> Cost
addCost (Cost -> Cost -> Cost) -> (a -> Cost) -> a -> Cost -> Cost
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Cost
f) Cost
IsCheap [a]
xs
addCost :: Cost -> Cost -> Cost
addCost :: Cost -> Cost -> Cost
addCost Cost
IsCheap Cost
IsCheap = Cost
IsCheap
addCost Cost
_ Cost
_ = Cost
IsExpensive
instance Outputable ArityType where
ppr :: SafeArityType -> SDoc
ppr (AT [ATLamInfo]
oss Divergence
div)
| [ATLamInfo] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ATLamInfo]
oss = Divergence -> SDoc
forall {doc}. IsLine doc => Divergence -> doc
pp_div Divergence
div
| Bool
otherwise = Char -> SDoc
forall doc. IsLine doc => Char -> doc
char Char
'\\' SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat ((ATLamInfo -> SDoc) -> [ATLamInfo] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map ATLamInfo -> SDoc
forall {doc}. IsLine doc => ATLamInfo -> doc
pp_os [ATLamInfo]
oss) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc
forall doc. IsLine doc => doc
dot SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> Divergence -> SDoc
forall {doc}. IsLine doc => Divergence -> doc
pp_div Divergence
div
where
pp_div :: Divergence -> doc
pp_div Divergence
Diverges = Char -> doc
forall doc. IsLine doc => Char -> doc
char Char
'⊥'
pp_div Divergence
ExnOrDiv = Char -> doc
forall doc. IsLine doc => Char -> doc
char Char
'x'
pp_div Divergence
Dunno = Char -> doc
forall doc. IsLine doc => Char -> doc
char Char
'T'
pp_os :: ATLamInfo -> doc
pp_os (Cost
IsCheap, OneShotInfo
OneShotLam) = String -> doc
forall doc. IsLine doc => String -> doc
text String
"(C1)"
pp_os (Cost
IsExpensive, OneShotInfo
OneShotLam) = String -> doc
forall doc. IsLine doc => String -> doc
text String
"(X1)"
pp_os (Cost
IsCheap, OneShotInfo
NoOneShotInfo) = String -> doc
forall doc. IsLine doc => String -> doc
text String
"(C?)"
pp_os (Cost
IsExpensive, OneShotInfo
NoOneShotInfo) = String -> doc
forall doc. IsLine doc => String -> doc
text String
"(X?)"
mkBotArityType :: [OneShotInfo] -> ArityType
mkBotArityType :: [OneShotInfo] -> SafeArityType
mkBotArityType [OneShotInfo]
oss = [ATLamInfo] -> Divergence -> SafeArityType
AT [(Cost
IsCheap,OneShotInfo
os) | OneShotInfo
os <- [OneShotInfo]
oss] Divergence
botDiv
botArityType :: ArityType
botArityType :: SafeArityType
botArityType = [OneShotInfo] -> SafeArityType
mkBotArityType []
topArityType :: ArityType
topArityType :: SafeArityType
topArityType = [ATLamInfo] -> Divergence -> SafeArityType
AT [] Divergence
topDiv
arityTypeArity :: SafeArityType -> Arity
arityTypeArity :: SafeArityType -> Int
arityTypeArity (AT [ATLamInfo]
lams Divergence
_) = [ATLamInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ATLamInfo]
lams
arityTypeOneShots :: SafeArityType -> [OneShotInfo]
arityTypeOneShots :: SafeArityType -> [OneShotInfo]
arityTypeOneShots (AT [ATLamInfo]
lams Divergence
_) = (ATLamInfo -> OneShotInfo) -> [ATLamInfo] -> [OneShotInfo]
forall a b. (a -> b) -> [a] -> [b]
map ATLamInfo -> OneShotInfo
forall a b. (a, b) -> b
snd [ATLamInfo]
lams
safeArityType :: ArityType -> SafeArityType
safeArityType :: SafeArityType -> SafeArityType
safeArityType at :: SafeArityType
at@(AT [ATLamInfo]
lams Divergence
_)
= case Int -> Cost -> [ATLamInfo] -> Maybe Int
go Int
0 Cost
IsCheap [ATLamInfo]
lams of
Maybe Int
Nothing -> SafeArityType
at
Just Int
ar -> [ATLamInfo] -> Divergence -> SafeArityType
AT (Int -> [ATLamInfo] -> [ATLamInfo]
forall a. Int -> [a] -> [a]
take Int
ar [ATLamInfo]
lams) Divergence
topDiv
where
go :: Arity -> Cost -> [(Cost,OneShotInfo)] -> Maybe Arity
go :: Int -> Cost -> [ATLamInfo] -> Maybe Int
go Int
_ Cost
_ [] = Maybe Int
forall a. Maybe a
Nothing
go Int
ar Cost
ch1 ((Cost
ch2,OneShotInfo
os):[ATLamInfo]
lams)
= case (Cost
ch1 Cost -> Cost -> Cost
`addCost` Cost
ch2, OneShotInfo
os) of
(Cost
IsExpensive, OneShotInfo
NoOneShotInfo) -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
ar
(Cost
ch, OneShotInfo
_) -> Int -> Cost -> [ATLamInfo] -> Maybe Int
go (Int
arInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Cost
ch [ATLamInfo]
lams
infixl 2 `trimArityType`
trimArityType :: Arity -> ArityType -> ArityType
trimArityType :: Int -> SafeArityType -> SafeArityType
trimArityType Int
max_arity at :: SafeArityType
at@(AT [ATLamInfo]
lams Divergence
_)
| [ATLamInfo]
lams [ATLamInfo] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtMost` Int
max_arity = SafeArityType
at
| Bool
otherwise = [ATLamInfo] -> Divergence -> SafeArityType
AT (Int -> [ATLamInfo] -> [ATLamInfo]
forall a. Int -> [a] -> [a]
take Int
max_arity [ATLamInfo]
lams) Divergence
topDiv
data ArityOpts = ArityOpts
{ ArityOpts -> Bool
ao_ped_bot :: !Bool
, ArityOpts -> Bool
ao_dicts_cheap :: !Bool
}
exprEtaExpandArity :: HasDebugCallStack => ArityOpts -> CoreExpr -> Maybe SafeArityType
exprEtaExpandArity :: HasDebugCallStack => ArityOpts -> CoreExpr -> Maybe SafeArityType
exprEtaExpandArity ArityOpts
opts CoreExpr
e
| AT [] Divergence
_ <- SafeArityType
arity_type
= Maybe SafeArityType
forall a. Maybe a
Nothing
| Bool
otherwise
= SafeArityType -> Maybe SafeArityType
forall a. a -> Maybe a
Just SafeArityType
arity_type
where
arity_type :: SafeArityType
arity_type = SafeArityType -> SafeArityType
safeArityType (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType (ArityOpts -> Bool -> ArityEnv
findRhsArityEnv ArityOpts
opts Bool
False) CoreExpr
e)
findRhsArity :: ArityOpts -> RecFlag -> Id -> CoreExpr
-> (Bool, SafeArityType)
findRhsArity :: ArityOpts -> RecFlag -> TyVar -> CoreExpr -> (Bool, SafeArityType)
findRhsArity ArityOpts
opts RecFlag
is_rec TyVar
bndr CoreExpr
rhs
| TyVar -> Bool
isJoinId TyVar
bndr
= (Bool
False, SafeArityType
join_arity_type)
| Bool
otherwise
= (Bool
arity_increased, SafeArityType
non_join_arity_type)
where
old_arity :: Int
old_arity = CoreExpr -> Int
exprArity CoreExpr
rhs
init_env :: ArityEnv
init_env :: ArityEnv
init_env = ArityOpts -> Bool -> ArityEnv
findRhsArityEnv ArityOpts
opts (TyVar -> Bool
isJoinId TyVar
bndr)
non_join_arity_type :: SafeArityType
non_join_arity_type = case RecFlag
is_rec of
RecFlag
Recursive -> Int -> SafeArityType -> SafeArityType
go Int
0 SafeArityType
botArityType
RecFlag
NonRecursive -> ArityEnv -> SafeArityType
step ArityEnv
init_env
arity_increased :: Bool
arity_increased = SafeArityType -> Int
arityTypeArity SafeArityType
non_join_arity_type Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
old_arity
join_arity_type :: SafeArityType
join_arity_type = case RecFlag
is_rec of
RecFlag
Recursive -> Int -> SafeArityType -> SafeArityType
go Int
0 SafeArityType
botArityType
RecFlag
NonRecursive -> Int -> SafeArityType -> SafeArityType
trimArityType Int
ty_arity (HasDebugCallStack => CoreExpr -> SafeArityType
CoreExpr -> SafeArityType
cheapArityType CoreExpr
rhs)
ty_arity :: Int
ty_arity = Type -> Int
typeArity (TyVar -> Type
idType TyVar
bndr)
use_call_cards :: [Card]
use_call_cards = TyVar -> [Card]
useSiteCallCards TyVar
bndr
step :: ArityEnv -> SafeArityType
step :: ArityEnv -> SafeArityType
step ArityEnv
env = Int -> SafeArityType -> SafeArityType
trimArityType Int
ty_arity (SafeArityType -> SafeArityType) -> SafeArityType -> SafeArityType
forall a b. (a -> b) -> a -> b
$
SafeArityType -> SafeArityType
safeArityType (SafeArityType -> SafeArityType) -> SafeArityType -> SafeArityType
forall a b. (a -> b) -> a -> b
$
ArityEnv -> SafeArityType -> [Card] -> SafeArityType
combineWithCallCards ArityEnv
env (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
rhs) [Card]
use_call_cards
go :: Int -> SafeArityType -> SafeArityType
go :: Int -> SafeArityType -> SafeArityType
go !Int
n cur_at :: SafeArityType
cur_at@(AT [ATLamInfo]
lams Divergence
div)
| Bool -> Bool
not (Divergence -> Bool
isDeadEndDiv Divergence
div)
, [ATLamInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ATLamInfo]
lams Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
old_arity = SafeArityType
cur_at
| SafeArityType
next_at SafeArityType -> SafeArityType -> Bool
forall a. Eq a => a -> a -> Bool
== SafeArityType
cur_at = SafeArityType
cur_at
| Bool
otherwise
= Bool -> String -> SDoc -> SafeArityType -> SafeArityType
forall a. HasCallStack => Bool -> String -> SDoc -> a -> a
warnPprTrace (Bool
debugIsOn Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2)
String
"Exciting arity"
(Int -> SDoc -> SDoc
nest Int
2 (TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
bndr SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SafeArityType -> SDoc
forall a. Outputable a => a -> SDoc
ppr SafeArityType
cur_at SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SafeArityType -> SDoc
forall a. Outputable a => a -> SDoc
ppr SafeArityType
next_at SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
rhs)) (SafeArityType -> SafeArityType) -> SafeArityType -> SafeArityType
forall a b. (a -> b) -> a -> b
$
Int -> SafeArityType -> SafeArityType
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) SafeArityType
next_at
where
next_at :: SafeArityType
next_at = ArityEnv -> SafeArityType
step (ArityEnv -> TyVar -> SafeArityType -> ArityEnv
extendSigEnv ArityEnv
init_env TyVar
bndr SafeArityType
cur_at)
combineWithCallCards :: ArityEnv -> ArityType -> [Card] -> ArityType
combineWithCallCards :: ArityEnv -> SafeArityType -> [Card] -> SafeArityType
combineWithCallCards ArityEnv
env at :: SafeArityType
at@(AT [ATLamInfo]
lams Divergence
div) [Card]
cards
| [ATLamInfo] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ATLamInfo]
lams = SafeArityType
at
| Bool
otherwise = [ATLamInfo] -> Divergence -> SafeArityType
AT ([ATLamInfo] -> [OneShotInfo] -> [ATLamInfo]
zip_lams [ATLamInfo]
lams [OneShotInfo]
oss) Divergence
div
where
oss :: [OneShotInfo]
oss = (Card -> OneShotInfo) -> [Card] -> [OneShotInfo]
forall a b. (a -> b) -> [a] -> [b]
map Card -> OneShotInfo
card_to_oneshot [Card]
cards
card_to_oneshot :: Card -> OneShotInfo
card_to_oneshot Card
n
| Card -> Bool
isAtMostOnce Card
n, Bool -> Bool
not (ArityEnv -> Bool
pedanticBottoms ArityEnv
env)
= OneShotInfo
OneShotLam
| Card
n Card -> Card -> Bool
forall a. Eq a => a -> a -> Bool
== Card
C_11
= OneShotInfo
OneShotLam
| Bool
otherwise
= OneShotInfo
NoOneShotInfo
zip_lams :: [ATLamInfo] -> [OneShotInfo] -> [ATLamInfo]
zip_lams :: [ATLamInfo] -> [OneShotInfo] -> [ATLamInfo]
zip_lams [ATLamInfo]
lams [] = [ATLamInfo]
lams
zip_lams [] [OneShotInfo]
oss | Divergence -> Bool
isDeadEndDiv Divergence
div = []
| Bool
otherwise = [ (Cost
IsExpensive,OneShotInfo
OneShotLam)
| OneShotInfo
_ <- (OneShotInfo -> Bool) -> [OneShotInfo] -> [OneShotInfo]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo [OneShotInfo]
oss]
zip_lams ((Cost
ch,OneShotInfo
os1):[ATLamInfo]
lams) (OneShotInfo
os2:[OneShotInfo]
oss)
= (Cost
ch, OneShotInfo
os1 OneShotInfo -> OneShotInfo -> OneShotInfo
`bestOneShot` OneShotInfo
os2) ATLamInfo -> [ATLamInfo] -> [ATLamInfo]
forall a. a -> [a] -> [a]
: [ATLamInfo] -> [OneShotInfo] -> [ATLamInfo]
zip_lams [ATLamInfo]
lams [OneShotInfo]
oss
useSiteCallCards :: Id -> [Card]
useSiteCallCards :: TyVar -> [Card]
useSiteCallCards TyVar
bndr
= [Card]
call_arity_one_shots [Card] -> [Card] -> [Card]
`zip_cards` [Card]
dmd_one_shots
where
call_arity_one_shots :: [Card]
call_arity_one_shots :: [Card]
call_arity_one_shots
| Int
call_arity Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = []
| Bool
otherwise = Card
C_0N Card -> [Card] -> [Card]
forall a. a -> [a] -> [a]
: Int -> Card -> [Card]
forall a. Int -> a -> [a]
replicate (Int
call_arityInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Card
C_01
call_arity :: Int
call_arity = TyVar -> Int
idCallArity TyVar
bndr
dmd_one_shots :: [Card]
dmd_one_shots :: [Card]
dmd_one_shots = case TyVar -> Demand
idDemandInfo TyVar
bndr of
Demand
AbsDmd -> []
Demand
BotDmd -> []
Card
_ :* SubDemand
sd -> SubDemand -> [Card]
callCards SubDemand
sd
zip_cards :: [Card] -> [Card] -> [Card]
zip_cards (Card
n1:[Card]
ns1) (Card
n2:[Card]
ns2) = (Card
n1 Card -> Card -> Card
`glbCard` Card
n2) Card -> [Card] -> [Card]
forall a. a -> [a] -> [a]
: [Card] -> [Card] -> [Card]
zip_cards [Card]
ns1 [Card]
ns2
zip_cards [] [Card]
ns2 = [Card]
ns2
zip_cards [Card]
ns1 [] = [Card]
ns1
arityLam :: Id -> ArityType -> ArityType
arityLam :: TyVar -> SafeArityType -> SafeArityType
arityLam TyVar
id (AT [ATLamInfo]
oss Divergence
div)
= [ATLamInfo] -> Divergence -> SafeArityType
AT ((Cost
IsCheap, OneShotInfo
one_shot) ATLamInfo -> [ATLamInfo] -> [ATLamInfo]
forall a. a -> [a] -> [a]
: [ATLamInfo]
oss) Divergence
div
where
one_shot :: OneShotInfo
one_shot | Divergence -> Bool
isDeadEndDiv Divergence
div = OneShotInfo
OneShotLam
| Bool
otherwise = TyVar -> OneShotInfo
idStateHackOneShotInfo TyVar
id
floatIn :: Cost -> ArityType -> ArityType
floatIn :: Cost -> SafeArityType -> SafeArityType
floatIn Cost
ch at :: SafeArityType
at@(AT [ATLamInfo]
lams Divergence
div)
= case [ATLamInfo]
lams of
[] -> SafeArityType
at
(Cost
IsExpensive,OneShotInfo
_):[ATLamInfo]
_ -> SafeArityType
at
(Cost
_,OneShotInfo
os):[ATLamInfo]
lams -> [ATLamInfo] -> Divergence -> SafeArityType
AT ((Cost
ch,OneShotInfo
os)ATLamInfo -> [ATLamInfo] -> [ATLamInfo]
forall a. a -> [a] -> [a]
:[ATLamInfo]
lams) Divergence
div
addWork :: ArityType -> ArityType
addWork :: SafeArityType -> SafeArityType
addWork at :: SafeArityType
at@(AT [ATLamInfo]
lams Divergence
div)
= case [ATLamInfo]
lams of
[] -> SafeArityType
at
ATLamInfo
lam:[ATLamInfo]
lams' -> [ATLamInfo] -> Divergence -> SafeArityType
AT (ATLamInfo -> ATLamInfo
add_work ATLamInfo
lam ATLamInfo -> [ATLamInfo] -> [ATLamInfo]
forall a. a -> [a] -> [a]
: [ATLamInfo]
lams') Divergence
div
add_work :: ATLamInfo -> ATLamInfo
add_work :: ATLamInfo -> ATLamInfo
add_work (Cost
_,OneShotInfo
os) = (Cost
IsExpensive,OneShotInfo
os)
arityApp :: ArityType -> Cost -> ArityType
arityApp :: SafeArityType -> Cost -> SafeArityType
arityApp (AT ((Cost
ch1,OneShotInfo
_):[ATLamInfo]
oss) Divergence
div) Cost
ch2 = Cost -> SafeArityType -> SafeArityType
floatIn (Cost
ch1 Cost -> Cost -> Cost
`addCost` Cost
ch2) ([ATLamInfo] -> Divergence -> SafeArityType
AT [ATLamInfo]
oss Divergence
div)
arityApp SafeArityType
at Cost
_ = SafeArityType
at
andArityType :: ArityEnv -> ArityType -> ArityType -> ArityType
andArityType :: ArityEnv -> SafeArityType -> SafeArityType -> SafeArityType
andArityType ArityEnv
env (AT (ATLamInfo
lam1:[ATLamInfo]
lams1) Divergence
div1) (AT (ATLamInfo
lam2:[ATLamInfo]
lams2) Divergence
div2)
| AT [ATLamInfo]
lams' Divergence
div' <- ArityEnv -> SafeArityType -> SafeArityType -> SafeArityType
andArityType ArityEnv
env ([ATLamInfo] -> Divergence -> SafeArityType
AT [ATLamInfo]
lams1 Divergence
div1) ([ATLamInfo] -> Divergence -> SafeArityType
AT [ATLamInfo]
lams2 Divergence
div2)
= [ATLamInfo] -> Divergence -> SafeArityType
AT ((ATLamInfo
lam1 ATLamInfo -> ATLamInfo -> ATLamInfo
`and_lam` ATLamInfo
lam2) ATLamInfo -> [ATLamInfo] -> [ATLamInfo]
forall a. a -> [a] -> [a]
: [ATLamInfo]
lams') Divergence
div'
where
(Cost
ch1,OneShotInfo
os1) and_lam :: ATLamInfo -> ATLamInfo -> ATLamInfo
`and_lam` (Cost
ch2,OneShotInfo
os2)
= ( Cost
ch1 Cost -> Cost -> Cost
`addCost` Cost
ch2, OneShotInfo
os1 OneShotInfo -> OneShotInfo -> OneShotInfo
`bestOneShot` OneShotInfo
os2)
andArityType ArityEnv
env (AT [] Divergence
div1) SafeArityType
at2 = ArityEnv -> Divergence -> SafeArityType -> SafeArityType
andWithTail ArityEnv
env Divergence
div1 SafeArityType
at2
andArityType ArityEnv
env SafeArityType
at1 (AT [] Divergence
div2) = ArityEnv -> Divergence -> SafeArityType -> SafeArityType
andWithTail ArityEnv
env Divergence
div2 SafeArityType
at1
andWithTail :: ArityEnv -> Divergence -> ArityType -> ArityType
andWithTail :: ArityEnv -> Divergence -> SafeArityType -> SafeArityType
andWithTail ArityEnv
env Divergence
div1 at2 :: SafeArityType
at2@(AT [ATLamInfo]
lams2 Divergence
_)
| Divergence -> Bool
isDeadEndDiv Divergence
div1
= SafeArityType
at2
| ArityEnv -> Bool
pedanticBottoms ArityEnv
env
= [ATLamInfo] -> Divergence -> SafeArityType
AT [] Divergence
topDiv
| Bool
otherwise
= [ATLamInfo] -> Divergence -> SafeArityType
AT ((ATLamInfo -> ATLamInfo) -> [ATLamInfo] -> [ATLamInfo]
forall a b. (a -> b) -> [a] -> [b]
map ATLamInfo -> ATLamInfo
add_work [ATLamInfo]
lams2) Divergence
topDiv
data ArityEnv
= AE { ArityEnv -> ArityOpts
am_opts :: !ArityOpts
, ArityEnv -> IdEnv SafeArityType
am_sigs :: !(IdEnv SafeArityType)
, ArityEnv -> Bool
am_free_joins :: !Bool
}
instance Outputable ArityEnv where
ppr :: ArityEnv -> SDoc
ppr (AE { am_sigs :: ArityEnv -> IdEnv SafeArityType
am_sigs = IdEnv SafeArityType
sigs, am_free_joins :: ArityEnv -> Bool
am_free_joins = Bool
free_joins })
= String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"AE" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces ([SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
sep [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"free joins:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
free_joins
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"sigs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> IdEnv SafeArityType -> SDoc
forall a. Outputable a => a -> SDoc
ppr IdEnv SafeArityType
sigs ])
findRhsArityEnv :: ArityOpts -> Bool -> ArityEnv
findRhsArityEnv :: ArityOpts -> Bool -> ArityEnv
findRhsArityEnv ArityOpts
opts Bool
free_joins
= AE { am_opts :: ArityOpts
am_opts = ArityOpts
opts
, am_free_joins :: Bool
am_free_joins = Bool
free_joins
, am_sigs :: IdEnv SafeArityType
am_sigs = IdEnv SafeArityType
forall a. VarEnv a
emptyVarEnv }
freeJoinsOK :: ArityEnv -> Bool
freeJoinsOK :: ArityEnv -> Bool
freeJoinsOK (AE { am_free_joins :: ArityEnv -> Bool
am_free_joins = Bool
free_joins }) = Bool
free_joins
modifySigEnv :: (IdEnv ArityType -> IdEnv ArityType) -> ArityEnv -> ArityEnv
modifySigEnv :: (IdEnv SafeArityType -> IdEnv SafeArityType)
-> ArityEnv -> ArityEnv
modifySigEnv IdEnv SafeArityType -> IdEnv SafeArityType
f env :: ArityEnv
env@(AE { am_sigs :: ArityEnv -> IdEnv SafeArityType
am_sigs = IdEnv SafeArityType
sigs }) = ArityEnv
env { am_sigs = f sigs }
{-# INLINE modifySigEnv #-}
del_sig_env :: Id -> ArityEnv -> ArityEnv
del_sig_env :: TyVar -> ArityEnv -> ArityEnv
del_sig_env TyVar
id = (IdEnv SafeArityType -> IdEnv SafeArityType)
-> ArityEnv -> ArityEnv
modifySigEnv (\IdEnv SafeArityType
sigs -> IdEnv SafeArityType -> TyVar -> IdEnv SafeArityType
forall a. VarEnv a -> TyVar -> VarEnv a
delVarEnv IdEnv SafeArityType
sigs TyVar
id)
{-# INLINE del_sig_env #-}
del_sig_env_list :: [Id] -> ArityEnv -> ArityEnv
del_sig_env_list :: [TyVar] -> ArityEnv -> ArityEnv
del_sig_env_list [TyVar]
ids = (IdEnv SafeArityType -> IdEnv SafeArityType)
-> ArityEnv -> ArityEnv
modifySigEnv (\IdEnv SafeArityType
sigs -> IdEnv SafeArityType -> [TyVar] -> IdEnv SafeArityType
forall a. VarEnv a -> [TyVar] -> VarEnv a
delVarEnvList IdEnv SafeArityType
sigs [TyVar]
ids)
{-# INLINE del_sig_env_list #-}
extendSigEnv :: ArityEnv -> Id -> SafeArityType -> ArityEnv
extendSigEnv :: ArityEnv -> TyVar -> SafeArityType -> ArityEnv
extendSigEnv ArityEnv
env TyVar
id SafeArityType
ar_ty
= (IdEnv SafeArityType -> IdEnv SafeArityType)
-> ArityEnv -> ArityEnv
modifySigEnv (\IdEnv SafeArityType
sigs -> IdEnv SafeArityType
-> TyVar -> SafeArityType -> IdEnv SafeArityType
forall a. VarEnv a -> TyVar -> a -> VarEnv a
extendVarEnv IdEnv SafeArityType
sigs TyVar
id SafeArityType
ar_ty) (ArityEnv -> ArityEnv) -> ArityEnv -> ArityEnv
forall a b. (a -> b) -> a -> b
$
ArityEnv
env
delInScope :: ArityEnv -> Id -> ArityEnv
delInScope :: ArityEnv -> TyVar -> ArityEnv
delInScope ArityEnv
env TyVar
id = TyVar -> ArityEnv -> ArityEnv
del_sig_env TyVar
id ArityEnv
env
delInScopeList :: ArityEnv -> [Id] -> ArityEnv
delInScopeList :: ArityEnv -> [TyVar] -> ArityEnv
delInScopeList ArityEnv
env [TyVar]
ids = [TyVar] -> ArityEnv -> ArityEnv
del_sig_env_list [TyVar]
ids ArityEnv
env
lookupSigEnv :: ArityEnv -> Id -> Maybe SafeArityType
lookupSigEnv :: ArityEnv -> TyVar -> Maybe SafeArityType
lookupSigEnv (AE { am_sigs :: ArityEnv -> IdEnv SafeArityType
am_sigs = IdEnv SafeArityType
sigs }) TyVar
id = IdEnv SafeArityType -> TyVar -> Maybe SafeArityType
forall a. VarEnv a -> TyVar -> Maybe a
lookupVarEnv IdEnv SafeArityType
sigs TyVar
id
pedanticBottoms :: ArityEnv -> Bool
pedanticBottoms :: ArityEnv -> Bool
pedanticBottoms (AE { am_opts :: ArityEnv -> ArityOpts
am_opts = ArityOpts{ ao_ped_bot :: ArityOpts -> Bool
ao_ped_bot = Bool
ped_bot }}) = Bool
ped_bot
exprCost :: ArityEnv -> CoreExpr -> Maybe Type -> Cost
exprCost :: ArityEnv -> CoreExpr -> Maybe Type -> Cost
exprCost ArityEnv
env CoreExpr
e Maybe Type
mb_ty
| ArityEnv -> CoreExpr -> Maybe Type -> Bool
myExprIsCheap ArityEnv
env CoreExpr
e Maybe Type
mb_ty = Cost
IsCheap
| Bool
otherwise = Cost
IsExpensive
myExprIsCheap :: ArityEnv -> CoreExpr -> Maybe Type -> Bool
myExprIsCheap :: ArityEnv -> CoreExpr -> Maybe Type -> Bool
myExprIsCheap (AE { am_opts :: ArityEnv -> ArityOpts
am_opts = ArityOpts
opts, am_sigs :: ArityEnv -> IdEnv SafeArityType
am_sigs = IdEnv SafeArityType
sigs }) CoreExpr
e Maybe Type
mb_ty
= Bool
cheap_dict Bool -> Bool -> Bool
|| CoreExpr -> Bool
cheap_fun CoreExpr
e
where
cheap_dict :: Bool
cheap_dict = case Maybe Type
mb_ty of
Maybe Type
Nothing -> Bool
False
Just Type
ty -> (ArityOpts -> Bool
ao_dicts_cheap ArityOpts
opts Bool -> Bool -> Bool
&& Type -> Bool
isDictTy Type
ty)
Bool -> Bool -> Bool
|| Type -> Bool
isCallStackPredTy Type
ty Bool -> Bool -> Bool
|| Type -> Bool
isCallStackTy Type
ty
cheap_fun :: CoreExpr -> Bool
cheap_fun CoreExpr
e = CheapAppFun -> CoreExpr -> Bool
exprIsCheapX (IdEnv SafeArityType -> CheapAppFun
myIsCheapApp IdEnv SafeArityType
sigs) CoreExpr
e
myIsCheapApp :: IdEnv SafeArityType -> CheapAppFun
myIsCheapApp :: IdEnv SafeArityType -> CheapAppFun
myIsCheapApp IdEnv SafeArityType
sigs TyVar
fn Int
n_val_args = case IdEnv SafeArityType -> TyVar -> Maybe SafeArityType
forall a. VarEnv a -> TyVar -> Maybe a
lookupVarEnv IdEnv SafeArityType
sigs TyVar
fn of
Maybe SafeArityType
Nothing -> CheapAppFun
isCheapApp TyVar
fn Int
n_val_args
Just (AT [ATLamInfo]
lams Divergence
div)
| Divergence -> Bool
isDeadEndDiv Divergence
div -> Bool
True
| Int
n_val_args Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 -> Bool
True
| Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [ATLamInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ATLamInfo]
lams -> Bool
True
| Bool
otherwise -> Bool
False
arityType :: HasDebugCallStack => ArityEnv -> CoreExpr -> ArityType
arityType :: HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env (Var TyVar
v)
| Just SafeArityType
at <- ArityEnv -> TyVar -> Maybe SafeArityType
lookupSigEnv ArityEnv
env TyVar
v
= SafeArityType
at
| Bool
otherwise
= Bool -> SDoc -> SafeArityType -> SafeArityType
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (ArityEnv -> Bool
freeJoinsOK ArityEnv
env Bool -> Bool -> Bool
|| Bool -> Bool
not (TyVar -> Bool
isJoinId TyVar
v)) (TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
v) (SafeArityType -> SafeArityType) -> SafeArityType -> SafeArityType
forall a b. (a -> b) -> a -> b
$
TyVar -> SafeArityType
idArityType TyVar
v
arityType ArityEnv
env (Cast CoreExpr
e Coercion
_)
= HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
e
arityType ArityEnv
env (Lam TyVar
x CoreExpr
e)
| TyVar -> Bool
isId TyVar
x = TyVar -> SafeArityType -> SafeArityType
arityLam TyVar
x (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env' CoreExpr
e)
| Bool
otherwise = HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env' CoreExpr
e
where
env' :: ArityEnv
env' = ArityEnv -> TyVar -> ArityEnv
delInScope ArityEnv
env TyVar
x
arityType ArityEnv
env (App CoreExpr
fun (Type Type
_))
= HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
fun
arityType ArityEnv
env (App CoreExpr
fun CoreExpr
arg )
= SafeArityType -> Cost -> SafeArityType
arityApp SafeArityType
fun_at Cost
arg_cost
where
fun_at :: SafeArityType
fun_at = HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
fun
arg_cost :: Cost
arg_cost = ArityEnv -> CoreExpr -> Maybe Type -> Cost
exprCost ArityEnv
env CoreExpr
arg Maybe Type
forall a. Maybe a
Nothing
arityType ArityEnv
env (Case CoreExpr
scrut TyVar
bndr Type
_ [Alt TyVar]
alts)
| CoreExpr -> Bool
exprIsDeadEnd CoreExpr
scrut Bool -> Bool -> Bool
|| [Alt TyVar] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt TyVar]
alts
= SafeArityType
botArityType
| Bool -> Bool
not (ArityEnv -> Bool
pedanticBottoms ArityEnv
env)
, ArityEnv -> CoreExpr -> Maybe Type -> Bool
myExprIsCheap ArityEnv
env CoreExpr
scrut (Type -> Maybe Type
forall a. a -> Maybe a
Just (TyVar -> Type
idType TyVar
bndr))
= SafeArityType
alts_type
| CoreExpr -> Bool
exprOkForSpeculation CoreExpr
scrut
= SafeArityType
alts_type
| Bool
otherwise
= SafeArityType -> SafeArityType
addWork SafeArityType
alts_type
where
env' :: ArityEnv
env' = ArityEnv -> TyVar -> ArityEnv
delInScope ArityEnv
env TyVar
bndr
arity_type_alt :: Alt TyVar -> SafeArityType
arity_type_alt (Alt AltCon
_con [TyVar]
bndrs CoreExpr
rhs) = HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType (ArityEnv -> [TyVar] -> ArityEnv
delInScopeList ArityEnv
env' [TyVar]
bndrs) CoreExpr
rhs
alts_type :: SafeArityType
alts_type = (SafeArityType -> SafeArityType -> SafeArityType)
-> [SafeArityType] -> SafeArityType
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (ArityEnv -> SafeArityType -> SafeArityType -> SafeArityType
andArityType ArityEnv
env) ((Alt TyVar -> SafeArityType) -> [Alt TyVar] -> [SafeArityType]
forall a b. (a -> b) -> [a] -> [b]
map Alt TyVar -> SafeArityType
arity_type_alt [Alt TyVar]
alts)
arityType ArityEnv
env (Let (NonRec TyVar
b CoreExpr
rhs) CoreExpr
e)
=
Cost -> SafeArityType -> SafeArityType
floatIn Cost
rhs_cost (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env' CoreExpr
e)
where
rhs_cost :: Cost
rhs_cost = ArityEnv -> CoreExpr -> Maybe Type -> Cost
exprCost ArityEnv
env CoreExpr
rhs (Type -> Maybe Type
forall a. a -> Maybe a
Just (TyVar -> Type
idType TyVar
b))
env' :: ArityEnv
env' = ArityEnv -> TyVar -> SafeArityType -> ArityEnv
extendSigEnv ArityEnv
env TyVar
b (SafeArityType -> SafeArityType
safeArityType (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
rhs))
arityType ArityEnv
env (Let (Rec [(TyVar, CoreExpr)]
prs) CoreExpr
e)
=
Cost -> SafeArityType -> SafeArityType
floatIn (((TyVar, CoreExpr) -> Cost) -> [(TyVar, CoreExpr)] -> Cost
forall a. (a -> Cost) -> [a] -> Cost
allCosts (TyVar, CoreExpr) -> Cost
bind_cost [(TyVar, CoreExpr)]
prs) (HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env' CoreExpr
e)
where
bind_cost :: (TyVar, CoreExpr) -> Cost
bind_cost (TyVar
b,CoreExpr
e) = ArityEnv -> CoreExpr -> Maybe Type -> Cost
exprCost ArityEnv
env' CoreExpr
e (Type -> Maybe Type
forall a. a -> Maybe a
Just (TyVar -> Type
idType TyVar
b))
env' :: ArityEnv
env' = (ArityEnv -> (TyVar, CoreExpr) -> ArityEnv)
-> ArityEnv -> [(TyVar, CoreExpr)] -> ArityEnv
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ArityEnv -> (TyVar, CoreExpr) -> ArityEnv
extend_rec ArityEnv
env [(TyVar, CoreExpr)]
prs
extend_rec :: ArityEnv -> (Id,CoreExpr) -> ArityEnv
extend_rec :: ArityEnv -> (TyVar, CoreExpr) -> ArityEnv
extend_rec ArityEnv
env (TyVar
b,CoreExpr
_) = ArityEnv -> TyVar -> SafeArityType -> ArityEnv
extendSigEnv ArityEnv
env TyVar
b (SafeArityType -> ArityEnv) -> SafeArityType -> ArityEnv
forall a b. (a -> b) -> a -> b
$
TyVar -> SafeArityType
idArityType TyVar
b
arityType ArityEnv
env (Tick CoreTickish
t CoreExpr
e)
| Bool -> Bool
not (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t) = HasDebugCallStack => ArityEnv -> CoreExpr -> SafeArityType
ArityEnv -> CoreExpr -> SafeArityType
arityType ArityEnv
env CoreExpr
e
arityType ArityEnv
_ CoreExpr
_ = SafeArityType
topArityType
idArityType :: Id -> ArityType
idArityType :: TyVar -> SafeArityType
idArityType TyVar
v
| DmdSig
strict_sig <- TyVar -> DmdSig
idDmdSig TyVar
v
, ([Demand]
ds, Divergence
div) <- DmdSig -> ([Demand], Divergence)
splitDmdSig DmdSig
strict_sig
, Divergence -> Bool
isDeadEndDiv Divergence
div
= [ATLamInfo] -> Divergence -> SafeArityType
AT ([Demand] -> [ATLamInfo] -> [ATLamInfo]
forall b a. [b] -> [a] -> [a]
takeList [Demand]
ds [ATLamInfo]
one_shots) Divergence
div
| Type -> Bool
isEmptyTy Type
id_ty
= SafeArityType
botArityType
| Bool
otherwise
= [ATLamInfo] -> Divergence -> SafeArityType
AT (Int -> [ATLamInfo] -> [ATLamInfo]
forall a. Int -> [a] -> [a]
take (TyVar -> Int
idArity TyVar
v) [ATLamInfo]
one_shots) Divergence
topDiv
where
id_ty :: Type
id_ty = TyVar -> Type
idType TyVar
v
one_shots :: [(Cost,OneShotInfo)]
one_shots :: [ATLamInfo]
one_shots = Cost -> [Cost]
forall a. a -> [a]
repeat Cost
IsCheap [Cost] -> [OneShotInfo] -> [ATLamInfo]
forall a b. [a] -> [b] -> [(a, b)]
`zip` Type -> [OneShotInfo]
typeOneShots Type
id_ty
cheapArityType :: HasDebugCallStack => CoreExpr -> ArityType
cheapArityType :: HasDebugCallStack => CoreExpr -> SafeArityType
cheapArityType CoreExpr
e = CoreExpr -> SafeArityType
go CoreExpr
e
where
go :: CoreExpr -> SafeArityType
go (Var TyVar
v) = TyVar -> SafeArityType
idArityType TyVar
v
go (Cast CoreExpr
e Coercion
_) = CoreExpr -> SafeArityType
go CoreExpr
e
go (Lam TyVar
x CoreExpr
e) | TyVar -> Bool
isId TyVar
x = TyVar -> SafeArityType -> SafeArityType
arityLam TyVar
x (CoreExpr -> SafeArityType
go CoreExpr
e)
| Bool
otherwise = CoreExpr -> SafeArityType
go CoreExpr
e
go (App CoreExpr
e CoreExpr
a) | CoreExpr -> Bool
forall b. Expr b -> Bool
isTypeArg CoreExpr
a = CoreExpr -> SafeArityType
go CoreExpr
e
| Bool
otherwise = CoreExpr -> SafeArityType -> SafeArityType
arity_app CoreExpr
a (CoreExpr -> SafeArityType
go CoreExpr
e)
go (Tick CoreTickish
t CoreExpr
e) | Bool -> Bool
not (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t) = CoreExpr -> SafeArityType
go CoreExpr
e
go (Case CoreExpr
_ TyVar
_ Type
_ [Alt TyVar]
alts) | [Alt TyVar] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt TyVar]
alts = SafeArityType
botArityType
go CoreExpr
_ = SafeArityType
topArityType
arity_app :: CoreExpr -> SafeArityType -> SafeArityType
arity_app CoreExpr
_ at :: SafeArityType
at@(AT [] Divergence
_) = SafeArityType
at
arity_app CoreExpr
arg at :: SafeArityType
at@(AT ((Cost
cost,OneShotInfo
_):[ATLamInfo]
lams) Divergence
div)
| Bool -> SDoc -> Bool -> Bool
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Cost
cost Cost -> Cost -> Bool
forall a. Eq a => a -> a -> Bool
== Cost
IsCheap) (SafeArityType -> SDoc
forall a. Outputable a => a -> SDoc
ppr SafeArityType
at SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
arg) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$
Divergence -> Bool
isDeadEndDiv Divergence
div = [ATLamInfo] -> Divergence -> SafeArityType
AT [ATLamInfo]
lams Divergence
div
| CoreExpr -> Bool
exprIsTrivial CoreExpr
arg = [ATLamInfo] -> Divergence -> SafeArityType
AT [ATLamInfo]
lams Divergence
topDiv
| Bool
otherwise = SafeArityType
topArityType
exprArity :: CoreExpr -> Arity
exprArity :: CoreExpr -> Int
exprArity CoreExpr
e = CoreExpr -> Int
go CoreExpr
e
where
go :: CoreExpr -> Int
go (Var TyVar
v) = TyVar -> Int
idArity TyVar
v
go (Lam TyVar
x CoreExpr
e) | TyVar -> Bool
isId TyVar
x = CoreExpr -> Int
go CoreExpr
e Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
| Bool
otherwise = CoreExpr -> Int
go CoreExpr
e
go (Tick CoreTickish
t CoreExpr
e) | Bool -> Bool
not (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t) = CoreExpr -> Int
go CoreExpr
e
go (Cast CoreExpr
e Coercion
_) = CoreExpr -> Int
go CoreExpr
e
go (App CoreExpr
e (Type Type
_)) = CoreExpr -> Int
go CoreExpr
e
go (App CoreExpr
f CoreExpr
a) | CoreExpr -> Bool
exprIsTrivial CoreExpr
a = (CoreExpr -> Int
go CoreExpr
f Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` Int
0
go CoreExpr
_ = Int
0
exprIsDeadEnd :: CoreExpr -> Bool
exprIsDeadEnd :: CoreExpr -> Bool
exprIsDeadEnd CoreExpr
e
= Int -> CoreExpr -> Bool
go Int
0 CoreExpr
e
where
go :: Arity -> CoreExpr -> Bool
go :: Int -> CoreExpr -> Bool
go Int
_ (Lit {}) = Bool
False
go Int
_ (Type {}) = Bool
False
go Int
_ (Coercion {}) = Bool
False
go Int
n (App CoreExpr
e CoreExpr
a) | CoreExpr -> Bool
forall b. Expr b -> Bool
isTypeArg CoreExpr
a = Int -> CoreExpr -> Bool
go Int
n CoreExpr
e
| Bool
otherwise = Int -> CoreExpr -> Bool
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) CoreExpr
e
go Int
n (Tick CoreTickish
_ CoreExpr
e) = Int -> CoreExpr -> Bool
go Int
n CoreExpr
e
go Int
n (Cast CoreExpr
e Coercion
_) = Int -> CoreExpr -> Bool
go Int
n CoreExpr
e
go Int
n (Let Bind TyVar
_ CoreExpr
e) = Int -> CoreExpr -> Bool
go Int
n CoreExpr
e
go Int
n (Lam TyVar
v CoreExpr
e) | TyVar -> Bool
isTyVar TyVar
v = Int -> CoreExpr -> Bool
go Int
n CoreExpr
e
| Bool
otherwise = Bool
False
go Int
_ (Case CoreExpr
_ TyVar
_ Type
_ [Alt TyVar]
alts) = [Alt TyVar] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt TyVar]
alts
go Int
n (Var TyVar
v) | DmdSig -> Int -> Bool
isDeadEndAppSig (TyVar -> DmdSig
idDmdSig TyVar
v) Int
n = Bool
True
| Type -> Bool
isEmptyTy (TyVar -> Type
idType TyVar
v) = Bool
True
| Bool
otherwise = Bool
False
etaExpand :: Arity -> CoreExpr -> CoreExpr
etaExpand :: Int -> CoreExpr -> CoreExpr
etaExpand Int
n CoreExpr
orig_expr
= InScopeSet -> [OneShotInfo] -> CoreExpr -> CoreExpr
eta_expand InScopeSet
in_scope (Int -> OneShotInfo -> [OneShotInfo]
forall a. Int -> a -> [a]
replicate Int
n OneShotInfo
NoOneShotInfo) CoreExpr
orig_expr
where
in_scope :: InScopeSet
in_scope = {-#SCC "eta_expand:in-scopeX" #-}
VarSet -> InScopeSet
mkInScopeSet (CoreExpr -> VarSet
exprFreeVars CoreExpr
orig_expr)
etaExpandAT :: InScopeSet -> SafeArityType -> CoreExpr -> CoreExpr
etaExpandAT :: InScopeSet -> SafeArityType -> CoreExpr -> CoreExpr
etaExpandAT InScopeSet
in_scope SafeArityType
at CoreExpr
orig_expr
= InScopeSet -> [OneShotInfo] -> CoreExpr -> CoreExpr
eta_expand InScopeSet
in_scope (SafeArityType -> [OneShotInfo]
arityTypeOneShots SafeArityType
at) CoreExpr
orig_expr
eta_expand :: InScopeSet -> [OneShotInfo] -> CoreExpr -> CoreExpr
eta_expand :: InScopeSet -> [OneShotInfo] -> CoreExpr -> CoreExpr
eta_expand InScopeSet
in_scope [OneShotInfo]
one_shots (Cast CoreExpr
expr Coercion
co)
= HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast (InScopeSet -> [OneShotInfo] -> CoreExpr -> CoreExpr
eta_expand InScopeSet
in_scope [OneShotInfo]
one_shots CoreExpr
expr) Coercion
co
eta_expand InScopeSet
in_scope [OneShotInfo]
one_shots CoreExpr
orig_expr
= InScopeSet -> [OneShotInfo] -> [TyVar] -> CoreExpr -> CoreExpr
go InScopeSet
in_scope [OneShotInfo]
one_shots [] CoreExpr
orig_expr
where
go :: InScopeSet -> [OneShotInfo] -> [TyVar] -> CoreExpr -> CoreExpr
go InScopeSet
_ [] [TyVar]
_ CoreExpr
_ = CoreExpr
orig_expr
go InScopeSet
in_scope oss :: [OneShotInfo]
oss@(OneShotInfo
_:[OneShotInfo]
oss1) [TyVar]
vs (Lam TyVar
v CoreExpr
body)
| TyVar -> Bool
isTyVar TyVar
v = InScopeSet -> [OneShotInfo] -> [TyVar] -> CoreExpr -> CoreExpr
go (InScopeSet
in_scope InScopeSet -> TyVar -> InScopeSet
`extendInScopeSet` TyVar
v) [OneShotInfo]
oss (TyVar
vTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
vs) CoreExpr
body
| Bool
otherwise = InScopeSet -> [OneShotInfo] -> [TyVar] -> CoreExpr -> CoreExpr
go (InScopeSet
in_scope InScopeSet -> TyVar -> InScopeSet
`extendInScopeSet` TyVar
v) [OneShotInfo]
oss1 (TyVar
vTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
vs) CoreExpr
body
go InScopeSet
in_scope [OneShotInfo]
oss [TyVar]
rev_vs CoreExpr
expr
=
CoreExpr -> CoreExpr
retick (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
EtaInfo -> CoreExpr -> CoreExpr
etaInfoAbs EtaInfo
top_eis (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
InScopeSet -> CoreExpr -> EtaInfo -> CoreExpr
etaInfoApp InScopeSet
in_scope' CoreExpr
sexpr EtaInfo
eis
where
(InScopeSet
in_scope', eis :: EtaInfo
eis@(EI [TyVar]
eta_bndrs MCoercionR
mco))
= [OneShotInfo]
-> SDoc -> InScopeSet -> Type -> (InScopeSet, EtaInfo)
mkEtaWW [OneShotInfo]
oss (CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
orig_expr) InScopeSet
in_scope (HasDebugCallStack => CoreExpr -> Type
CoreExpr -> Type
exprType CoreExpr
expr)
top_bndrs :: [TyVar]
top_bndrs = [TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
rev_vs
top_eis :: EtaInfo
top_eis = [TyVar] -> MCoercionR -> EtaInfo
EI ([TyVar]
top_bndrs [TyVar] -> [TyVar] -> [TyVar]
forall a. [a] -> [a] -> [a]
++ [TyVar]
eta_bndrs) ([TyVar] -> MCoercionR -> MCoercionR
mkPiMCos [TyVar]
top_bndrs MCoercionR
mco)
(CoreExpr
expr', [CoreExpr]
args) = CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
expr
([CoreTickish]
ticks, CoreExpr
expr'') = (CoreTickish -> Bool) -> CoreExpr -> ([CoreTickish], CoreExpr)
forall b.
(CoreTickish -> Bool) -> Expr b -> ([CoreTickish], Expr b)
stripTicksTop CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreExpr
expr'
sexpr :: CoreExpr
sexpr = CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps CoreExpr
expr'' [CoreExpr]
args
retick :: CoreExpr -> CoreExpr
retick CoreExpr
expr = (CoreTickish -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreTickish] -> CoreExpr
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreTickish -> CoreExpr -> CoreExpr
mkTick CoreExpr
expr [CoreTickish]
ticks
data EtaInfo = EI [Var] MCoercionR
instance Outputable EtaInfo where
ppr :: EtaInfo -> SDoc
ppr (EI [TyVar]
vs MCoercionR
mco) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"EI" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [TyVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVar]
vs SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (MCoercionR -> SDoc
forall a. Outputable a => a -> SDoc
ppr MCoercionR
mco)
etaInfoApp :: InScopeSet -> CoreExpr -> EtaInfo -> CoreExpr
etaInfoApp :: InScopeSet -> CoreExpr -> EtaInfo -> CoreExpr
etaInfoApp InScopeSet
in_scope CoreExpr
expr EtaInfo
eis
= Subst -> CoreExpr -> EtaInfo -> CoreExpr
go (InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope) CoreExpr
expr EtaInfo
eis
where
go :: Subst -> CoreExpr -> EtaInfo -> CoreExpr
go :: Subst -> CoreExpr -> EtaInfo -> CoreExpr
go Subst
subst (Tick CoreTickish
t CoreExpr
e) EtaInfo
eis
= CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick (Subst -> CoreTickish -> CoreTickish
substTickish Subst
subst CoreTickish
t) (Subst -> CoreExpr -> EtaInfo -> CoreExpr
go Subst
subst CoreExpr
e EtaInfo
eis)
go Subst
subst (Cast CoreExpr
e Coercion
co) (EI [TyVar]
bs MCoercionR
mco)
= Subst -> CoreExpr -> EtaInfo -> CoreExpr
go Subst
subst CoreExpr
e ([TyVar] -> MCoercionR -> EtaInfo
EI [TyVar]
bs MCoercionR
mco')
where
mco' :: MCoercionR
mco' = MCoercionR -> MCoercionR
checkReflexiveMCo (HasDebugCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
Core.substCo Subst
subst Coercion
co Coercion -> MCoercionR -> MCoercionR
`mkTransMCoR` MCoercionR
mco)
go Subst
subst (Case CoreExpr
e TyVar
b Type
ty [Alt TyVar]
alts) EtaInfo
eis
= CoreExpr -> TyVar -> Type -> [Alt TyVar] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case (HasDebugCallStack => Subst -> CoreExpr -> CoreExpr
Subst -> CoreExpr -> CoreExpr
Core.substExprSC Subst
subst CoreExpr
e) TyVar
b1 Type
ty' [Alt TyVar]
alts'
where
(Subst
subst1, TyVar
b1) = Subst -> TyVar -> (Subst, TyVar)
Core.substBndr Subst
subst TyVar
b
alts' :: [Alt TyVar]
alts' = (Alt TyVar -> Alt TyVar) -> [Alt TyVar] -> [Alt TyVar]
forall a b. (a -> b) -> [a] -> [b]
map Alt TyVar -> Alt TyVar
subst_alt [Alt TyVar]
alts
ty' :: Type
ty' = Type -> EtaInfo -> Type
etaInfoAppTy (Subst -> Type -> Type
substTyUnchecked Subst
subst Type
ty) EtaInfo
eis
subst_alt :: Alt TyVar -> Alt TyVar
subst_alt (Alt AltCon
con [TyVar]
bs CoreExpr
rhs) = AltCon -> [TyVar] -> CoreExpr -> Alt TyVar
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [TyVar]
bs' (Subst -> CoreExpr -> EtaInfo -> CoreExpr
go Subst
subst2 CoreExpr
rhs EtaInfo
eis)
where
(Subst
subst2,[TyVar]
bs') = Subst -> [TyVar] -> (Subst, [TyVar])
forall (f :: * -> *).
Traversable f =>
Subst -> f TyVar -> (Subst, f TyVar)
Core.substBndrs Subst
subst1 [TyVar]
bs
go Subst
subst (Let Bind TyVar
b CoreExpr
e) EtaInfo
eis
| Bool -> Bool
not (Bind TyVar -> Bool
isJoinBind Bind TyVar
b)
= Bind TyVar -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let Bind TyVar
b' (Subst -> CoreExpr -> EtaInfo -> CoreExpr
go Subst
subst' CoreExpr
e EtaInfo
eis)
where
(Subst
subst', Bind TyVar
b') = HasDebugCallStack => Subst -> Bind TyVar -> (Subst, Bind TyVar)
Subst -> Bind TyVar -> (Subst, Bind TyVar)
Core.substBindSC Subst
subst Bind TyVar
b
go Subst
subst (Lam TyVar
v CoreExpr
e) (EI (TyVar
b:[TyVar]
bs) MCoercionR
mco)
| Just (CoreExpr
arg,MCoercionR
mco') <- MCoercionR -> CoreExpr -> Maybe (CoreExpr, MCoercionR)
pushMCoArg MCoercionR
mco (TyVar -> CoreExpr
forall b. TyVar -> Expr b
varToCoreExpr TyVar
b)
= Subst -> CoreExpr -> EtaInfo -> CoreExpr
go (Subst -> TyVar -> CoreExpr -> Subst
Core.extendSubst Subst
subst TyVar
v CoreExpr
arg) CoreExpr
e ([TyVar] -> MCoercionR -> EtaInfo
EI [TyVar]
bs MCoercionR
mco')
go Subst
subst CoreExpr
e (EI [TyVar]
bs MCoercionR
mco) = HasDebugCallStack => Subst -> CoreExpr -> CoreExpr
Subst -> CoreExpr -> CoreExpr
Core.substExprSC Subst
subst CoreExpr
e
CoreExpr -> MCoercionR -> CoreExpr
`mkCastMCo` MCoercionR -> MCoercionR
checkReflexiveMCo MCoercionR
mco
CoreExpr -> [TyVar] -> CoreExpr
forall b. Expr b -> [TyVar] -> Expr b
`mkVarApps` [TyVar]
bs
etaInfoAppTy :: Type -> EtaInfo -> Type
etaInfoAppTy :: Type -> EtaInfo -> Type
etaInfoAppTy Type
ty (EI [TyVar]
bs MCoercionR
mco)
= HasDebugCallStack => SDoc -> Type -> [CoreExpr] -> Type
SDoc -> Type -> [CoreExpr] -> Type
applyTypeToArgs (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"etaInfoAppTy") Type
ty1 ((TyVar -> CoreExpr) -> [TyVar] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map TyVar -> CoreExpr
forall b. TyVar -> Expr b
varToCoreExpr [TyVar]
bs)
where
ty1 :: Type
ty1 = case MCoercionR
mco of
MCoercionR
MRefl -> Type
ty
MCo Coercion
co -> HasDebugCallStack => Coercion -> Type
Coercion -> Type
coercionRKind Coercion
co
etaInfoAbs :: EtaInfo -> CoreExpr -> CoreExpr
etaInfoAbs :: EtaInfo -> CoreExpr -> CoreExpr
etaInfoAbs (EI [TyVar]
bs MCoercionR
mco) CoreExpr
expr = ([TyVar] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [TyVar]
bs CoreExpr
expr) CoreExpr -> MCoercionR -> CoreExpr
`mkCastMCo` MCoercionR -> MCoercionR
mkSymMCo MCoercionR
mco
mkEtaWW
:: [OneShotInfo]
-> SDoc
-> InScopeSet
-> Type
-> (InScopeSet, EtaInfo)
mkEtaWW :: [OneShotInfo]
-> SDoc -> InScopeSet -> Type -> (InScopeSet, EtaInfo)
mkEtaWW [OneShotInfo]
orig_oss SDoc
ppr_orig_expr InScopeSet
in_scope Type
orig_ty
= Int -> [OneShotInfo] -> Subst -> Type -> (InScopeSet, EtaInfo)
go Int
0 [OneShotInfo]
orig_oss Subst
empty_subst Type
orig_ty
where
empty_subst :: Subst
empty_subst = InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope
go :: Int
-> [OneShotInfo]
-> Subst -> Type
-> (InScopeSet, EtaInfo)
go :: Int -> [OneShotInfo] -> Subst -> Type -> (InScopeSet, EtaInfo)
go Int
_ [] Subst
subst Type
_
= (Subst -> InScopeSet
getSubstInScope Subst
subst, [TyVar] -> MCoercionR -> EtaInfo
EI [] MCoercionR
MRefl)
go Int
n oss :: [OneShotInfo]
oss@(OneShotInfo
one_shot:[OneShotInfo]
oss1) Subst
subst Type
ty
| Just (Bndr TyVar
tcv ForAllTyFlag
vis, Type
ty') <- Type -> Maybe (ForAllTyBinder, Type)
splitForAllForAllTyBinder_maybe Type
ty
, (Subst
subst', TyVar
tcv') <- HasDebugCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
Type.substVarBndr Subst
subst TyVar
tcv
, let oss' :: [OneShotInfo]
oss' | TyVar -> Bool
isTyVar TyVar
tcv = [OneShotInfo]
oss
| Bool
otherwise = [OneShotInfo]
oss1
, (InScopeSet
in_scope, EI [TyVar]
bs MCoercionR
mco) <- Int -> [OneShotInfo] -> Subst -> Type -> (InScopeSet, EtaInfo)
go Int
n [OneShotInfo]
oss' Subst
subst' Type
ty'
= (InScopeSet
in_scope, [TyVar] -> MCoercionR -> EtaInfo
EI (TyVar
tcv' TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: [TyVar]
bs) (ForAllTyBinder -> Type -> MCoercionR -> MCoercionR
mkEtaForAllMCo (TyVar -> ForAllTyFlag -> ForAllTyBinder
forall var argf. var -> argf -> VarBndr var argf
Bndr TyVar
tcv' ForAllTyFlag
vis) Type
ty' MCoercionR
mco))
| Just (FunTyFlag
_af, Type
mult, Type
arg_ty, Type
res_ty) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
ty
, HasDebugCallStack => Type -> Bool
Type -> Bool
typeHasFixedRuntimeRep Type
arg_ty
, (Subst
subst', TyVar
eta_id) <- Int -> Subst -> Scaled Type -> (Subst, TyVar)
freshEtaId Int
n Subst
subst (Type -> Type -> Scaled Type
forall a. Type -> a -> Scaled a
Scaled Type
mult Type
arg_ty)
, let eta_id' :: TyVar
eta_id' = TyVar
eta_id TyVar -> OneShotInfo -> TyVar
`setIdOneShotInfo` OneShotInfo
one_shot
, (InScopeSet
in_scope, EI [TyVar]
bs MCoercionR
mco) <- Int -> [OneShotInfo] -> Subst -> Type -> (InScopeSet, EtaInfo)
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [OneShotInfo]
oss1 Subst
subst' Type
res_ty
= (InScopeSet
in_scope, [TyVar] -> MCoercionR -> EtaInfo
EI (TyVar
eta_id' TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: [TyVar]
bs) (TyVar -> MCoercionR -> MCoercionR
mkFunResMCo TyVar
eta_id' MCoercionR
mco))
| Just (Coercion
co, Type
ty') <- Type -> Maybe (Coercion, Type)
topNormaliseNewType_maybe Type
ty
,
let co' :: Coercion
co' = HasDebugCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
Type.substCo Subst
subst Coercion
co
, (InScopeSet
in_scope, EI [TyVar]
bs MCoercionR
mco) <- Int -> [OneShotInfo] -> Subst -> Type -> (InScopeSet, EtaInfo)
go Int
n [OneShotInfo]
oss Subst
subst Type
ty'
= (InScopeSet
in_scope, [TyVar] -> MCoercionR -> EtaInfo
EI [TyVar]
bs (Coercion -> MCoercionR -> MCoercionR
mkTransMCoR Coercion
co' MCoercionR
mco))
| Bool
otherwise
= Bool
-> String -> SDoc -> (InScopeSet, EtaInfo) -> (InScopeSet, EtaInfo)
forall a. HasCallStack => Bool -> String -> SDoc -> a -> a
warnPprTrace Bool
True String
"mkEtaWW" (([OneShotInfo] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [OneShotInfo]
orig_oss SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
orig_ty) SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SDoc
ppr_orig_expr)
(Subst -> InScopeSet
getSubstInScope Subst
subst, [TyVar] -> MCoercionR -> EtaInfo
EI [] MCoercionR
MRefl)
mkEtaForAllMCo :: ForAllTyBinder -> Type -> MCoercion -> MCoercion
mkEtaForAllMCo :: ForAllTyBinder -> Type -> MCoercionR -> MCoercionR
mkEtaForAllMCo (Bndr TyVar
tcv ForAllTyFlag
vis) Type
ty MCoercionR
mco
= case MCoercionR
mco of
MCoercionR
MRefl | ForAllTyFlag
vis ForAllTyFlag -> ForAllTyFlag -> Bool
forall a. Eq a => a -> a -> Bool
== ForAllTyFlag
coreTyLamForAllTyFlag -> MCoercionR
MRefl
| Bool
otherwise -> Coercion -> MCoercionR
mk_fco (Type -> Coercion
mkRepReflCo Type
ty)
MCo Coercion
co -> Coercion -> MCoercionR
mk_fco Coercion
co
where
mk_fco :: Coercion -> MCoercionR
mk_fco Coercion
co = Coercion -> MCoercionR
MCo (HasDebugCallStack =>
TyVar
-> ForAllTyFlag -> ForAllTyFlag -> Coercion -> Coercion -> Coercion
TyVar
-> ForAllTyFlag -> ForAllTyFlag -> Coercion -> Coercion -> Coercion
mkForAllCo TyVar
tcv ForAllTyFlag
vis ForAllTyFlag
coreTyLamForAllTyFlag
(Type -> Coercion
mkNomReflCo (TyVar -> Type
varType TyVar
tcv)) Coercion
co)
tryEtaReduce :: UnVarSet -> [Var] -> CoreExpr -> SubDemand -> Maybe CoreExpr
tryEtaReduce :: UnVarSet -> [TyVar] -> CoreExpr -> SubDemand -> Maybe CoreExpr
tryEtaReduce UnVarSet
rec_ids [TyVar]
bndrs CoreExpr
body SubDemand
eval_sd
= [TyVar] -> CoreExpr -> Coercion -> Maybe CoreExpr
go ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
bndrs) CoreExpr
body (Type -> Coercion
mkRepReflCo (HasDebugCallStack => CoreExpr -> Type
CoreExpr -> Type
exprType CoreExpr
body))
where
incoming_arity :: Int
incoming_arity = (TyVar -> Bool) -> [TyVar] -> Int
forall a. (a -> Bool) -> [a] -> Int
count TyVar -> Bool
isId [TyVar]
bndrs
go :: [Var]
-> CoreExpr
-> Coercion
-> Maybe CoreExpr
go :: [TyVar] -> CoreExpr -> Coercion -> Maybe CoreExpr
go [TyVar]
bs (Cast CoreExpr
e Coercion
co1) Coercion
co2
= [TyVar] -> CoreExpr -> Coercion -> Maybe CoreExpr
go [TyVar]
bs CoreExpr
e (Coercion
co1 Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co2)
go [TyVar]
bs (Tick CoreTickish
t CoreExpr
e) Coercion
co
| CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
t
= (CoreExpr -> CoreExpr) -> Maybe CoreExpr -> Maybe CoreExpr
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
t) (Maybe CoreExpr -> Maybe CoreExpr)
-> Maybe CoreExpr -> Maybe CoreExpr
forall a b. (a -> b) -> a -> b
$ [TyVar] -> CoreExpr -> Coercion -> Maybe CoreExpr
go [TyVar]
bs CoreExpr
e Coercion
co
go (TyVar
b : [TyVar]
bs) (App CoreExpr
fun CoreExpr
arg) Coercion
co
| Just (Coercion
co', [CoreTickish]
ticks) <- TyVar
-> CoreExpr -> Coercion -> Type -> Maybe (Coercion, [CoreTickish])
ok_arg TyVar
b CoreExpr
arg Coercion
co (HasDebugCallStack => CoreExpr -> Type
CoreExpr -> Type
exprType CoreExpr
fun)
= (CoreExpr -> CoreExpr) -> Maybe CoreExpr -> Maybe CoreExpr
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CoreExpr -> [CoreTickish] -> CoreExpr)
-> [CoreTickish] -> CoreExpr -> CoreExpr
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((CoreTickish -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreTickish] -> CoreExpr
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreTickish -> CoreExpr -> CoreExpr
mkTick) [CoreTickish]
ticks) (Maybe CoreExpr -> Maybe CoreExpr)
-> Maybe CoreExpr -> Maybe CoreExpr
forall a b. (a -> b) -> a -> b
$ [TyVar] -> CoreExpr -> Coercion -> Maybe CoreExpr
go [TyVar]
bs CoreExpr
fun Coercion
co'
go [TyVar]
remaining_bndrs CoreExpr
fun Coercion
co
| (TyVar -> Bool) -> [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all TyVar -> Bool
isTyVar [TyVar]
remaining_bndrs
, [TyVar]
remaining_bndrs [TyVar] -> [TyVar] -> Bool
forall a b. [a] -> [b] -> Bool
`ltLength` [TyVar]
bndrs
, CoreExpr -> Bool
ok_fun CoreExpr
fun
, let used_vars :: VarSet
used_vars = CoreExpr -> VarSet
exprFreeVars CoreExpr
fun VarSet -> VarSet -> VarSet
`unionVarSet` Coercion -> VarSet
tyCoVarsOfCo Coercion
co
reduced_bndrs :: VarSet
reduced_bndrs = [TyVar] -> VarSet
mkVarSet ([TyVar] -> [TyVar] -> [TyVar]
forall b a. [b] -> [a] -> [a]
dropList [TyVar]
remaining_bndrs [TyVar]
bndrs)
, VarSet
used_vars VarSet -> VarSet -> Bool
`disjointVarSet` VarSet
reduced_bndrs
= CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just ([TyVar] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
remaining_bndrs) (HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast CoreExpr
fun Coercion
co))
go [TyVar]
_remaining_bndrs CoreExpr
_fun Coercion
_ =
Maybe CoreExpr
forall a. Maybe a
Nothing
ok_fun :: CoreExpr -> Bool
ok_fun (App CoreExpr
fun (Type {})) = CoreExpr -> Bool
ok_fun CoreExpr
fun
ok_fun (Cast CoreExpr
fun Coercion
_) = CoreExpr -> Bool
ok_fun CoreExpr
fun
ok_fun (Tick CoreTickish
_ CoreExpr
expr) = CoreExpr -> Bool
ok_fun CoreExpr
expr
ok_fun (Var TyVar
fun_id) = TyVar -> Bool
is_eta_reduction_sound TyVar
fun_id
ok_fun CoreExpr
_fun = Bool
False
is_eta_reduction_sound :: TyVar -> Bool
is_eta_reduction_sound TyVar
fun
| TyVar
fun TyVar -> UnVarSet -> Bool
`elemUnVarSet` UnVarSet
rec_ids
= Bool
False
| TyVar -> Bool
cantEtaReduceFun TyVar
fun
= Bool
False
| Bool
otherwise
=
TyVar -> Int
fun_arity TyVar
fun Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
incoming_arity
Bool -> Bool -> Bool
|| Int -> Bool
all_calls_with_arity Int
incoming_arity
Bool -> Bool -> Bool
|| (TyVar -> Bool) -> [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all TyVar -> Bool
ok_lam [TyVar]
bndrs
all_calls_with_arity :: Int -> Bool
all_calls_with_arity Int
n = Card -> Bool
isStrict ((Card, SubDemand) -> Card
forall a b. (a, b) -> a
fst ((Card, SubDemand) -> Card) -> (Card, SubDemand) -> Card
forall a b. (a -> b) -> a -> b
$ Int -> SubDemand -> (Card, SubDemand)
peelManyCalls Int
n SubDemand
eval_sd)
fun_arity :: TyVar -> Int
fun_arity TyVar
fun
| Int
arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int
arity
| Unfolding -> Bool
isEvaldUnfolding (IdUnfoldingFun
idUnfolding TyVar
fun) = Int
1
| Bool
otherwise = Int
0
where
arity :: Int
arity = TyVar -> Int
idArity TyVar
fun
ok_lam :: TyVar -> Bool
ok_lam TyVar
v = TyVar -> Bool
isTyVar TyVar
v Bool -> Bool -> Bool
|| TyVar -> Bool
isEvVar TyVar
v
ok_arg :: Var
-> CoreExpr
-> Coercion
-> Type
-> Maybe (Coercion
, [CoreTickish])
ok_arg :: TyVar
-> CoreExpr -> Coercion -> Type -> Maybe (Coercion, [CoreTickish])
ok_arg TyVar
bndr (Type Type
arg_ty) Coercion
co Type
fun_ty
| Just TyVar
tv <- Type -> Maybe TyVar
getTyVar_maybe Type
arg_ty
, TyVar
bndr TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
tv = case Type -> Maybe (ForAllTyBinder, Type)
splitForAllForAllTyBinder_maybe Type
fun_ty of
Just (Bndr TyVar
_ ForAllTyFlag
vis, Type
_) -> (Coercion, [CoreTickish]) -> Maybe (Coercion, [CoreTickish])
forall a. a -> Maybe a
Just (Coercion
fco, [])
where !fco :: Coercion
fco = HasDebugCallStack =>
TyVar
-> ForAllTyFlag -> ForAllTyFlag -> Coercion -> Coercion -> Coercion
TyVar
-> ForAllTyFlag -> ForAllTyFlag -> Coercion -> Coercion -> Coercion
mkForAllCo TyVar
tv ForAllTyFlag
vis ForAllTyFlag
coreTyLamForAllTyFlag Coercion
kco Coercion
co
kco :: Coercion
kco = Type -> Coercion
mkNomReflCo (TyVar -> Type
tyVarKind TyVar
tv)
Maybe (ForAllTyBinder, Type)
Nothing -> String -> SDoc -> Maybe (Coercion, [CoreTickish])
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"tryEtaReduce: type arg to non-forall type"
(String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"fun:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
bndr
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"arg:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
arg_ty
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"fun_ty:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
fun_ty)
ok_arg TyVar
bndr (Var TyVar
v) Coercion
co Type
fun_ty
| TyVar
bndr TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
v
, let mult :: Type
mult = TyVar -> Type
idMult TyVar
bndr
, Just (FunTyFlag
_af, Type
fun_mult, Type
_, Type
_) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
fun_ty
, Type
mult HasCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`eqType` Type
fun_mult
= (Coercion, [CoreTickish]) -> Maybe (Coercion, [CoreTickish])
forall a. a -> Maybe a
Just (Role -> TyVar -> Coercion -> Coercion
mkFunResCo Role
Representational TyVar
bndr Coercion
co, [])
ok_arg TyVar
bndr (Cast CoreExpr
e Coercion
co_arg) Coercion
co Type
fun_ty
| ([CoreTickish]
ticks, Var TyVar
v) <- (CoreTickish -> Bool) -> CoreExpr -> ([CoreTickish], CoreExpr)
forall b.
(CoreTickish -> Bool) -> Expr b -> ([CoreTickish], Expr b)
stripTicksTop CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreExpr
e
, Just (FunTyFlag
_, Type
fun_mult, Type
_, Type
_) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
fun_ty
, TyVar
bndr TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
v
, Type
fun_mult HasCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`eqType` TyVar -> Type
idMult TyVar
bndr
= (Coercion, [CoreTickish]) -> Maybe (Coercion, [CoreTickish])
forall a. a -> Maybe a
Just (HasDebugCallStack =>
Role -> Coercion -> Coercion -> Coercion -> Coercion
Role -> Coercion -> Coercion -> Coercion -> Coercion
mkFunCoNoFTF Role
Representational (Type -> Coercion
multToCo Type
fun_mult) (Coercion -> Coercion
mkSymCo Coercion
co_arg) Coercion
co, [CoreTickish]
ticks)
ok_arg TyVar
bndr (Tick CoreTickish
t CoreExpr
arg) Coercion
co Type
fun_ty
| CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
t, Just (Coercion
co', [CoreTickish]
ticks) <- TyVar
-> CoreExpr -> Coercion -> Type -> Maybe (Coercion, [CoreTickish])
ok_arg TyVar
bndr CoreExpr
arg Coercion
co Type
fun_ty
= (Coercion, [CoreTickish]) -> Maybe (Coercion, [CoreTickish])
forall a. a -> Maybe a
Just (Coercion
co', CoreTickish
tCoreTickish -> [CoreTickish] -> [CoreTickish]
forall a. a -> [a] -> [a]
:[CoreTickish]
ticks)
ok_arg TyVar
_ CoreExpr
_ Coercion
_ Type
_ = Maybe (Coercion, [CoreTickish])
forall a. Maybe a
Nothing
cantEtaReduceFun :: Id -> Bool
cantEtaReduceFun :: TyVar -> Bool
cantEtaReduceFun TyVar
fun
= TyVar -> Bool
hasNoBinding TyVar
fun
Bool -> Bool -> Bool
|| TyVar -> Bool
isJoinId TyVar
fun
Bool -> Bool -> Bool
|| (Maybe [CbvMark] -> Bool
forall a. Maybe a -> Bool
isJust (TyVar -> Maybe [CbvMark]
idCbvMarks_maybe TyVar
fun))
pushCoArgs :: CoercionR -> [CoreArg] -> Maybe ([CoreArg], MCoercion)
pushCoArgs :: Coercion -> [CoreExpr] -> Maybe ([CoreExpr], MCoercionR)
pushCoArgs Coercion
co [] = ([CoreExpr], MCoercionR) -> Maybe ([CoreExpr], MCoercionR)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return ([], Coercion -> MCoercionR
MCo Coercion
co)
pushCoArgs Coercion
co (CoreExpr
arg:[CoreExpr]
args) = do { (arg', m_co1) <- Coercion -> CoreExpr -> Maybe (CoreExpr, MCoercionR)
pushCoArg Coercion
co CoreExpr
arg
; case m_co1 of
MCo Coercion
co1 -> do { (args', m_co2) <- Coercion -> [CoreExpr] -> Maybe ([CoreExpr], MCoercionR)
pushCoArgs Coercion
co1 [CoreExpr]
args
; return (arg':args', m_co2) }
MCoercionR
MRefl -> ([CoreExpr], MCoercionR) -> Maybe ([CoreExpr], MCoercionR)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr
arg'CoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args, MCoercionR
MRefl) }
pushMCoArg :: MCoercionR -> CoreArg -> Maybe (CoreArg, MCoercion)
pushMCoArg :: MCoercionR -> CoreExpr -> Maybe (CoreExpr, MCoercionR)
pushMCoArg MCoercionR
MRefl CoreExpr
arg = (CoreExpr, MCoercionR) -> Maybe (CoreExpr, MCoercionR)
forall a. a -> Maybe a
Just (CoreExpr
arg, MCoercionR
MRefl)
pushMCoArg (MCo Coercion
co) CoreExpr
arg = Coercion -> CoreExpr -> Maybe (CoreExpr, MCoercionR)
pushCoArg Coercion
co CoreExpr
arg
pushCoArg :: CoercionR -> CoreArg -> Maybe (CoreArg, MCoercion)
pushCoArg :: Coercion -> CoreExpr -> Maybe (CoreExpr, MCoercionR)
pushCoArg Coercion
co CoreExpr
arg
| Type Type
ty <- CoreExpr
arg
= do { (ty', m_co') <- Coercion -> Type -> Maybe (Type, MCoercionR)
pushCoTyArg Coercion
co Type
ty
; return (Type ty', m_co') }
| Bool
otherwise
= do { (arg_mco, m_co') <- Coercion -> Maybe (MCoercionR, MCoercionR)
pushCoValArg Coercion
co
; let arg_mco' = MCoercionR -> MCoercionR
checkReflexiveMCo MCoercionR
arg_mco
; return (arg `mkCastMCo` arg_mco', m_co') }
pushCoTyArg :: CoercionR -> Type -> Maybe (Type, MCoercionR)
pushCoTyArg :: Coercion -> Type -> Maybe (Type, MCoercionR)
pushCoTyArg Coercion
co Type
ty
| Coercion -> Bool
isReflCo Coercion
co
= (Type, MCoercionR) -> Maybe (Type, MCoercionR)
forall a. a -> Maybe a
Just (Type
ty, MCoercionR
MRefl)
| Type -> Bool
isForAllTy_ty Type
tyL
= Bool
-> SDoc -> Maybe (Type, MCoercionR) -> Maybe (Type, MCoercionR)
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Type -> Bool
isForAllTy_ty Type
tyR) (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
ty) (Maybe (Type, MCoercionR) -> Maybe (Type, MCoercionR))
-> Maybe (Type, MCoercionR) -> Maybe (Type, MCoercionR)
forall a b. (a -> b) -> a -> b
$
(Type, MCoercionR) -> Maybe (Type, MCoercionR)
forall a. a -> Maybe a
Just (Type
ty Type -> Coercion -> Type
`mkCastTy` Coercion
co1, Coercion -> MCoercionR
MCo Coercion
co2)
| Bool
otherwise
= Maybe (Type, MCoercionR)
forall a. Maybe a
Nothing
where
Pair Type
tyL Type
tyR = HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
co1 :: Coercion
co1 = Coercion -> Coercion
mkSymCo (HasDebugCallStack => CoSel -> Coercion -> Coercion
CoSel -> Coercion -> Coercion
mkSelCo CoSel
SelForAll Coercion
co)
co2 :: Coercion
co2 = Coercion -> Coercion -> Coercion
mkInstCo Coercion
co (Role -> Type -> Coercion -> Coercion
mkGReflLeftCo Role
Nominal Type
ty Coercion
co1)
pushCoValArg :: CoercionR -> Maybe (MCoercionR, MCoercionR)
pushCoValArg :: Coercion -> Maybe (MCoercionR, MCoercionR)
pushCoValArg Coercion
co
| Coercion -> Bool
isReflCo Coercion
co
= (MCoercionR, MCoercionR) -> Maybe (MCoercionR, MCoercionR)
forall a. a -> Maybe a
Just (MCoercionR
MRefl, MCoercionR
MRefl)
| Type -> Bool
isFunTy Type
tyL
, (Coercion
_, Coercion
co1, Coercion
co2) <- HasDebugCallStack => Coercion -> (Coercion, Coercion, Coercion)
Coercion -> (Coercion, Coercion, Coercion)
decomposeFunCo Coercion
co
, HasDebugCallStack => Type -> Bool
Type -> Bool
typeHasFixedRuntimeRep Type
new_arg_ty
= Bool
-> SDoc
-> Maybe (MCoercionR, MCoercionR)
-> Maybe (MCoercionR, MCoercionR)
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Type -> Bool
isFunTy Type
tyL Bool -> Bool -> Bool
&& Type -> Bool
isFunTy Type
tyR)
([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"co:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"old_arg_ty:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
old_arg_ty
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"new_arg_ty:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
new_arg_ty ]) (Maybe (MCoercionR, MCoercionR) -> Maybe (MCoercionR, MCoercionR))
-> Maybe (MCoercionR, MCoercionR) -> Maybe (MCoercionR, MCoercionR)
forall a b. (a -> b) -> a -> b
$
(MCoercionR, MCoercionR) -> Maybe (MCoercionR, MCoercionR)
forall a. a -> Maybe a
Just (Coercion -> MCoercionR
coToMCo (Coercion -> Coercion
mkSymCo Coercion
co1), Coercion -> MCoercionR
coToMCo Coercion
co2)
| Bool
otherwise
= Maybe (MCoercionR, MCoercionR)
forall a. Maybe a
Nothing
where
old_arg_ty :: Type
old_arg_ty = HasDebugCallStack => Type -> Type
Type -> Type
funArgTy Type
tyR
new_arg_ty :: Type
new_arg_ty = HasDebugCallStack => Type -> Type
Type -> Type
funArgTy Type
tyL
Pair Type
tyL Type
tyR = HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
pushCoercionIntoLambda
:: HasDebugCallStack => InScopeSet -> Var -> CoreExpr -> CoercionR -> Maybe (Var, CoreExpr)
pushCoercionIntoLambda :: HasDebugCallStack =>
InScopeSet
-> TyVar -> CoreExpr -> Coercion -> Maybe (TyVar, CoreExpr)
pushCoercionIntoLambda InScopeSet
in_scope TyVar
x CoreExpr
e Coercion
co
| Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Bool -> Bool
not (TyVar -> Bool
isTyVar TyVar
x) Bool -> Bool -> Bool
&& Bool -> Bool
not (TyVar -> Bool
isCoVar TyVar
x)) Bool
True
, Pair Type
s1s2 Type
t1t2 <- HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
, Just {} <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
s1s2
, Just (FunTyFlag
_, Type
w1, Type
t1,Type
_t2) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
t1t2
, (Coercion
_, Coercion
co1, Coercion
co2) <- HasDebugCallStack => Coercion -> (Coercion, Coercion, Coercion)
Coercion -> (Coercion, Coercion, Coercion)
decomposeFunCo Coercion
co
, HasDebugCallStack => Type -> Bool
Type -> Bool
typeHasFixedRuntimeRep Type
t1
= let
x' :: TyVar
x' = TyVar
x TyVar -> Type -> TyVar
`setIdType` Type
t1 TyVar -> Type -> TyVar
`setIdMult` Type
w1
in_scope' :: InScopeSet
in_scope' = InScopeSet
in_scope InScopeSet -> TyVar -> InScopeSet
`extendInScopeSet` TyVar
x'
subst :: Subst
subst = Subst -> TyVar -> CoreExpr -> Subst
extendIdSubst (InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope')
TyVar
x
(HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast (TyVar -> CoreExpr
forall b. TyVar -> Expr b
Var TyVar
x') (Coercion -> Coercion
mkSymCo Coercion
co1))
in (TyVar, CoreExpr) -> Maybe (TyVar, CoreExpr)
forall a. a -> Maybe a
Just (TyVar
x', HasDebugCallStack => Subst -> CoreExpr -> CoreExpr
Subst -> CoreExpr -> CoreExpr
substExpr Subst
subst CoreExpr
e HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion
co2)
| Bool
otherwise
= Maybe (TyVar, CoreExpr)
forall a. Maybe a
Nothing
pushCoDataCon :: DataCon -> [CoreExpr] -> MCoercion
-> Maybe (DataCon
, [Type]
, [CoreExpr])
pushCoDataCon :: DataCon
-> [CoreExpr] -> MCoercionR -> Maybe (DataCon, [Type], [CoreExpr])
pushCoDataCon DataCon
dc [CoreExpr]
dc_args MCoercionR
MRefl = (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a. a -> Maybe a
Just ((DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr]))
-> (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a b. (a -> b) -> a -> b
$! (DataCon -> [CoreExpr] -> (DataCon, [Type], [CoreExpr])
push_dc_refl DataCon
dc [CoreExpr]
dc_args)
pushCoDataCon DataCon
dc [CoreExpr]
dc_args (MCo Coercion
co) = DataCon
-> [CoreExpr]
-> Coercion
-> Pair Type
-> Maybe (DataCon, [Type], [CoreExpr])
push_dc_gen DataCon
dc [CoreExpr]
dc_args Coercion
co (HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co)
push_dc_refl :: DataCon -> [CoreExpr] -> (DataCon, [Type], [CoreExpr])
push_dc_refl :: DataCon -> [CoreExpr] -> (DataCon, [Type], [CoreExpr])
push_dc_refl DataCon
dc [CoreExpr]
dc_args
= (DataCon
dc, (CoreExpr -> Type) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Type
exprToType [CoreExpr]
univ_ty_args, [CoreExpr]
rest_args)
where
!([CoreExpr]
univ_ty_args, [CoreExpr]
rest_args) = [TyVar] -> [CoreExpr] -> ([CoreExpr], [CoreExpr])
forall b a. [b] -> [a] -> ([a], [a])
splitAtList (DataCon -> [TyVar]
dataConUnivTyVars DataCon
dc) [CoreExpr]
dc_args
push_dc_gen :: DataCon -> [CoreExpr] -> Coercion -> Pair Type
-> Maybe (DataCon, [Type], [CoreExpr])
push_dc_gen :: DataCon
-> [CoreExpr]
-> Coercion
-> Pair Type
-> Maybe (DataCon, [Type], [CoreExpr])
push_dc_gen DataCon
dc [CoreExpr]
dc_args Coercion
co (Pair Type
from_ty Type
to_ty)
| Type
from_ty HasCallStack => Type -> Type -> Bool
Type -> Type -> Bool
`eqType` Type
to_ty
= (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a. a -> Maybe a
Just ((DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr]))
-> (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a b. (a -> b) -> a -> b
$! (DataCon -> [CoreExpr] -> (DataCon, [Type], [CoreExpr])
push_dc_refl DataCon
dc [CoreExpr]
dc_args)
| Just (TyCon
to_tc, [Type]
to_tc_arg_tys) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
to_ty
, TyCon
to_tc TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== DataCon -> TyCon
dataConTyCon DataCon
dc
= let
tc_arity :: Int
tc_arity = TyCon -> Int
tyConArity TyCon
to_tc
dc_univ_tyvars :: [TyVar]
dc_univ_tyvars = DataCon -> [TyVar]
dataConUnivTyVars DataCon
dc
dc_ex_tcvars :: [TyVar]
dc_ex_tcvars = DataCon -> [TyVar]
dataConExTyCoVars DataCon
dc
arg_tys :: [Scaled Type]
arg_tys = DataCon -> [Scaled Type]
dataConRepArgTys DataCon
dc
non_univ_args :: [CoreExpr]
non_univ_args = [TyVar] -> [CoreExpr] -> [CoreExpr]
forall b a. [b] -> [a] -> [a]
dropList [TyVar]
dc_univ_tyvars [CoreExpr]
dc_args
([CoreExpr]
ex_args, [CoreExpr]
val_args) = [TyVar] -> [CoreExpr] -> ([CoreExpr], [CoreExpr])
forall b a. [b] -> [a] -> ([a], [a])
splitAtList [TyVar]
dc_ex_tcvars [CoreExpr]
non_univ_args
omegas :: [Coercion]
omegas = Int -> Coercion -> Infinite Role -> [Coercion]
decomposeCo Int
tc_arity Coercion
co (TyCon -> Infinite Role
tyConRolesRepresentational TyCon
to_tc)
(Type -> Coercion
psi_subst, [Type]
to_ex_arg_tys)
= Role
-> [TyVar]
-> [Coercion]
-> [TyVar]
-> [Type]
-> (Type -> Coercion, [Type])
liftCoSubstWithEx Role
Representational
[TyVar]
dc_univ_tyvars
[Coercion]
omegas
[TyVar]
dc_ex_tcvars
((CoreExpr -> Type) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Type
exprToType [CoreExpr]
ex_args)
new_val_args :: [CoreExpr]
new_val_args = (Type -> CoreExpr -> CoreExpr)
-> [Type] -> [CoreExpr] -> [CoreExpr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Type -> CoreExpr -> CoreExpr
cast_arg ((Scaled Type -> Type) -> [Scaled Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Scaled Type -> Type
forall a. Scaled a -> a
scaledThing [Scaled Type]
arg_tys) [CoreExpr]
val_args
cast_arg :: Type -> CoreExpr -> CoreExpr
cast_arg Type
arg_ty CoreExpr
arg = HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast CoreExpr
arg (Type -> Coercion
psi_subst Type
arg_ty)
to_ex_args :: [CoreExpr]
to_ex_args = (Type -> CoreExpr) -> [Type] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map Type -> CoreExpr
forall b. Type -> Expr b
Type [Type]
to_ex_arg_tys
dump_doc :: SDoc
dump_doc = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc, [TyVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVar]
dc_univ_tyvars, [TyVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [TyVar]
dc_ex_tcvars,
[Scaled Type] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Scaled Type]
arg_tys, [CoreExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
dc_args,
[CoreExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
ex_args, [CoreExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
val_args, Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
from_ty, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
to_ty, TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
to_tc
, Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Type -> SDoc) -> Type -> SDoc
forall a b. (a -> b) -> a -> b
$ TyCon -> [Type] -> Type
mkTyConApp TyCon
to_tc ((CoreExpr -> Type) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Type
exprToType ([CoreExpr] -> [Type]) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> a -> b
$ [TyVar] -> [CoreExpr] -> [CoreExpr]
forall b a. [b] -> [a] -> [a]
takeList [TyVar]
dc_univ_tyvars [CoreExpr]
dc_args) ]
in
Bool
-> SDoc
-> Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (HasCallStack => Type -> Type -> Bool
Type -> Type -> Bool
eqType Type
from_ty (TyCon -> [Type] -> Type
mkTyConApp TyCon
to_tc ((CoreExpr -> Type) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Type
exprToType ([CoreExpr] -> [Type]) -> [CoreExpr] -> [Type]
forall a b. (a -> b) -> a -> b
$ [TyVar] -> [CoreExpr] -> [CoreExpr]
forall b a. [b] -> [a] -> [a]
takeList [TyVar]
dc_univ_tyvars [CoreExpr]
dc_args))) SDoc
dump_doc (Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr]))
-> Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a b. (a -> b) -> a -> b
$
Bool
-> SDoc
-> Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr ([CoreExpr] -> [Scaled Type] -> Bool
forall a b. [a] -> [b] -> Bool
equalLength [CoreExpr]
val_args [Scaled Type]
arg_tys) SDoc
dump_doc (Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr]))
-> Maybe (DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a b. (a -> b) -> a -> b
$
(DataCon, [Type], [CoreExpr])
-> Maybe (DataCon, [Type], [CoreExpr])
forall a. a -> Maybe a
Just (DataCon
dc, [Type]
to_tc_arg_tys, [CoreExpr]
to_ex_args [CoreExpr] -> [CoreExpr] -> [CoreExpr]
forall a. [a] -> [a] -> [a]
++ [CoreExpr]
new_val_args)
| Bool
otherwise
= Maybe (DataCon, [Type], [CoreExpr])
forall a. Maybe a
Nothing
collectBindersPushingCo :: CoreExpr -> ([Var], CoreExpr)
collectBindersPushingCo :: CoreExpr -> ([TyVar], CoreExpr)
collectBindersPushingCo CoreExpr
e
= [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go [] CoreExpr
e
where
go :: [Var] -> CoreExpr -> ([Var], CoreExpr)
go :: [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go [TyVar]
bs (Lam TyVar
b CoreExpr
e) = [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go (TyVar
bTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
bs) CoreExpr
e
go [TyVar]
bs (Cast CoreExpr
e Coercion
co) = [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c [TyVar]
bs CoreExpr
e Coercion
co
go [TyVar]
bs CoreExpr
e = ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
bs, CoreExpr
e)
go_c :: [Var] -> CoreExpr -> CoercionR -> ([Var], CoreExpr)
go_c :: [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c [TyVar]
bs (Cast CoreExpr
e Coercion
co1) Coercion
co2 = [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c [TyVar]
bs CoreExpr
e (Coercion
co1 Coercion -> Coercion -> Coercion
`mkTransCo` Coercion
co2)
go_c [TyVar]
bs (Lam TyVar
b CoreExpr
e) Coercion
co = [TyVar] -> TyVar -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_lam [TyVar]
bs TyVar
b CoreExpr
e Coercion
co
go_c [TyVar]
bs CoreExpr
e Coercion
co = ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
bs, HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast CoreExpr
e Coercion
co)
go_lam :: [Var] -> Var -> CoreExpr -> CoercionR -> ([Var], CoreExpr)
go_lam :: [TyVar] -> TyVar -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_lam [TyVar]
bs TyVar
b CoreExpr
e Coercion
co
| TyVar -> Bool
isTyVar TyVar
b
, let Pair Type
tyL Type
tyR = HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
, Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Type -> Bool
isForAllTy_ty Type
tyL) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$
Type -> Bool
isForAllTy_ty Type
tyR
, Coercion -> Bool
isReflCo (HasDebugCallStack => CoSel -> Coercion -> Coercion
CoSel -> Coercion -> Coercion
mkSelCo CoSel
SelForAll Coercion
co)
= [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c (TyVar
bTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
bs) CoreExpr
e (Coercion -> Coercion -> Coercion
mkInstCo Coercion
co (Type -> Coercion
mkNomReflCo (TyVar -> Type
mkTyVarTy TyVar
b)))
| TyVar -> Bool
isCoVar TyVar
b
, let Pair Type
tyL Type
tyR = HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
, Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Type -> Bool
isForAllTy_co Type
tyL) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$
Type -> Bool
isForAllTy_co Type
tyR
, Coercion -> Bool
isReflCo (HasDebugCallStack => CoSel -> Coercion -> Coercion
CoSel -> Coercion -> Coercion
mkSelCo CoSel
SelForAll Coercion
co)
, let cov :: Coercion
cov = TyVar -> Coercion
mkCoVarCo TyVar
b
= [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c (TyVar
bTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
bs) CoreExpr
e (Coercion -> Coercion -> Coercion
mkInstCo Coercion
co (Type -> Coercion
mkNomReflCo (Coercion -> Type
mkCoercionTy Coercion
cov)))
| TyVar -> Bool
isId TyVar
b
, let Pair Type
tyL Type
tyR = HasDebugCallStack => Coercion -> Pair Type
Coercion -> Pair Type
coercionKind Coercion
co
, Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Type -> Bool
isFunTy Type
tyL) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Type -> Bool
isFunTy Type
tyR
, (Coercion
co_mult, Coercion
co_arg, Coercion
co_res) <- HasDebugCallStack => Coercion -> (Coercion, Coercion, Coercion)
Coercion -> (Coercion, Coercion, Coercion)
decomposeFunCo Coercion
co
, Coercion -> Bool
isReflCo Coercion
co_mult
, Coercion -> Bool
isReflCo Coercion
co_arg
= [TyVar] -> CoreExpr -> Coercion -> ([TyVar], CoreExpr)
go_c (TyVar
bTyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
:[TyVar]
bs) CoreExpr
e Coercion
co_res
| Bool
otherwise = ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
bs, HasDebugCallStack => CoreExpr -> Coercion -> CoreExpr
CoreExpr -> Coercion -> CoreExpr
mkCast (TyVar -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam TyVar
b CoreExpr
e) Coercion
co)
etaExpandToJoinPoint :: JoinArity -> CoreExpr -> ([CoreBndr], CoreExpr)
etaExpandToJoinPoint :: Int -> CoreExpr -> ([TyVar], CoreExpr)
etaExpandToJoinPoint Int
join_arity CoreExpr
expr
= Int -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go Int
join_arity [] CoreExpr
expr
where
go :: Int -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go Int
0 [TyVar]
rev_bs CoreExpr
e = ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
rev_bs, CoreExpr
e)
go Int
n [TyVar]
rev_bs (Lam TyVar
b CoreExpr
e) = Int -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (TyVar
b TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: [TyVar]
rev_bs) CoreExpr
e
go Int
n [TyVar]
rev_bs CoreExpr
e = case Int -> CoreExpr -> ([TyVar], CoreExpr)
etaBodyForJoinPoint Int
n CoreExpr
e of
([TyVar]
bs, CoreExpr
e') -> ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
rev_bs [TyVar] -> [TyVar] -> [TyVar]
forall a. [a] -> [a] -> [a]
++ [TyVar]
bs, CoreExpr
e')
etaExpandToJoinPointRule :: JoinArity -> CoreRule -> CoreRule
etaExpandToJoinPointRule :: Int -> CoreRule -> CoreRule
etaExpandToJoinPointRule Int
_ rule :: CoreRule
rule@(BuiltinRule {})
= Bool -> String -> SDoc -> CoreRule -> CoreRule
forall a. HasCallStack => Bool -> String -> SDoc -> a -> a
warnPprTrace Bool
True String
"Can't eta-expand built-in rule:" (CoreRule -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreRule
rule)
CoreRule
rule
etaExpandToJoinPointRule Int
join_arity rule :: CoreRule
rule@(Rule { ru_bndrs :: CoreRule -> [TyVar]
ru_bndrs = [TyVar]
bndrs, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs
, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args })
| Int
need_args Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
= CoreRule
rule
| Int
need_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
= String -> SDoc -> CoreRule
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"etaExpandToJoinPointRule" (Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
join_arity SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ CoreRule -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreRule
rule)
| Bool
otherwise
= CoreRule
rule { ru_bndrs = bndrs ++ new_bndrs
, ru_args = args ++ new_args
, ru_rhs = new_rhs }
where
need_args :: Int
need_args = Int
join_arity Int -> Int -> Int
forall a. Num a => a -> a -> a
- [CoreExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CoreExpr]
args
([TyVar]
new_bndrs, CoreExpr
new_rhs) = Int -> CoreExpr -> ([TyVar], CoreExpr)
etaBodyForJoinPoint Int
need_args CoreExpr
rhs
new_args :: [CoreExpr]
new_args = [TyVar] -> [CoreExpr]
forall b. [TyVar] -> [Expr b]
varsToCoreExprs [TyVar]
new_bndrs
etaBodyForJoinPoint :: Int -> CoreExpr -> ([CoreBndr], CoreExpr)
etaBodyForJoinPoint :: Int -> CoreExpr -> ([TyVar], CoreExpr)
etaBodyForJoinPoint Int
need_args CoreExpr
body
= Int -> Type -> Subst -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go Int
need_args Type
body_ty (InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope) [] CoreExpr
body
where
go :: Int -> Type -> Subst -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go Int
0 Type
_ Subst
_ [TyVar]
rev_bs CoreExpr
e
= ([TyVar] -> [TyVar]
forall a. [a] -> [a]
reverse [TyVar]
rev_bs, CoreExpr
e)
go Int
n Type
ty Subst
subst [TyVar]
rev_bs CoreExpr
e
| Just (TyVar
tv, Type
res_ty) <- Type -> Maybe (TyVar, Type)
splitForAllTyCoVar_maybe Type
ty
, let (Subst
subst', TyVar
tv') = HasDebugCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
substVarBndr Subst
subst TyVar
tv
= Int -> Type -> Subst -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Type
res_ty Subst
subst' (TyVar
tv' TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: [TyVar]
rev_bs) (CoreExpr
e CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
`App` TyVar -> CoreExpr
forall b. TyVar -> Expr b
varToCoreExpr TyVar
tv')
| Just (FunTyFlag
_, Type
mult, Type
arg_ty, Type
res_ty) <- Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
ty
, let (Subst
subst', TyVar
b) = Int -> Subst -> Scaled Type -> (Subst, TyVar)
freshEtaId Int
n Subst
subst (Type -> Type -> Scaled Type
forall a. Type -> a -> Scaled a
Scaled Type
mult Type
arg_ty)
= Int -> Type -> Subst -> [TyVar] -> CoreExpr -> ([TyVar], CoreExpr)
go (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Type
res_ty Subst
subst' (TyVar
b TyVar -> [TyVar] -> [TyVar]
forall a. a -> [a] -> [a]
: [TyVar]
rev_bs) (CoreExpr
e CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
`App` TyVar -> CoreExpr
forall b. TyVar -> Expr b
varToCoreExpr TyVar
b)
| Bool
otherwise
= String -> SDoc -> ([TyVar], CoreExpr)
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"etaBodyForJoinPoint" (SDoc -> ([TyVar], CoreExpr)) -> SDoc -> ([TyVar], CoreExpr)
forall a b. (a -> b) -> a -> b
$ Int -> SDoc
forall doc. IsLine doc => Int -> doc
int Int
need_args SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
body SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => CoreExpr -> Type
CoreExpr -> Type
exprType CoreExpr
body)
body_ty :: Type
body_ty = HasDebugCallStack => CoreExpr -> Type
CoreExpr -> Type
exprType CoreExpr
body
in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet (CoreExpr -> VarSet
exprFreeVars CoreExpr
body VarSet -> VarSet -> VarSet
`unionVarSet` Type -> VarSet
tyCoVarsOfType Type
body_ty)
freshEtaId :: Int -> Subst -> Scaled Type -> (Subst, Id)
freshEtaId :: Int -> Subst -> Scaled Type -> (Subst, TyVar)
freshEtaId Int
n Subst
subst Scaled Type
ty
= (Subst
subst', TyVar
eta_id')
where
Scaled Type
mult' Type
ty' = HasDebugCallStack => Subst -> Scaled Type -> Scaled Type
Subst -> Scaled Type -> Scaled Type
Type.substScaledTyUnchecked Subst
subst Scaled Type
ty
eta_id' :: TyVar
eta_id' = InScopeSet -> TyVar -> TyVar
uniqAway (Subst -> InScopeSet
getSubstInScope Subst
subst) (TyVar -> TyVar) -> TyVar -> TyVar
forall a b. (a -> b) -> a -> b
$
FastString -> Unique -> Type -> Type -> TyVar
mkSysLocalOrCoVar (String -> FastString
fsLit String
"eta") (Int -> Unique
mkBuiltinUnique Int
n) Type
mult' Type
ty'
subst' :: Subst
subst' = Subst -> TyVar -> Subst
extendSubstInScope Subst
subst TyVar
eta_id'