{-# LANGUAGE CPP #-}
module GHC.Core.Opt.Simplify.Utils (
mkLam, mkCase, prepareAlts, tryEtaExpandRhs,
preInlineUnconditionally, postInlineUnconditionally,
activeUnfolding, activeRule,
getUnfoldingInRuleMatch,
simplEnvForGHCi, updModeForStableUnfoldings, updModeForRules,
SimplCont(..), DupFlag(..), StaticEnv,
isSimplified, contIsStop,
contIsDupable, contResultType, contHoleType, contHoleScaling,
contIsTrivial, contArgs,
countArgs,
mkBoringStop, mkRhsStop, mkLazyArgStop, contIsRhsOrArg,
interestingCallContext,
ArgInfo(..), ArgSpec(..), mkArgInfo,
addValArgTo, addCastTo, addTyArgTo,
argInfoExpr, argInfoAppArgs, pushSimplifiedArgs,
isStrictArgInfo, lazyArgContext,
abstractFloats,
isExitJoinId
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core.Opt.Simplify.Env
import GHC.Core.Opt.Monad ( SimplMode(..), Tick(..) )
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Core
import qualified GHC.Core.Subst
import GHC.Core.Ppr
import GHC.Core.TyCo.Ppr ( pprParendType )
import GHC.Core.FVs
import GHC.Core.Utils
import GHC.Core.Opt.Arity
import GHC.Core.Unfold
import GHC.Core.Unfold.Make
import GHC.Types.Name
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Types.Demand
import GHC.Types.Var.Set
import GHC.Types.Basic
import GHC.Core.Opt.Simplify.Monad
import GHC.Core.Type hiding( substTy )
import GHC.Core.Coercion hiding( substCo )
import GHC.Core.DataCon ( dataConWorkId, isNullaryRepDataCon )
import GHC.Core.Multiplicity
import GHC.Utils.Misc
import GHC.Data.OrdList ( isNilOL )
import GHC.Utils.Monad
import GHC.Utils.Outputable
import GHC.Utils.Logger
import GHC.Utils.Panic
import GHC.Core.Opt.ConstantFold
import GHC.Data.FastString ( fsLit )
import Control.Monad ( when )
import Data.List ( sortBy )
data SimplCont
= Stop
OutType
CallCtxt
| CastIt
OutCoercion
SimplCont
| ApplyToVal
{ SimplCont -> DupFlag
sc_dup :: DupFlag
, SimplCont -> OutType
sc_hole_ty :: OutType
, SimplCont -> Expr Id
sc_arg :: InExpr
, SimplCont -> StaticEnv
sc_env :: StaticEnv
, SimplCont -> SimplCont
sc_cont :: SimplCont }
| ApplyToTy
{ SimplCont -> OutType
sc_arg_ty :: OutType
, sc_hole_ty :: OutType
, sc_cont :: SimplCont }
| Select
{ sc_dup :: DupFlag
, SimplCont -> Id
sc_bndr :: InId
, SimplCont -> [InAlt]
sc_alts :: [InAlt]
, sc_env :: StaticEnv
, sc_cont :: SimplCont }
| StrictBind
{ sc_dup :: DupFlag
, sc_bndr :: InId
, SimplCont -> [Id]
sc_bndrs :: [InBndr]
, SimplCont -> Expr Id
sc_body :: InExpr
, sc_env :: StaticEnv
, sc_cont :: SimplCont }
| StrictArg
{ sc_dup :: DupFlag
, SimplCont -> ArgInfo
sc_fun :: ArgInfo
, SimplCont -> OutType
sc_fun_ty :: OutType
, sc_cont :: SimplCont }
| TickIt
CoreTickish
SimplCont
type StaticEnv = SimplEnv
data DupFlag = NoDup
| Simplified
| OkToDup
isSimplified :: DupFlag -> Bool
isSimplified :: DupFlag -> Bool
isSimplified DupFlag
NoDup = Bool
False
isSimplified DupFlag
_ = Bool
True
perhapsSubstTy :: DupFlag -> StaticEnv -> Type -> Type
perhapsSubstTy :: DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy DupFlag
dup StaticEnv
env OutType
ty
| DupFlag -> Bool
isSimplified DupFlag
dup = OutType
ty
| Bool
otherwise = StaticEnv -> OutType -> OutType
substTy StaticEnv
env OutType
ty
instance Outputable DupFlag where
ppr :: DupFlag -> SDoc
ppr DupFlag
OkToDup = String -> SDoc
text String
"ok"
ppr DupFlag
NoDup = String -> SDoc
text String
"nodup"
ppr DupFlag
Simplified = String -> SDoc
text String
"simpl"
instance Outputable SimplCont where
ppr :: SimplCont -> SDoc
ppr (Stop OutType
ty CallCtxt
interesting) = String -> SDoc
text String
"Stop" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
brackets (forall a. Outputable a => a -> SDoc
ppr CallCtxt
interesting) SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr OutType
ty
ppr (CastIt OutCoercion
co SimplCont
cont ) = (String -> SDoc
text String
"CastIt" SDoc -> SDoc -> SDoc
<+> OutCoercion -> SDoc
pprOptCo OutCoercion
co) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (TickIt CoreTickish
t SimplCont
cont) = (String -> SDoc
text String
"TickIt" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr CoreTickish
t) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (ApplyToTy { sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text String
"ApplyToTy" SDoc -> SDoc -> SDoc
<+> OutType -> SDoc
pprParendType OutType
ty) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (ApplyToVal { sc_arg :: SimplCont -> Expr Id
sc_arg = Expr Id
arg, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont, sc_hole_ty :: SimplCont -> OutType
sc_hole_ty = OutType
hole_ty })
= (SDoc -> Arity -> SDoc -> SDoc
hang (String -> SDoc
text String
"ApplyToVal" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr DupFlag
dup SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"hole" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr OutType
hole_ty)
Arity
2 (forall b. OutputableBndr b => Expr b -> SDoc
pprParendExpr Expr Id
arg))
SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (StrictBind { sc_bndr :: SimplCont -> Id
sc_bndr = Id
b, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text String
"StrictBind" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Id
b) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
ai, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text String
"StrictArg" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr (ArgInfo -> Id
ai_fun ArgInfo
ai)) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (Select { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_bndr :: SimplCont -> Id
sc_bndr = Id
bndr, sc_alts :: SimplCont -> [InAlt]
sc_alts = [InAlt]
alts, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text String
"Select" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr DupFlag
dup SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Id
bndr) SDoc -> SDoc -> SDoc
$$
SDoc -> SDoc
whenPprDebug (Arity -> SDoc -> SDoc
nest Arity
2 forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
vcat [forall a. Outputable a => a -> SDoc
ppr (StaticEnv -> TvSubstEnv
seTvSubst StaticEnv
se), forall a. Outputable a => a -> SDoc
ppr [InAlt]
alts]) SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
data ArgInfo
= ArgInfo {
ArgInfo -> Id
ai_fun :: OutId,
ArgInfo -> [ArgSpec]
ai_args :: [ArgSpec],
ArgInfo -> FunRules
ai_rules :: FunRules,
ArgInfo -> Bool
ai_encl :: Bool,
ArgInfo -> [Demand]
ai_dmds :: [Demand],
ArgInfo -> [Arity]
ai_discs :: [Int]
}
data ArgSpec
= ValArg { ArgSpec -> Demand
as_dmd :: Demand
, ArgSpec -> Expr Id
as_arg :: OutExpr
, ArgSpec -> OutType
as_hole_ty :: OutType }
| TyArg { ArgSpec -> OutType
as_arg_ty :: OutType
, as_hole_ty :: OutType }
| CastBy OutCoercion
instance Outputable ArgInfo where
ppr :: ArgInfo -> SDoc
ppr (ArgInfo { ai_fun :: ArgInfo -> Id
ai_fun = Id
fun, ai_args :: ArgInfo -> [ArgSpec]
ai_args = [ArgSpec]
args, ai_dmds :: ArgInfo -> [Demand]
ai_dmds = [Demand]
dmds })
= String -> SDoc
text String
"ArgInfo" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces
([SDoc] -> SDoc
sep [ String -> SDoc
text String
"fun =" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Id
fun
, String -> SDoc
text String
"dmds =" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr [Demand]
dmds
, String -> SDoc
text String
"args =" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr [ArgSpec]
args ])
instance Outputable ArgSpec where
ppr :: ArgSpec -> SDoc
ppr (ValArg { as_arg :: ArgSpec -> Expr Id
as_arg = Expr Id
arg }) = String -> SDoc
text String
"ValArg" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Expr Id
arg
ppr (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty }) = String -> SDoc
text String
"TyArg" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr OutType
ty
ppr (CastBy OutCoercion
c) = String -> SDoc
text String
"CastBy" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr OutCoercion
c
addValArgTo :: ArgInfo -> OutExpr -> OutType -> ArgInfo
addValArgTo :: ArgInfo -> Expr Id -> OutType -> ArgInfo
addValArgTo ArgInfo
ai Expr Id
arg OutType
hole_ty
| ArgInfo { ai_dmds :: ArgInfo -> [Demand]
ai_dmds = Demand
dmd:[Demand]
dmds, ai_discs :: ArgInfo -> [Arity]
ai_discs = Arity
_:[Arity]
discs, ai_rules :: ArgInfo -> FunRules
ai_rules = FunRules
rules } <- ArgInfo
ai
, let arg_spec :: ArgSpec
arg_spec = ValArg { as_arg :: Expr Id
as_arg = Expr Id
arg, as_hole_ty :: OutType
as_hole_ty = OutType
hole_ty, as_dmd :: Demand
as_dmd = Demand
dmd }
= ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = ArgSpec
arg_spec forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai
, ai_dmds :: [Demand]
ai_dmds = [Demand]
dmds
, ai_discs :: [Arity]
ai_discs = [Arity]
discs
, ai_rules :: FunRules
ai_rules = FunRules -> FunRules
decRules FunRules
rules }
| Bool
otherwise
= forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"addValArgTo" (forall a. Outputable a => a -> SDoc
ppr ArgInfo
ai SDoc -> SDoc -> SDoc
$$ forall a. Outputable a => a -> SDoc
ppr Expr Id
arg)
addTyArgTo :: ArgInfo -> OutType -> OutType -> ArgInfo
addTyArgTo :: ArgInfo -> OutType -> OutType -> ArgInfo
addTyArgTo ArgInfo
ai OutType
arg_ty OutType
hole_ty = ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = ArgSpec
arg_spec forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai
, ai_rules :: FunRules
ai_rules = FunRules -> FunRules
decRules (ArgInfo -> FunRules
ai_rules ArgInfo
ai) }
where
arg_spec :: ArgSpec
arg_spec = TyArg { as_arg_ty :: OutType
as_arg_ty = OutType
arg_ty, as_hole_ty :: OutType
as_hole_ty = OutType
hole_ty }
addCastTo :: ArgInfo -> OutCoercion -> ArgInfo
addCastTo :: ArgInfo -> OutCoercion -> ArgInfo
addCastTo ArgInfo
ai OutCoercion
co = ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = OutCoercion -> ArgSpec
CastBy OutCoercion
co forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai }
isStrictArgInfo :: ArgInfo -> Bool
isStrictArgInfo :: ArgInfo -> Bool
isStrictArgInfo (ArgInfo { ai_dmds :: ArgInfo -> [Demand]
ai_dmds = [Demand]
dmds })
| Demand
dmd:[Demand]
_ <- [Demand]
dmds = Demand -> Bool
isStrUsedDmd Demand
dmd
| Bool
otherwise = Bool
False
argInfoAppArgs :: [ArgSpec] -> [OutExpr]
argInfoAppArgs :: [ArgSpec] -> [Expr Id]
argInfoAppArgs [] = []
argInfoAppArgs (CastBy {} : [ArgSpec]
_) = []
argInfoAppArgs (ValArg { as_arg :: ArgSpec -> Expr Id
as_arg = Expr Id
arg } : [ArgSpec]
as) = Expr Id
arg forall a. a -> [a] -> [a]
: [ArgSpec] -> [Expr Id]
argInfoAppArgs [ArgSpec]
as
argInfoAppArgs (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty } : [ArgSpec]
as) = forall b. OutType -> Expr b
Type OutType
ty forall a. a -> [a] -> [a]
: [ArgSpec] -> [Expr Id]
argInfoAppArgs [ArgSpec]
as
pushSimplifiedArgs :: SimplEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs :: StaticEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs StaticEnv
_env [] SimplCont
k = SimplCont
k
pushSimplifiedArgs StaticEnv
env (ArgSpec
arg : [ArgSpec]
args) SimplCont
k
= case ArgSpec
arg of
TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
arg_ty, as_hole_ty :: ArgSpec -> OutType
as_hole_ty = OutType
hole_ty }
-> ApplyToTy { sc_arg_ty :: OutType
sc_arg_ty = OutType
arg_ty, sc_hole_ty :: OutType
sc_hole_ty = OutType
hole_ty, sc_cont :: SimplCont
sc_cont = SimplCont
rest }
ValArg { as_arg :: ArgSpec -> Expr Id
as_arg = Expr Id
arg, as_hole_ty :: ArgSpec -> OutType
as_hole_ty = OutType
hole_ty }
-> ApplyToVal { sc_arg :: Expr Id
sc_arg = Expr Id
arg, sc_env :: StaticEnv
sc_env = StaticEnv
env, sc_dup :: DupFlag
sc_dup = DupFlag
Simplified
, sc_hole_ty :: OutType
sc_hole_ty = OutType
hole_ty, sc_cont :: SimplCont
sc_cont = SimplCont
rest }
CastBy OutCoercion
c -> OutCoercion -> SimplCont -> SimplCont
CastIt OutCoercion
c SimplCont
rest
where
rest :: SimplCont
rest = StaticEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs StaticEnv
env [ArgSpec]
args SimplCont
k
argInfoExpr :: OutId -> [ArgSpec] -> OutExpr
argInfoExpr :: Id -> [ArgSpec] -> Expr Id
argInfoExpr Id
fun [ArgSpec]
rev_args
= [ArgSpec] -> Expr Id
go [ArgSpec]
rev_args
where
go :: [ArgSpec] -> Expr Id
go [] = forall b. Id -> Expr b
Var Id
fun
go (ValArg { as_arg :: ArgSpec -> Expr Id
as_arg = Expr Id
arg } : [ArgSpec]
as) = [ArgSpec] -> Expr Id
go [ArgSpec]
as forall b. Expr b -> Expr b -> Expr b
`App` Expr Id
arg
go (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty } : [ArgSpec]
as) = [ArgSpec] -> Expr Id
go [ArgSpec]
as forall b. Expr b -> Expr b -> Expr b
`App` forall b. OutType -> Expr b
Type OutType
ty
go (CastBy OutCoercion
co : [ArgSpec]
as) = Expr Id -> OutCoercion -> Expr Id
mkCast ([ArgSpec] -> Expr Id
go [ArgSpec]
as) OutCoercion
co
type FunRules = Maybe (Int, [CoreRule])
decRules :: FunRules -> FunRules
decRules :: FunRules -> FunRules
decRules (Just (Arity
n, [CoreRule]
rules)) = forall a. a -> Maybe a
Just (Arity
nforall a. Num a => a -> a -> a
-Arity
1, [CoreRule]
rules)
decRules FunRules
Nothing = forall a. Maybe a
Nothing
mkFunRules :: [CoreRule] -> FunRules
mkFunRules :: [CoreRule] -> FunRules
mkFunRules [] = forall a. Maybe a
Nothing
mkFunRules [CoreRule]
rs = forall a. a -> Maybe a
Just (Arity
n_required, [CoreRule]
rs)
where
n_required :: Arity
n_required = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (forall a b. (a -> b) -> [a] -> [b]
map CoreRule -> Arity
ruleArity [CoreRule]
rs)
mkBoringStop :: OutType -> SimplCont
mkBoringStop :: OutType -> SimplCont
mkBoringStop OutType
ty = OutType -> CallCtxt -> SimplCont
Stop OutType
ty CallCtxt
BoringCtxt
mkRhsStop :: OutType -> SimplCont
mkRhsStop :: OutType -> SimplCont
mkRhsStop OutType
ty = OutType -> CallCtxt -> SimplCont
Stop OutType
ty CallCtxt
RhsCtxt
mkLazyArgStop :: OutType -> CallCtxt -> SimplCont
mkLazyArgStop :: OutType -> CallCtxt -> SimplCont
mkLazyArgStop OutType
ty CallCtxt
cci = OutType -> CallCtxt -> SimplCont
Stop OutType
ty CallCtxt
cci
contIsRhsOrArg :: SimplCont -> Bool
contIsRhsOrArg :: SimplCont -> Bool
contIsRhsOrArg (Stop {}) = Bool
True
contIsRhsOrArg (StrictBind {}) = Bool
True
contIsRhsOrArg (StrictArg {}) = Bool
True
contIsRhsOrArg SimplCont
_ = Bool
False
contIsRhs :: SimplCont -> Bool
contIsRhs :: SimplCont -> Bool
contIsRhs (Stop OutType
_ CallCtxt
RhsCtxt) = Bool
True
contIsRhs SimplCont
_ = Bool
False
contIsStop :: SimplCont -> Bool
contIsStop :: SimplCont -> Bool
contIsStop (Stop {}) = Bool
True
contIsStop SimplCont
_ = Bool
False
contIsDupable :: SimplCont -> Bool
contIsDupable :: SimplCont -> Bool
contIsDupable (Stop {}) = Bool
True
contIsDupable (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> Bool
contIsDupable SimplCont
k
contIsDupable (ApplyToVal { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
OkToDup }) = Bool
True
contIsDupable (Select { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
OkToDup }) = Bool
True
contIsDupable (StrictArg { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
OkToDup }) = Bool
True
contIsDupable (CastIt OutCoercion
_ SimplCont
k) = SimplCont -> Bool
contIsDupable SimplCont
k
contIsDupable SimplCont
_ = Bool
False
contIsTrivial :: SimplCont -> Bool
contIsTrivial :: SimplCont -> Bool
contIsTrivial (Stop {}) = Bool
True
contIsTrivial (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> Bool
contIsTrivial SimplCont
k
contIsTrivial (ApplyToVal { sc_arg :: SimplCont -> Expr Id
sc_arg = Coercion OutCoercion
_, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> Bool
contIsTrivial SimplCont
k
contIsTrivial (CastIt OutCoercion
_ SimplCont
k) = SimplCont -> Bool
contIsTrivial SimplCont
k
contIsTrivial SimplCont
_ = Bool
False
contResultType :: SimplCont -> OutType
contResultType :: SimplCont -> OutType
contResultType (Stop OutType
ty CallCtxt
_) = OutType
ty
contResultType (CastIt OutCoercion
_ SimplCont
k) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (StrictBind { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (StrictArg { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (Select { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (ApplyToVal { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contResultType SimplCont
k
contResultType (TickIt CoreTickish
_ SimplCont
k) = SimplCont -> OutType
contResultType SimplCont
k
contHoleType :: SimplCont -> OutType
contHoleType :: SimplCont -> OutType
contHoleType (Stop OutType
ty CallCtxt
_) = OutType
ty
contHoleType (TickIt CoreTickish
_ SimplCont
k) = SimplCont -> OutType
contHoleType SimplCont
k
contHoleType (CastIt OutCoercion
co SimplCont
_) = OutCoercion -> OutType
coercionLKind OutCoercion
co
contHoleType (StrictBind { sc_bndr :: SimplCont -> Id
sc_bndr = Id
b, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se })
= DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy DupFlag
dup StaticEnv
se (Id -> OutType
idType Id
b)
contHoleType (StrictArg { sc_fun_ty :: SimplCont -> OutType
sc_fun_ty = OutType
ty }) = OutType -> OutType
funArgTy OutType
ty
contHoleType (ApplyToTy { sc_hole_ty :: SimplCont -> OutType
sc_hole_ty = OutType
ty }) = OutType
ty
contHoleType (ApplyToVal { sc_hole_ty :: SimplCont -> OutType
sc_hole_ty = OutType
ty }) = OutType
ty
contHoleType (Select { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
d, sc_bndr :: SimplCont -> Id
sc_bndr = Id
b, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se })
= DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy DupFlag
d StaticEnv
se (Id -> OutType
idType Id
b)
contHoleScaling :: SimplCont -> Mult
contHoleScaling :: SimplCont -> OutType
contHoleScaling (Stop OutType
_ CallCtxt
_) = OutType
One
contHoleScaling (CastIt OutCoercion
_ SimplCont
k) = SimplCont -> OutType
contHoleScaling SimplCont
k
contHoleScaling (StrictBind { sc_bndr :: SimplCont -> Id
sc_bndr = Id
id, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= Id -> OutType
idMult Id
id OutType -> OutType -> OutType
`mkMultMul` SimplCont -> OutType
contHoleScaling SimplCont
k
contHoleScaling (Select { sc_bndr :: SimplCont -> Id
sc_bndr = Id
id, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= Id -> OutType
idMult Id
id OutType -> OutType -> OutType
`mkMultMul` SimplCont -> OutType
contHoleScaling SimplCont
k
contHoleScaling (StrictArg { sc_fun_ty :: SimplCont -> OutType
sc_fun_ty = OutType
fun_ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= OutType
w OutType -> OutType -> OutType
`mkMultMul` SimplCont -> OutType
contHoleScaling SimplCont
k
where
(OutType
w, OutType
_, OutType
_) = OutType -> (OutType, OutType, OutType)
splitFunTy OutType
fun_ty
contHoleScaling (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contHoleScaling SimplCont
k
contHoleScaling (ApplyToVal { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> OutType
contHoleScaling SimplCont
k
contHoleScaling (TickIt CoreTickish
_ SimplCont
k) = SimplCont -> OutType
contHoleScaling SimplCont
k
countArgs :: SimplCont -> Int
countArgs :: SimplCont -> Arity
countArgs (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }) = Arity
1 forall a. Num a => a -> a -> a
+ SimplCont -> Arity
countArgs SimplCont
cont
countArgs (ApplyToVal { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }) = Arity
1 forall a. Num a => a -> a -> a
+ SimplCont -> Arity
countArgs SimplCont
cont
countArgs SimplCont
_ = Arity
0
contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
contArgs SimplCont
cont
| SimplCont -> Bool
lone SimplCont
cont = (Bool
True, [], SimplCont
cont)
| Bool
otherwise = [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [] SimplCont
cont
where
lone :: SimplCont -> Bool
lone (ApplyToTy {}) = Bool
False
lone (ApplyToVal {}) = Bool
False
lone (CastIt {}) = Bool
False
lone SimplCont
_ = Bool
True
go :: [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [ArgSummary]
args (ApplyToVal { sc_arg :: SimplCont -> Expr Id
sc_arg = Expr Id
arg, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go (Expr Id -> StaticEnv -> ArgSummary
is_interesting Expr Id
arg StaticEnv
se forall a. a -> [a] -> [a]
: [ArgSummary]
args) SimplCont
k
go [ArgSummary]
args (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [ArgSummary]
args SimplCont
k
go [ArgSummary]
args (CastIt OutCoercion
_ SimplCont
k) = [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [ArgSummary]
args SimplCont
k
go [ArgSummary]
args SimplCont
k = (Bool
False, forall a. [a] -> [a]
reverse [ArgSummary]
args, SimplCont
k)
is_interesting :: Expr Id -> StaticEnv -> ArgSummary
is_interesting Expr Id
arg StaticEnv
se = StaticEnv -> Expr Id -> ArgSummary
interestingArg StaticEnv
se Expr Id
arg
mkArgInfo :: SimplEnv
-> Id
-> [CoreRule]
-> Int
-> SimplCont
-> ArgInfo
mkArgInfo :: StaticEnv -> Id -> [CoreRule] -> Arity -> SimplCont -> ArgInfo
mkArgInfo StaticEnv
env Id
fun [CoreRule]
rules Arity
n_val_args SimplCont
call_cont
| Arity
n_val_args forall a. Ord a => a -> a -> Bool
< Id -> Arity
idArity Id
fun
= ArgInfo { ai_fun :: Id
ai_fun = Id
fun, ai_args :: [ArgSpec]
ai_args = []
, ai_rules :: FunRules
ai_rules = FunRules
fun_rules
, ai_encl :: Bool
ai_encl = Bool
False
, ai_dmds :: [Demand]
ai_dmds = [Demand]
vanilla_dmds
, ai_discs :: [Arity]
ai_discs = [Arity]
vanilla_discounts }
| Bool
otherwise
= ArgInfo { ai_fun :: Id
ai_fun = Id
fun
, ai_args :: [ArgSpec]
ai_args = []
, ai_rules :: FunRules
ai_rules = FunRules
fun_rules
, ai_encl :: Bool
ai_encl = [CoreRule] -> SimplCont -> Bool
interestingArgContext [CoreRule]
rules SimplCont
call_cont
, ai_dmds :: [Demand]
ai_dmds = OutType -> [Demand] -> [Demand]
add_type_strictness (Id -> OutType
idType Id
fun) [Demand]
arg_dmds
, ai_discs :: [Arity]
ai_discs = [Arity]
arg_discounts }
where
fun_rules :: FunRules
fun_rules = [CoreRule] -> FunRules
mkFunRules [CoreRule]
rules
vanilla_discounts, arg_discounts :: [Int]
vanilla_discounts :: [Arity]
vanilla_discounts = forall a. a -> [a]
repeat Arity
0
arg_discounts :: [Arity]
arg_discounts = case Id -> Unfolding
idUnfolding Id
fun of
CoreUnfolding {uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfIfGoodArgs {ug_args :: UnfoldingGuidance -> [Arity]
ug_args = [Arity]
discounts}}
-> [Arity]
discounts forall a. [a] -> [a] -> [a]
++ [Arity]
vanilla_discounts
Unfolding
_ -> [Arity]
vanilla_discounts
vanilla_dmds, arg_dmds :: [Demand]
vanilla_dmds :: [Demand]
vanilla_dmds = forall a. a -> [a]
repeat Demand
topDmd
arg_dmds :: [Demand]
arg_dmds
| Bool -> Bool
not (SimplMode -> Bool
sm_inline (StaticEnv -> SimplMode
seMode StaticEnv
env))
= [Demand]
vanilla_dmds
| Bool
otherwise
=
case StrictSig -> ([Demand], Divergence)
splitStrictSig (Id -> StrictSig
idStrictness Id
fun) of
([Demand]
demands, Divergence
result_info)
| Bool -> Bool
not ([Demand]
demands forall a. [a] -> Arity -> Bool
`lengthExceeds` Arity
n_val_args)
->
if Divergence -> Bool
isDeadEndDiv Divergence
result_info then
[Demand]
demands
else
[Demand]
demands forall a. [a] -> [a] -> [a]
++ [Demand]
vanilla_dmds
| Bool
otherwise
-> WARN( True, text "More demands than arity" <+> ppr fun <+> ppr (idArity fun)
<+> ppr n_val_args <+> ppr demands )
[Demand]
vanilla_dmds
add_type_strictness :: Type -> [Demand] -> [Demand]
add_type_strictness :: OutType -> [Demand] -> [Demand]
add_type_strictness OutType
fun_ty [Demand]
dmds
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Demand]
dmds = []
| Just (Id
_, OutType
fun_ty') <- OutType -> Maybe (Id, OutType)
splitForAllTyCoVar_maybe OutType
fun_ty
= OutType -> [Demand] -> [Demand]
add_type_strictness OutType
fun_ty' [Demand]
dmds
| Just (OutType
_, OutType
arg_ty, OutType
fun_ty') <- OutType -> Maybe (OutType, OutType, OutType)
splitFunTy_maybe OutType
fun_ty
, Demand
dmd : [Demand]
rest_dmds <- [Demand]
dmds
, let dmd' :: Demand
dmd' = case HasDebugCallStack => OutType -> Maybe Bool
isLiftedType_maybe OutType
arg_ty of
Just Bool
False -> Demand -> Demand
strictifyDmd Demand
dmd
Maybe Bool
_ -> Demand
dmd
= Demand
dmd' forall a. a -> [a] -> [a]
: OutType -> [Demand] -> [Demand]
add_type_strictness OutType
fun_ty' [Demand]
rest_dmds
| Bool
otherwise
= [Demand]
dmds
lazyArgContext :: ArgInfo -> CallCtxt
lazyArgContext :: ArgInfo -> CallCtxt
lazyArgContext (ArgInfo { ai_encl :: ArgInfo -> Bool
ai_encl = Bool
encl_rules, ai_discs :: ArgInfo -> [Arity]
ai_discs = [Arity]
discs })
| Bool
encl_rules = CallCtxt
RuleArgCtxt
| Arity
disc:[Arity]
_ <- [Arity]
discs, Arity
disc forall a. Ord a => a -> a -> Bool
> Arity
0 = CallCtxt
DiscArgCtxt
| Bool
otherwise = CallCtxt
BoringCtxt
strictArgContext :: ArgInfo -> CallCtxt
strictArgContext :: ArgInfo -> CallCtxt
strictArgContext (ArgInfo { ai_encl :: ArgInfo -> Bool
ai_encl = Bool
encl_rules, ai_discs :: ArgInfo -> [Arity]
ai_discs = [Arity]
discs })
| Bool
encl_rules = CallCtxt
RuleArgCtxt
| Arity
disc:[Arity]
_ <- [Arity]
discs, Arity
disc forall a. Ord a => a -> a -> Bool
> Arity
0 = CallCtxt
DiscArgCtxt
| Bool
otherwise = CallCtxt
RhsCtxt
interestingCallContext :: SimplEnv -> SimplCont -> CallCtxt
interestingCallContext :: StaticEnv -> SimplCont -> CallCtxt
interestingCallContext StaticEnv
env SimplCont
cont
= SimplCont -> CallCtxt
interesting SimplCont
cont
where
interesting :: SimplCont -> CallCtxt
interesting (Select {})
| SimplMode -> Bool
sm_case_case (StaticEnv -> SimplMode
getMode StaticEnv
env) = CallCtxt
CaseCtxt
| Bool
otherwise = CallCtxt
BoringCtxt
interesting (ApplyToVal {}) = CallCtxt
ValAppCtxt
interesting (StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
fun }) = ArgInfo -> CallCtxt
strictArgContext ArgInfo
fun
interesting (StrictBind {}) = CallCtxt
BoringCtxt
interesting (Stop OutType
_ CallCtxt
cci) = CallCtxt
cci
interesting (TickIt CoreTickish
_ SimplCont
k) = SimplCont -> CallCtxt
interesting SimplCont
k
interesting (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> CallCtxt
interesting SimplCont
k
interesting (CastIt OutCoercion
_ SimplCont
k) = SimplCont -> CallCtxt
interesting SimplCont
k
interestingArgContext :: [CoreRule] -> SimplCont -> Bool
interestingArgContext :: [CoreRule] -> SimplCont -> Bool
interestingArgContext [CoreRule]
rules SimplCont
call_cont
= forall (f :: * -> *) a. Foldable f => f a -> Bool
notNull [CoreRule]
rules Bool -> Bool -> Bool
|| Bool
enclosing_fn_has_rules
where
enclosing_fn_has_rules :: Bool
enclosing_fn_has_rules = SimplCont -> Bool
go SimplCont
call_cont
go :: SimplCont -> Bool
go (Select {}) = Bool
False
go (ApplyToVal {}) = Bool
False
go (ApplyToTy {}) = Bool
False
go (StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
fun }) = ArgInfo -> Bool
ai_encl ArgInfo
fun
go (StrictBind {}) = Bool
False
go (CastIt OutCoercion
_ SimplCont
c) = SimplCont -> Bool
go SimplCont
c
go (Stop OutType
_ CallCtxt
RuleArgCtxt) = Bool
True
go (Stop OutType
_ CallCtxt
_) = Bool
False
go (TickIt CoreTickish
_ SimplCont
c) = SimplCont -> Bool
go SimplCont
c
interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
interestingArg :: StaticEnv -> Expr Id -> ArgSummary
interestingArg StaticEnv
env Expr Id
e = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
0 Expr Id
e
where
go :: StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
n (Var Id
v)
= case StaticEnv -> Id -> SimplSR
substId StaticEnv
env Id
v of
DoneId Id
v' -> Arity -> Id -> ArgSummary
go_var Arity
n Id
v'
DoneEx Expr Id
e Maybe Arity
_ -> StaticEnv -> Arity -> Expr Id -> ArgSummary
go (StaticEnv -> StaticEnv
zapSubstEnv StaticEnv
env) Arity
n Expr Id
e
ContEx TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids Expr Id
e -> StaticEnv -> Arity -> Expr Id -> ArgSummary
go (StaticEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> StaticEnv
setSubstEnv StaticEnv
env TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids) Arity
n Expr Id
e
go StaticEnv
_ Arity
_ (Lit {}) = ArgSummary
ValueArg
go StaticEnv
_ Arity
_ (Type OutType
_) = ArgSummary
TrivArg
go StaticEnv
_ Arity
_ (Coercion OutCoercion
_) = ArgSummary
TrivArg
go StaticEnv
env Arity
n (App Expr Id
fn (Type OutType
_)) = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
n Expr Id
fn
go StaticEnv
env Arity
n (App Expr Id
fn Expr Id
_) = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env (Arity
nforall a. Num a => a -> a -> a
+Arity
1) Expr Id
fn
go StaticEnv
env Arity
n (Tick CoreTickish
_ Expr Id
a) = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
n Expr Id
a
go StaticEnv
env Arity
n (Cast Expr Id
e OutCoercion
_) = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
n Expr Id
e
go StaticEnv
env Arity
n (Lam Id
v Expr Id
e)
| Id -> Bool
isTyVar Id
v = StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env Arity
n Expr Id
e
| Arity
nforall a. Ord a => a -> a -> Bool
>Arity
0 = ArgSummary
NonTrivArg
| Bool
otherwise = ArgSummary
ValueArg
go StaticEnv
_ Arity
_ (Case {}) = ArgSummary
NonTrivArg
go StaticEnv
env Arity
n (Let Bind Id
b Expr Id
e) = case StaticEnv -> Arity -> Expr Id -> ArgSummary
go StaticEnv
env' Arity
n Expr Id
e of
ArgSummary
ValueArg -> ArgSummary
ValueArg
ArgSummary
_ -> ArgSummary
NonTrivArg
where
env' :: StaticEnv
env' = StaticEnv
env StaticEnv -> [Id] -> StaticEnv
`addNewInScopeIds` forall b. Bind b -> [b]
bindersOf Bind Id
b
go_var :: Arity -> Id -> ArgSummary
go_var Arity
n Id
v
| Id -> Bool
isConLikeId Id
v = ArgSummary
ValueArg
| Id -> Arity
idArity Id
v forall a. Ord a => a -> a -> Bool
> Arity
n = ArgSummary
ValueArg
| Arity
n forall a. Ord a => a -> a -> Bool
> Arity
0 = ArgSummary
NonTrivArg
| Bool
conlike_unfolding = ArgSummary
ValueArg
| Bool
otherwise = ArgSummary
TrivArg
where
conlike_unfolding :: Bool
conlike_unfolding = Unfolding -> Bool
isConLikeUnfolding (Id -> Unfolding
idUnfolding Id
v)
simplEnvForGHCi :: Logger -> DynFlags -> SimplEnv
simplEnvForGHCi :: Logger -> DynFlags -> StaticEnv
simplEnvForGHCi Logger
logger DynFlags
dflags
= SimplMode -> StaticEnv
mkSimplEnv forall a b. (a -> b) -> a -> b
$ SimplMode { sm_names :: [String]
sm_names = [String
"GHCi"]
, sm_phase :: CompilerPhase
sm_phase = CompilerPhase
InitialPhase
, sm_logger :: Logger
sm_logger = Logger
logger
, sm_dflags :: DynFlags
sm_dflags = DynFlags
dflags
, sm_uf_opts :: UnfoldingOpts
sm_uf_opts = UnfoldingOpts
uf_opts
, sm_rules :: Bool
sm_rules = Bool
rules_on
, sm_inline :: Bool
sm_inline = Bool
False
, sm_eta_expand :: Bool
sm_eta_expand = Bool
eta_expand_on
, sm_cast_swizzle :: Bool
sm_cast_swizzle = Bool
True
, sm_case_case :: Bool
sm_case_case = Bool
True
, sm_pre_inline :: Bool
sm_pre_inline = Bool
pre_inline_on
}
where
rules_on :: Bool
rules_on = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_EnableRewriteRules DynFlags
dflags
eta_expand_on :: Bool
eta_expand_on = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoLambdaEtaExpansion DynFlags
dflags
pre_inline_on :: Bool
pre_inline_on = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SimplPreInlining DynFlags
dflags
uf_opts :: UnfoldingOpts
uf_opts = DynFlags -> UnfoldingOpts
unfoldingOpts DynFlags
dflags
updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
updModeForStableUnfoldings Activation
unf_act SimplMode
current_mode
= SimplMode
current_mode { sm_phase :: CompilerPhase
sm_phase = Activation -> CompilerPhase
phaseFromActivation Activation
unf_act
, sm_eta_expand :: Bool
sm_eta_expand = Bool
False
, sm_inline :: Bool
sm_inline = Bool
True }
where
phaseFromActivation :: Activation -> CompilerPhase
phaseFromActivation (ActiveAfter SourceText
_ Arity
n) = Arity -> CompilerPhase
Phase Arity
n
phaseFromActivation Activation
_ = CompilerPhase
InitialPhase
updModeForRules :: SimplMode -> SimplMode
updModeForRules :: SimplMode -> SimplMode
updModeForRules SimplMode
current_mode
= SimplMode
current_mode { sm_phase :: CompilerPhase
sm_phase = CompilerPhase
InitialPhase
, sm_inline :: Bool
sm_inline = Bool
False
, sm_rules :: Bool
sm_rules = Bool
False
, sm_cast_swizzle :: Bool
sm_cast_swizzle = Bool
False
, sm_eta_expand :: Bool
sm_eta_expand = Bool
False }
activeUnfolding :: SimplMode -> Id -> Bool
activeUnfolding :: SimplMode -> Id -> Bool
activeUnfolding SimplMode
mode Id
id
| Unfolding -> Bool
isCompulsoryUnfolding (Id -> Unfolding
realIdUnfolding Id
id)
= Bool
True
| Bool
otherwise
= CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode) (Id -> Activation
idInlineActivation Id
id)
Bool -> Bool -> Bool
&& SimplMode -> Bool
sm_inline SimplMode
mode
getUnfoldingInRuleMatch :: SimplEnv -> InScopeEnv
getUnfoldingInRuleMatch :: StaticEnv -> InScopeEnv
getUnfoldingInRuleMatch StaticEnv
env
= (InScopeSet
in_scope, Id -> Unfolding
id_unf)
where
in_scope :: InScopeSet
in_scope = StaticEnv -> InScopeSet
seInScope StaticEnv
env
mode :: SimplMode
mode = StaticEnv -> SimplMode
getMode StaticEnv
env
id_unf :: Id -> Unfolding
id_unf Id
id | Id -> Bool
unf_is_active Id
id = Id -> Unfolding
idUnfolding Id
id
| Bool
otherwise = Unfolding
NoUnfolding
unf_is_active :: Id -> Bool
unf_is_active Id
id
| Bool -> Bool
not (SimplMode -> Bool
sm_rules SimplMode
mode) =
Unfolding -> Bool
isStableUnfolding (Id -> Unfolding
realIdUnfolding Id
id)
| Bool
otherwise = CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode) (Id -> Activation
idInlineActivation Id
id)
activeRule :: SimplMode -> Activation -> Bool
activeRule :: SimplMode -> Activation -> Bool
activeRule SimplMode
mode
| Bool -> Bool
not (SimplMode -> Bool
sm_rules SimplMode
mode) = \Activation
_ -> Bool
False
| Bool
otherwise = CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode)
preInlineUnconditionally
:: SimplEnv -> TopLevelFlag -> InId
-> InExpr -> StaticEnv
-> Maybe SimplEnv
preInlineUnconditionally :: StaticEnv
-> TopLevelFlag -> Id -> Expr Id -> StaticEnv -> Maybe StaticEnv
preInlineUnconditionally StaticEnv
env TopLevelFlag
top_lvl Id
bndr Expr Id
rhs StaticEnv
rhs_env
| Bool -> Bool
not Bool
pre_inline_unconditionally = forall a. Maybe a
Nothing
| Bool -> Bool
not Bool
active = forall a. Maybe a
Nothing
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
&& Id -> Bool
isDeadEndId Id
bndr = forall a. Maybe a
Nothing
| Id -> Bool
isCoVar Id
bndr = forall a. Maybe a
Nothing
| Id -> Bool
isExitJoinId Id
bndr = forall a. Maybe a
Nothing
| Bool -> Bool
not (OccInfo -> Bool
one_occ (Id -> OccInfo
idOccInfo Id
bndr)) = forall a. Maybe a
Nothing
| Bool -> Bool
not (Unfolding -> Bool
isStableUnfolding Unfolding
unf) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! (Expr Id -> StaticEnv
extend_subst_with Expr Id
rhs)
| Bool -> Bool
not (InlinePragma -> Bool
isInlinePragma InlinePragma
inline_prag)
, Just Expr Id
inl <- Unfolding -> Maybe (Expr Id)
maybeUnfoldingTemplate Unfolding
unf = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! (Expr Id -> StaticEnv
extend_subst_with Expr Id
inl)
| Bool
otherwise = forall a. Maybe a
Nothing
where
unf :: Unfolding
unf = Id -> Unfolding
idUnfolding Id
bndr
extend_subst_with :: Expr Id -> StaticEnv
extend_subst_with Expr Id
inl_rhs = StaticEnv -> Id -> SimplSR -> StaticEnv
extendIdSubst StaticEnv
env Id
bndr forall a b. (a -> b) -> a -> b
$! (StaticEnv -> Expr Id -> SimplSR
mkContEx StaticEnv
rhs_env Expr Id
inl_rhs)
one_occ :: OccInfo -> Bool
one_occ OccInfo
IAmDead = Bool
True
one_occ OneOcc{ occ_n_br :: OccInfo -> Arity
occ_n_br = Arity
1
, occ_in_lam :: OccInfo -> InsideLam
occ_in_lam = InsideLam
NotInsideLam } = TopLevelFlag -> Bool
isNotTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
|| Bool
early_phase
one_occ OneOcc{ occ_n_br :: OccInfo -> Arity
occ_n_br = Arity
1
, occ_in_lam :: OccInfo -> InsideLam
occ_in_lam = InsideLam
IsInsideLam
, occ_int_cxt :: OccInfo -> InterestingCxt
occ_int_cxt = InterestingCxt
IsInteresting } = Expr Id -> Bool
canInlineInLam Expr Id
rhs
one_occ OccInfo
_ = Bool
False
pre_inline_unconditionally :: Bool
pre_inline_unconditionally = SimplMode -> Bool
sm_pre_inline SimplMode
mode
mode :: SimplMode
mode = StaticEnv -> SimplMode
getMode StaticEnv
env
active :: Bool
active = CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode) (InlinePragma -> Activation
inlinePragmaActivation InlinePragma
inline_prag)
inline_prag :: InlinePragma
inline_prag = Id -> InlinePragma
idInlinePragma Id
bndr
canInlineInLam :: Expr Id -> Bool
canInlineInLam (Lit Literal
_) = Bool
True
canInlineInLam (Lam Id
b Expr Id
e) = Id -> Bool
isRuntimeVar Id
b Bool -> Bool -> Bool
|| Expr Id -> Bool
canInlineInLam Expr Id
e
canInlineInLam (Tick CoreTickish
t Expr Id
e) = Bool -> Bool
not (forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode CoreTickish
t) Bool -> Bool -> Bool
&& Expr Id -> Bool
canInlineInLam Expr Id
e
canInlineInLam Expr Id
_ = Bool
False
early_phase :: Bool
early_phase = SimplMode -> CompilerPhase
sm_phase SimplMode
mode forall a. Eq a => a -> a -> Bool
/= CompilerPhase
FinalPhase
postInlineUnconditionally
:: SimplEnv -> TopLevelFlag
-> OutId
-> OccInfo
-> OutExpr
-> Bool
postInlineUnconditionally :: StaticEnv -> TopLevelFlag -> Id -> OccInfo -> Expr Id -> Bool
postInlineUnconditionally StaticEnv
env TopLevelFlag
top_lvl Id
bndr OccInfo
occ_info Expr Id
rhs
| Bool -> Bool
not Bool
active = Bool
False
| OccInfo -> Bool
isWeakLoopBreaker OccInfo
occ_info = Bool
False
| Unfolding -> Bool
isStableUnfolding Unfolding
unfolding = Bool
False
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl = Bool
False
| Expr Id -> Bool
exprIsTrivial Expr Id
rhs = Bool
True
| Id -> Bool
isJoinId Id
bndr
, Bool -> Bool
not (CompilerPhase
phase forall a. Eq a => a -> a -> Bool
== CompilerPhase
FinalPhase) = Bool
False
| Bool
otherwise
= case OccInfo
occ_info of
OneOcc { occ_in_lam :: OccInfo -> InsideLam
occ_in_lam = InsideLam
in_lam, occ_int_cxt :: OccInfo -> InterestingCxt
occ_int_cxt = InterestingCxt
int_cxt, occ_n_br :: OccInfo -> Arity
occ_n_br = Arity
n_br }
-> Arity
n_br forall a. Ord a => a -> a -> Bool
< Arity
100
Bool -> Bool -> Bool
&& UnfoldingOpts -> Unfolding -> Bool
smallEnoughToInline UnfoldingOpts
uf_opts Unfolding
unfolding
Bool -> Bool -> Bool
&& (InsideLam
in_lam forall a. Eq a => a -> a -> Bool
== InsideLam
NotInsideLam Bool -> Bool -> Bool
||
(Unfolding -> Bool
isCheapUnfolding Unfolding
unfolding Bool -> Bool -> Bool
&& InterestingCxt
int_cxt forall a. Eq a => a -> a -> Bool
== InterestingCxt
IsInteresting))
OccInfo
IAmDead -> Bool
True
OccInfo
_ -> Bool
False
where
unfolding :: Unfolding
unfolding = Id -> Unfolding
idUnfolding Id
bndr
uf_opts :: UnfoldingOpts
uf_opts = StaticEnv -> UnfoldingOpts
seUnfoldingOpts StaticEnv
env
phase :: CompilerPhase
phase = SimplMode -> CompilerPhase
sm_phase (StaticEnv -> SimplMode
getMode StaticEnv
env)
active :: Bool
active = CompilerPhase -> Activation -> Bool
isActive CompilerPhase
phase (Id -> Activation
idInlineActivation Id
bndr)
mkLam :: SimplEnv -> [OutBndr] -> OutExpr -> SimplCont -> SimplM OutExpr
mkLam :: StaticEnv -> [Id] -> Expr Id -> SimplCont -> SimplM (Expr Id)
mkLam StaticEnv
_env [] Expr Id
body SimplCont
_cont
= forall (m :: * -> *) a. Monad m => a -> m a
return Expr Id
body
mkLam StaticEnv
env [Id]
bndrs Expr Id
body SimplCont
cont
= do { DynFlags
dflags <- forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; DynFlags -> [Id] -> Expr Id -> SimplM (Expr Id)
mkLam' DynFlags
dflags [Id]
bndrs Expr Id
body }
where
mode :: SimplMode
mode = StaticEnv -> SimplMode
getMode StaticEnv
env
mkLam' :: DynFlags -> [OutBndr] -> OutExpr -> SimplM OutExpr
mkLam' :: DynFlags -> [Id] -> Expr Id -> SimplM (Expr Id)
mkLam' DynFlags
dflags [Id]
bndrs body :: Expr Id
body@(Lam {})
= DynFlags -> [Id] -> Expr Id -> SimplM (Expr Id)
mkLam' DynFlags
dflags ([Id]
bndrs forall a. [a] -> [a] -> [a]
++ [Id]
bndrs1) Expr Id
body1
where
([Id]
bndrs1, Expr Id
body1) = forall b. Expr b -> ([b], Expr b)
collectBinders Expr Id
body
mkLam' DynFlags
dflags [Id]
bndrs (Tick CoreTickish
t Expr Id
expr)
| forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
t
= CoreTickish -> Expr Id -> Expr Id
mkTick CoreTickish
t forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynFlags -> [Id] -> Expr Id -> SimplM (Expr Id)
mkLam' DynFlags
dflags [Id]
bndrs Expr Id
expr
mkLam' DynFlags
dflags [Id]
bndrs (Cast Expr Id
body OutCoercion
co)
|
SimplMode -> Bool
sm_cast_swizzle SimplMode
mode
, Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Id -> Bool
bad [Id]
bndrs)
= do { Expr Id
lam <- DynFlags -> [Id] -> Expr Id -> SimplM (Expr Id)
mkLam' DynFlags
dflags [Id]
bndrs Expr Id
body
; forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Id -> OutCoercion -> Expr Id
mkCast Expr Id
lam (Role -> [Id] -> OutCoercion -> OutCoercion
mkPiCos Role
Representational [Id]
bndrs OutCoercion
co)) }
where
co_vars :: TyCoVarSet
co_vars = OutCoercion -> TyCoVarSet
tyCoVarsOfCo OutCoercion
co
bad :: Id -> Bool
bad Id
bndr = Id -> Bool
isCoVar Id
bndr Bool -> Bool -> Bool
&& Id
bndr Id -> TyCoVarSet -> Bool
`elemVarSet` TyCoVarSet
co_vars
mkLam' DynFlags
dflags [Id]
bndrs Expr Id
body
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoEtaReduction DynFlags
dflags
, Just Expr Id
etad_lam <- {-# SCC "tryee" #-} [Id] -> Expr Id -> Maybe (Expr Id)
tryEtaReduce [Id]
bndrs Expr Id
body
= do { Tick -> SimplM ()
tick (Id -> Tick
EtaReduction (forall a. [a] -> a
head [Id]
bndrs))
; forall (m :: * -> *) a. Monad m => a -> m a
return Expr Id
etad_lam }
| Bool -> Bool
not (SimplCont -> Bool
contIsRhs SimplCont
cont)
, SimplMode -> Bool
sm_eta_expand SimplMode
mode
, forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Id -> Bool
isRuntimeVar [Id]
bndrs
, let body_arity :: ArityType
body_arity = {-# SCC "eta" #-} DynFlags -> Expr Id -> ArityType
exprEtaExpandArity DynFlags
dflags Expr Id
body
, ArityType -> Bool
expandableArityType ArityType
body_arity
= do { Tick -> SimplM ()
tick (Id -> Tick
EtaExpansion (forall a. [a] -> a
head [Id]
bndrs))
; let res :: Expr Id
res = {-# SCC "eta3" #-}
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
bndrs forall a b. (a -> b) -> a -> b
$
ArityType -> Expr Id -> Expr Id
etaExpandAT ArityType
body_arity Expr Id
body
; String -> SDoc -> SimplM ()
traceSmpl String
"eta expand" ([SDoc] -> SDoc
vcat [String -> SDoc
text String
"before" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr (forall b. [b] -> Expr b -> Expr b
mkLams [Id]
bndrs Expr Id
body)
, String -> SDoc
text String
"after" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Expr Id
res])
; forall (m :: * -> *) a. Monad m => a -> m a
return Expr Id
res }
| Bool
otherwise
= forall (m :: * -> *) a. Monad m => a -> m a
return (forall b. [b] -> Expr b -> Expr b
mkLams [Id]
bndrs Expr Id
body)
tryEtaExpandRhs :: SimplMode -> OutId -> OutExpr
-> SimplM (ArityType, OutExpr)
tryEtaExpandRhs :: SimplMode -> Id -> Expr Id -> SimplM (ArityType, Expr Id)
tryEtaExpandRhs SimplMode
mode Id
bndr Expr Id
rhs
| Just Arity
join_arity <- Id -> Maybe Arity
isJoinId_maybe Id
bndr
= do { let ([Id]
join_bndrs, Expr Id
join_body) = forall b. Arity -> Expr b -> ([b], Expr b)
collectNBinders Arity
join_arity Expr Id
rhs
oss :: [OneShotInfo]
oss = [Id -> OneShotInfo
idOneShotInfo Id
id | Id
id <- [Id]
join_bndrs, Id -> Bool
isId Id
id]
arity_type :: ArityType
arity_type | Expr Id -> Bool
exprIsDeadEnd Expr Id
join_body = [OneShotInfo] -> ArityType
mkBotArityType [OneShotInfo]
oss
| Bool
otherwise = [OneShotInfo] -> ArityType
mkTopArityType [OneShotInfo]
oss
; forall (m :: * -> *) a. Monad m => a -> m a
return (ArityType
arity_type, Expr Id
rhs) }
| SimplMode -> Bool
sm_eta_expand SimplMode
mode
, Arity
new_arity forall a. Ord a => a -> a -> Bool
> Arity
old_arity
, Expr Id -> Bool
want_eta Expr Id
rhs
= do { Tick -> SimplM ()
tick (Id -> Tick
EtaExpansion Id
bndr)
; forall (m :: * -> *) a. Monad m => a -> m a
return (ArityType
arity_type, ArityType -> Expr Id -> Expr Id
etaExpandAT ArityType
arity_type Expr Id
rhs) }
| Bool
otherwise
= forall (m :: * -> *) a. Monad m => a -> m a
return (ArityType
arity_type, Expr Id
rhs)
where
dflags :: DynFlags
dflags = SimplMode -> DynFlags
sm_dflags SimplMode
mode
old_arity :: Arity
old_arity = Expr Id -> Arity
exprArity Expr Id
rhs
arity_type :: ArityType
arity_type = DynFlags -> Id -> Expr Id -> Arity -> ArityType
findRhsArity DynFlags
dflags Id
bndr Expr Id
rhs Arity
old_arity
ArityType -> Arity -> ArityType
`maxWithArity` Id -> Arity
idCallArity Id
bndr
new_arity :: Arity
new_arity = ArityType -> Arity
arityTypeArity ArityType
arity_type
want_eta :: Expr Id -> Bool
want_eta (Cast Expr Id
e OutCoercion
_) = Expr Id -> Bool
want_eta Expr Id
e
want_eta (Tick CoreTickish
_ Expr Id
e) = Expr Id -> Bool
want_eta Expr Id
e
want_eta (Lam Id
b Expr Id
e) | Id -> Bool
isTyVar Id
b = Expr Id -> Bool
want_eta Expr Id
e
want_eta (App Expr Id
e Expr Id
a) | Expr Id -> Bool
exprIsTrivial Expr Id
a = Expr Id -> Bool
want_eta Expr Id
e
want_eta (Var {}) = Bool
False
want_eta (Lit {}) = Bool
False
want_eta Expr Id
_ = Bool
True
abstractFloats :: UnfoldingOpts -> TopLevelFlag -> [OutTyVar] -> SimplFloats
-> OutExpr -> SimplM ([OutBind], OutExpr)
abstractFloats :: UnfoldingOpts
-> TopLevelFlag
-> [Id]
-> SimplFloats
-> Expr Id
-> SimplM ([Bind Id], Expr Id)
abstractFloats UnfoldingOpts
uf_opts TopLevelFlag
top_lvl [Id]
main_tvs SimplFloats
floats Expr Id
body
= ASSERT( notNull body_floats )
ASSERT( isNilOL (sfJoinFloats floats) )
do { (Subst
subst, [Bind Id]
float_binds) <- forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM Subst -> Bind Id -> SimplM (Subst, Bind Id)
abstract Subst
empty_subst [Bind Id]
body_floats
; forall (m :: * -> *) a. Monad m => a -> m a
return ([Bind Id]
float_binds, HasDebugCallStack => Subst -> Expr Id -> Expr Id
GHC.Core.Subst.substExpr Subst
subst Expr Id
body) }
where
is_top_lvl :: Bool
is_top_lvl = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
main_tv_set :: TyCoVarSet
main_tv_set = [Id] -> TyCoVarSet
mkVarSet [Id]
main_tvs
body_floats :: [Bind Id]
body_floats = LetFloats -> [Bind Id]
letFloatBinds (SimplFloats -> LetFloats
sfLetFloats SimplFloats
floats)
empty_subst :: Subst
empty_subst = InScopeSet -> Subst
GHC.Core.Subst.mkEmptySubst (SimplFloats -> InScopeSet
sfInScope SimplFloats
floats)
abstract :: GHC.Core.Subst.Subst -> OutBind -> SimplM (GHC.Core.Subst.Subst, OutBind)
abstract :: Subst -> Bind Id -> SimplM (Subst, Bind Id)
abstract Subst
subst (NonRec Id
id Expr Id
rhs)
= do { (Id
poly_id1, Expr Id
poly_app) <- [Id] -> Id -> SimplM (Id, Expr Id)
mk_poly1 [Id]
tvs_here Id
id
; let (Id
poly_id2, Expr Id
poly_rhs) = Id -> [Id] -> Expr Id -> (Id, Expr Id)
mk_poly2 Id
poly_id1 [Id]
tvs_here Expr Id
rhs'
!subst' :: Subst
subst' = Subst -> Id -> Expr Id -> Subst
GHC.Core.Subst.extendIdSubst Subst
subst Id
id Expr Id
poly_app
; forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
subst', forall b. b -> Expr b -> Bind b
NonRec Id
poly_id2 Expr Id
poly_rhs) }
where
rhs' :: Expr Id
rhs' = HasDebugCallStack => Subst -> Expr Id -> Expr Id
GHC.Core.Subst.substExpr Subst
subst Expr Id
rhs
tvs_here :: [Id]
tvs_here = [Id] -> [Id]
scopedSort forall a b. (a -> b) -> a -> b
$
forall a. (a -> Bool) -> [a] -> [a]
filter (Id -> TyCoVarSet -> Bool
`elemVarSet` TyCoVarSet
main_tv_set) forall a b. (a -> b) -> a -> b
$
[Id] -> [Id]
closeOverKindsList forall a b. (a -> b) -> a -> b
$
(Id -> Bool) -> Expr Id -> [Id]
exprSomeFreeVarsList Id -> Bool
isTyVar Expr Id
rhs'
abstract Subst
subst (Rec [(Id, Expr Id)]
prs)
= do { ([Id]
poly_ids, [Expr Id]
poly_apps) <- forall (m :: * -> *) a b c.
Applicative m =>
(a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM ([Id] -> Id -> SimplM (Id, Expr Id)
mk_poly1 [Id]
tvs_here) [Id]
ids
; let subst' :: Subst
subst' = Subst -> [(Id, Expr Id)] -> Subst
GHC.Core.Subst.extendSubstList Subst
subst ([Id]
ids forall a b. [a] -> [b] -> [(a, b)]
`zip` [Expr Id]
poly_apps)
poly_pairs :: [(Id, Expr Id)]
poly_pairs = [ Id -> [Id] -> Expr Id -> (Id, Expr Id)
mk_poly2 Id
poly_id [Id]
tvs_here Expr Id
rhs'
| (Id
poly_id, Expr Id
rhs) <- [Id]
poly_ids forall a b. [a] -> [b] -> [(a, b)]
`zip` [Expr Id]
rhss
, let rhs' :: Expr Id
rhs' = HasDebugCallStack => Subst -> Expr Id -> Expr Id
GHC.Core.Subst.substExpr Subst
subst' Expr Id
rhs ]
; forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
subst', forall b. [(b, Expr b)] -> Bind b
Rec [(Id, Expr Id)]
poly_pairs) }
where
([Id]
ids,[Expr Id]
rhss) = forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Expr Id)]
prs
tvs_here :: [Id]
tvs_here = [Id] -> [Id]
scopedSort [Id]
main_tvs
mk_poly1 :: [TyVar] -> Id -> SimplM (Id, CoreExpr)
mk_poly1 :: [Id] -> Id -> SimplM (Id, Expr Id)
mk_poly1 [Id]
tvs_here Id
var
= do { Unique
uniq <- forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let poly_name :: Name
poly_name = Name -> Unique -> Name
setNameUnique (Id -> Name
idName Id
var) Unique
uniq
poly_ty :: OutType
poly_ty = [Id] -> OutType -> OutType
mkInfForAllTys [Id]
tvs_here (Id -> OutType
idType Id
var)
poly_id :: Id
poly_id = Id -> [Id] -> Id -> Id
transferPolyIdInfo Id
var [Id]
tvs_here forall a b. (a -> b) -> a -> b
$
HasDebugCallStack => Name -> OutType -> OutType -> Id
mkLocalId Name
poly_name (Id -> OutType
idMult Id
var) OutType
poly_ty
; forall (m :: * -> *) a. Monad m => a -> m a
return (Id
poly_id, forall b. Expr b -> [OutType] -> Expr b
mkTyApps (forall b. Id -> Expr b
Var Id
poly_id) ([Id] -> [OutType]
mkTyVarTys [Id]
tvs_here)) }
mk_poly2 :: Id -> [TyVar] -> CoreExpr -> (Id, CoreExpr)
mk_poly2 :: Id -> [Id] -> Expr Id -> (Id, Expr Id)
mk_poly2 Id
poly_id [Id]
tvs_here Expr Id
rhs
= (Id
poly_id Id -> Unfolding -> Id
`setIdUnfolding` Unfolding
unf, Expr Id
poly_rhs)
where
poly_rhs :: Expr Id
poly_rhs = forall b. [b] -> Expr b -> Expr b
mkLams [Id]
tvs_here Expr Id
rhs
unf :: Unfolding
unf = UnfoldingOpts
-> UnfoldingSource -> Bool -> Bool -> Expr Id -> Unfolding
mkUnfolding UnfoldingOpts
uf_opts UnfoldingSource
InlineRhs Bool
is_top_lvl Bool
False Expr Id
poly_rhs
prepareAlts :: OutExpr -> OutId -> [InAlt] -> SimplM ([AltCon], [InAlt])
prepareAlts :: Expr Id -> Id -> [InAlt] -> SimplM ([AltCon], [InAlt])
prepareAlts Expr Id
scrut Id
case_bndr' [InAlt]
alts
| Just (TyCon
tc, [OutType]
tys) <- HasDebugCallStack => OutType -> Maybe (TyCon, [OutType])
splitTyConApp_maybe (Id -> OutType
varType Id
case_bndr')
= do { [Unique]
us <- forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let ([AltCon]
idcs1, [InAlt]
alts1) = forall b.
TyCon -> [OutType] -> [AltCon] -> [Alt b] -> ([AltCon], [Alt b])
filterAlts TyCon
tc [OutType]
tys [AltCon]
imposs_cons [InAlt]
alts
(Bool
yes2, [InAlt]
alts2) = [Unique]
-> OutType
-> TyCon
-> [OutType]
-> [AltCon]
-> [InAlt]
-> (Bool, [InAlt])
refineDefaultAlt [Unique]
us (Id -> OutType
idMult Id
case_bndr') TyCon
tc [OutType]
tys [AltCon]
idcs1 [InAlt]
alts1
(Bool
yes3, [AltCon]
idcs3, [InAlt]
alts3) = [AltCon] -> [InAlt] -> (Bool, [AltCon], [InAlt])
combineIdenticalAlts [AltCon]
idcs1 [InAlt]
alts2
; forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
yes2 forall a b. (a -> b) -> a -> b
$ Tick -> SimplM ()
tick (Id -> Tick
FillInCaseDefault Id
case_bndr')
; forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
yes3 forall a b. (a -> b) -> a -> b
$ Tick -> SimplM ()
tick (Id -> Tick
AltMerge Id
case_bndr')
; forall (m :: * -> *) a. Monad m => a -> m a
return ([AltCon]
idcs3, [InAlt]
alts3) }
| Bool
otherwise
= forall (m :: * -> *) a. Monad m => a -> m a
return ([], [InAlt]
alts)
where
imposs_cons :: [AltCon]
imposs_cons = case Expr Id
scrut of
Var Id
v -> Unfolding -> [AltCon]
otherCons (Id -> Unfolding
idUnfolding Id
v)
Expr Id
_ -> []
mkCase, mkCase1, mkCase2, mkCase3
:: DynFlags
-> OutExpr -> OutId
-> OutType -> [OutAlt]
-> SimplM OutExpr
mkCase :: DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase DynFlags
dflags Expr Id
scrut Id
outer_bndr OutType
alts_ty (Alt AltCon
DEFAULT [Id]
_ Expr Id
deflt_rhs : [InAlt]
outer_alts)
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CaseMerge DynFlags
dflags
, ([CoreTickish]
ticks, Case (Var Id
inner_scrut_var) Id
inner_bndr OutType
_ [InAlt]
inner_alts)
<- forall b.
(CoreTickish -> Bool) -> Expr b -> ([CoreTickish], Expr b)
stripTicksTop forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Id
deflt_rhs
, Id
inner_scrut_var forall a. Eq a => a -> a -> Bool
== Id
outer_bndr
= do { Tick -> SimplM ()
tick (Id -> Tick
CaseMerge Id
outer_bndr)
; let wrap_alt :: InAlt -> InAlt
wrap_alt (Alt AltCon
con [Id]
args Expr Id
rhs) = ASSERT( outer_bndr `notElem` args )
(forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [Id]
args (Expr Id -> Expr Id
wrap_rhs Expr Id
rhs))
wrap_rhs :: Expr Id -> Expr Id
wrap_rhs Expr Id
rhs = forall b. Bind b -> Expr b -> Expr b
Let (forall b. b -> Expr b -> Bind b
NonRec Id
inner_bndr (forall b. Id -> Expr b
Var Id
outer_bndr)) Expr Id
rhs
wrapped_alts :: [InAlt]
wrapped_alts | Id -> Bool
isDeadBinder Id
inner_bndr = [InAlt]
inner_alts
| Bool
otherwise = forall a b. (a -> b) -> [a] -> [b]
map InAlt -> InAlt
wrap_alt [InAlt]
inner_alts
merged_alts :: [InAlt]
merged_alts = forall a. [Alt a] -> [Alt a] -> [Alt a]
mergeAlts [InAlt]
outer_alts [InAlt]
wrapped_alts
; forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([CoreTickish] -> Expr Id -> Expr Id
mkTicks [CoreTickish]
ticks) forall a b. (a -> b) -> a -> b
$
DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase1 DynFlags
dflags Expr Id
scrut Id
outer_bndr OutType
alts_ty [InAlt]
merged_alts
}
mkCase DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts = DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase1 DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts
mkCase1 :: DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase1 DynFlags
_dflags Expr Id
scrut Id
case_bndr OutType
_ alts :: [InAlt]
alts@(Alt AltCon
_ [Id]
_ Expr Id
rhs1 : [InAlt]
_)
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all InAlt -> Bool
identity_alt [InAlt]
alts
= do { Tick -> SimplM ()
tick (Id -> Tick
CaseIdentity Id
case_bndr)
; forall (m :: * -> *) a. Monad m => a -> m a
return ([CoreTickish] -> Expr Id -> Expr Id
mkTicks [CoreTickish]
ticks forall a b. (a -> b) -> a -> b
$ forall {b} {b}. Expr b -> Expr b -> Expr b
re_cast Expr Id
scrut Expr Id
rhs1) }
where
ticks :: [CoreTickish]
ticks = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Alt AltCon
_ [Id]
_ Expr Id
rhs) -> forall b. (CoreTickish -> Bool) -> Expr b -> [CoreTickish]
stripTicksT forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Id
rhs) (forall a. [a] -> [a]
tail [InAlt]
alts)
identity_alt :: InAlt -> Bool
identity_alt (Alt AltCon
con [Id]
args Expr Id
rhs) = Expr Id -> AltCon -> [Id] -> Bool
check_eq Expr Id
rhs AltCon
con [Id]
args
check_eq :: Expr Id -> AltCon -> [Id] -> Bool
check_eq (Cast Expr Id
rhs OutCoercion
co) AltCon
con [Id]
args
= Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Id -> TyCoVarSet -> Bool
`elemVarSet` OutCoercion -> TyCoVarSet
tyCoVarsOfCo OutCoercion
co) [Id]
args) Bool -> Bool -> Bool
&& Expr Id -> AltCon -> [Id] -> Bool
check_eq Expr Id
rhs AltCon
con [Id]
args
check_eq (Tick CoreTickish
t Expr Id
e) AltCon
alt [Id]
args
= forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
t Bool -> Bool -> Bool
&& Expr Id -> AltCon -> [Id] -> Bool
check_eq Expr Id
e AltCon
alt [Id]
args
check_eq (Lit Literal
lit) (LitAlt Literal
lit') [Id]
_ = Literal
lit forall a. Eq a => a -> a -> Bool
== Literal
lit'
check_eq (Var Id
v) AltCon
_ [Id]
_ | Id
v forall a. Eq a => a -> a -> Bool
== Id
case_bndr = Bool
True
check_eq (Var Id
v) (DataAlt DataCon
con) [Id]
args
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [OutType]
arg_tys, forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
args = Id
v forall a. Eq a => a -> a -> Bool
== DataCon -> Id
dataConWorkId DataCon
con
check_eq Expr Id
rhs (DataAlt DataCon
con) [Id]
args = forall b. (CoreTickish -> Bool) -> Expr b -> Expr b -> Bool
cheapEqExpr' forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Id
rhs forall a b. (a -> b) -> a -> b
$
forall b. DataCon -> [OutType] -> [Id] -> Expr b
mkConApp2 DataCon
con [OutType]
arg_tys [Id]
args
check_eq Expr Id
_ AltCon
_ [Id]
_ = Bool
False
arg_tys :: [OutType]
arg_tys = OutType -> [OutType]
tyConAppArgs (Id -> OutType
idType Id
case_bndr)
re_cast :: Expr b -> Expr b -> Expr b
re_cast Expr b
scrut (Cast Expr b
rhs OutCoercion
co) = forall b. Expr b -> OutCoercion -> Expr b
Cast (Expr b -> Expr b -> Expr b
re_cast Expr b
scrut Expr b
rhs) OutCoercion
co
re_cast Expr b
scrut Expr b
_ = Expr b
scrut
mkCase1 DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts = DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase2 DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts
mkCase2 :: DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase2 DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts
|
case [InAlt]
alts of
[Alt AltCon
DEFAULT [Id]
_ Expr Id
_] -> Bool
False
[InAlt]
_ -> Bool
True
, GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CaseFolding DynFlags
dflags
, Just (Expr Id
scrut', AltCon -> Maybe AltCon
tx_con, Id -> Expr Id
mk_orig) <- Platform
-> Expr Id
-> Maybe (Expr Id, AltCon -> Maybe AltCon, Id -> Expr Id)
caseRules (DynFlags -> Platform
targetPlatform DynFlags
dflags) Expr Id
scrut
= do { Id
bndr' <- FastString -> OutType -> OutType -> SimplM Id
newId (String -> FastString
fsLit String
"lwild") OutType
Many (Expr Id -> OutType
exprType Expr Id
scrut')
; [InAlt]
alts' <- forall (m :: * -> *) a b.
Applicative m =>
(a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM ((AltCon -> Maybe AltCon)
-> (Id -> Expr Id) -> Id -> InAlt -> SimplM (Maybe InAlt)
tx_alt AltCon -> Maybe AltCon
tx_con Id -> Expr Id
mk_orig Id
bndr') [InAlt]
alts
; DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase3 DynFlags
dflags Expr Id
scrut' Id
bndr' OutType
alts_ty forall a b. (a -> b) -> a -> b
$
[InAlt] -> [InAlt]
add_default ([InAlt] -> [InAlt]
re_sort [InAlt]
alts')
}
| Bool
otherwise
= DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase3 DynFlags
dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts
where
tx_alt :: (AltCon -> Maybe AltCon) -> (Id -> CoreExpr) -> Id
-> CoreAlt -> SimplM (Maybe CoreAlt)
tx_alt :: (AltCon -> Maybe AltCon)
-> (Id -> Expr Id) -> Id -> InAlt -> SimplM (Maybe InAlt)
tx_alt AltCon -> Maybe AltCon
tx_con Id -> Expr Id
mk_orig Id
new_bndr (Alt AltCon
con [Id]
bs Expr Id
rhs)
= case AltCon -> Maybe AltCon
tx_con AltCon
con of
Maybe AltCon
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
Just AltCon
con' -> do { [Id]
bs' <- forall {m :: * -> *}. MonadUnique m => Id -> AltCon -> m [Id]
mk_new_bndrs Id
new_bndr AltCon
con'
; forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con' [Id]
bs' Expr Id
rhs')) }
where
rhs' :: Expr Id
rhs' | Id -> Bool
isDeadBinder Id
bndr = Expr Id
rhs
| Bool
otherwise = Id -> Expr Id -> Expr Id -> Expr Id
bindNonRec Id
bndr Expr Id
orig_val Expr Id
rhs
orig_val :: Expr Id
orig_val = case AltCon
con of
AltCon
DEFAULT -> Id -> Expr Id
mk_orig Id
new_bndr
LitAlt Literal
l -> forall b. Literal -> Expr b
Lit Literal
l
DataAlt DataCon
dc -> forall b. DataCon -> [OutType] -> [Id] -> Expr b
mkConApp2 DataCon
dc (OutType -> [OutType]
tyConAppArgs (Id -> OutType
idType Id
bndr)) [Id]
bs
mk_new_bndrs :: Id -> AltCon -> m [Id]
mk_new_bndrs Id
new_bndr (DataAlt DataCon
dc)
| Bool -> Bool
not (DataCon -> Bool
isNullaryRepDataCon DataCon
dc)
=
do { [Unique]
us <- forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let ([Id]
ex_tvs, [Id]
arg_ids) = [Unique] -> OutType -> DataCon -> [OutType] -> ([Id], [Id])
dataConRepInstPat [Unique]
us (Id -> OutType
idMult Id
new_bndr) DataCon
dc
(OutType -> [OutType]
tyConAppArgs (Id -> OutType
idType Id
new_bndr))
; forall (m :: * -> *) a. Monad m => a -> m a
return ([Id]
ex_tvs forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids) }
mk_new_bndrs Id
_ AltCon
_ = forall (m :: * -> *) a. Monad m => a -> m a
return []
re_sort :: [CoreAlt] -> [CoreAlt]
re_sort :: [InAlt] -> [InAlt]
re_sort [InAlt]
alts = forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy forall a. Alt a -> Alt a -> Ordering
cmpAlt [InAlt]
alts
add_default :: [CoreAlt] -> [CoreAlt]
add_default :: [InAlt] -> [InAlt]
add_default (Alt (LitAlt {}) [Id]
bs Expr Id
rhs : [InAlt]
alts) = forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [Id]
bs Expr Id
rhs forall a. a -> [a] -> [a]
: [InAlt]
alts
add_default [InAlt]
alts = [InAlt]
alts
mkCase3 :: DynFlags -> Expr Id -> Id -> OutType -> [InAlt] -> SimplM (Expr Id)
mkCase3 DynFlags
_dflags Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts
= forall (m :: * -> *) a. Monad m => a -> m a
return (forall b. Expr b -> b -> OutType -> [Alt b] -> Expr b
Case Expr Id
scrut Id
bndr OutType
alts_ty [InAlt]
alts)
isExitJoinId :: Var -> Bool
isExitJoinId :: Id -> Bool
isExitJoinId Id
id
= Id -> Bool
isJoinId Id
id
Bool -> Bool -> Bool
&& OccInfo -> Bool
isOneOcc (Id -> OccInfo
idOccInfo Id
id)
Bool -> Bool -> Bool
&& OccInfo -> InsideLam
occ_in_lam (Id -> OccInfo
idOccInfo Id
id) forall a. Eq a => a -> a -> Bool
== InsideLam
IsInsideLam