{-# LANGUAGE CPP #-}
module SimplUtils (
mkLam, mkCase, prepareAlts, tryEtaExpandRhs,
preInlineUnconditionally, postInlineUnconditionally,
activeUnfolding, activeRule,
getUnfoldingInRuleMatch,
simplEnvForGHCi, updModeForStableUnfoldings, updModeForRules,
SimplCont(..), DupFlag(..), StaticEnv,
isSimplified, contIsStop,
contIsDupable, contResultType, contHoleType,
contIsTrivial, contArgs,
countArgs,
mkBoringStop, mkRhsStop, mkLazyArgStop, contIsRhsOrArg,
interestingCallContext,
ArgInfo(..), ArgSpec(..), mkArgInfo,
addValArgTo, addCastTo, addTyArgTo,
argInfoExpr, argInfoAppArgs, pushSimplifiedArgs,
abstractFloats,
isExitJoinId
) where
#include "HsVersions.h"
import GhcPrelude
import SimplEnv
import CoreMonad ( SimplMode(..), Tick(..) )
import DynFlags
import CoreSyn
import qualified CoreSubst
import PprCore
import CoreFVs
import CoreUtils
import CoreArity
import CoreUnfold
import Name
import Id
import IdInfo
import Var
import Demand
import SimplMonad
import Type hiding( substTy )
import Coercion hiding( substCo )
import DataCon ( dataConWorkId, isNullaryRepDataCon )
import VarSet
import BasicTypes
import Util
import OrdList ( isNilOL )
import MonadUtils
import Outputable
import Pair
import PrelRules
import 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 -> InExpr
sc_arg :: InExpr
, SimplCont -> StaticEnv
sc_env :: StaticEnv
, SimplCont -> SimplCont
sc_cont :: SimplCont }
| ApplyToTy
{ SimplCont -> OutType
sc_arg_ty :: OutType
, SimplCont -> OutType
sc_hole_ty :: OutType
, sc_cont :: SimplCont }
| Select
{ sc_dup :: DupFlag
, SimplCont -> InId
sc_bndr :: InId
, SimplCont -> [InAlt]
sc_alts :: [InAlt]
, sc_env :: StaticEnv
, sc_cont :: SimplCont }
| StrictBind
{ sc_dup :: DupFlag
, sc_bndr :: InId
, SimplCont -> [InId]
sc_bndrs :: [InBndr]
, SimplCont -> InExpr
sc_body :: InExpr
, sc_env :: StaticEnv
, sc_cont :: SimplCont }
| StrictArg
{ sc_dup :: DupFlag
, SimplCont -> ArgInfo
sc_fun :: ArgInfo
, SimplCont -> CallCtxt
sc_cci :: CallCtxt
, sc_cont :: SimplCont }
| TickIt
(Tickish Id)
SimplCont
type StaticEnv = SimplEnv
data DupFlag = NoDup
| Simplified
| OkToDup
isSimplified :: DupFlag -> Bool
isSimplified :: DupFlag -> Bool
isSimplified NoDup = Bool
False
isSimplified _ = Bool
True
perhapsSubstTy :: DupFlag -> StaticEnv -> Type -> Type
perhapsSubstTy :: DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy dup :: DupFlag
dup env :: StaticEnv
env ty :: 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 OkToDup = String -> SDoc
text "ok"
ppr NoDup = String -> SDoc
text "nodup"
ppr Simplified = String -> SDoc
text "simpl"
instance Outputable SimplCont where
ppr :: SimplCont -> SDoc
ppr (Stop ty :: OutType
ty interesting :: CallCtxt
interesting) = String -> SDoc
text "Stop" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
brackets (CallCtxt -> SDoc
forall a. Outputable a => a -> SDoc
ppr CallCtxt
interesting) SDoc -> SDoc -> SDoc
<+> OutType -> SDoc
forall a. Outputable a => a -> SDoc
ppr OutType
ty
ppr (CastIt co :: OutCoercion
co cont :: SimplCont
cont ) = (String -> SDoc
text "CastIt" SDoc -> SDoc -> SDoc
<+> OutCoercion -> SDoc
pprOptCo OutCoercion
co) SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (TickIt t :: Tickish InId
t cont :: SimplCont
cont) = (String -> SDoc
text "TickIt" SDoc -> SDoc -> SDoc
<+> Tickish InId -> SDoc
forall a. Outputable a => a -> SDoc
ppr Tickish InId
t) SDoc -> SDoc -> SDoc
$$ SimplCont -> 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 "ApplyToTy" SDoc -> SDoc -> SDoc
<+> OutType -> SDoc
pprParendType OutType
ty) SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (ApplyToVal { sc_arg :: SimplCont -> InExpr
sc_arg = InExpr
arg, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text "ApplyToVal" SDoc -> SDoc -> SDoc
<+> DupFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr DupFlag
dup SDoc -> SDoc -> SDoc
<+> InExpr -> SDoc
forall b. OutputableBndr b => Expr b -> SDoc
pprParendExpr InExpr
arg)
SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (StrictBind { sc_bndr :: SimplCont -> InId
sc_bndr = InId
b, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= (String -> SDoc
text "StrictBind" SDoc -> SDoc -> SDoc
<+> InId -> SDoc
forall a. Outputable a => a -> SDoc
ppr InId
b) SDoc -> SDoc -> SDoc
$$ SimplCont -> 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 "StrictArg" SDoc -> SDoc -> SDoc
<+> InId -> SDoc
forall a. Outputable a => a -> SDoc
ppr (ArgInfo -> InId
ai_fun ArgInfo
ai)) SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
ppr (Select { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_bndr :: SimplCont -> InId
sc_bndr = InId
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 "Select" SDoc -> SDoc -> SDoc
<+> DupFlag -> SDoc
forall a. Outputable a => a -> SDoc
ppr DupFlag
dup SDoc -> SDoc -> SDoc
<+> InId -> SDoc
forall a. Outputable a => a -> SDoc
ppr InId
bndr) SDoc -> SDoc -> SDoc
$$
SDoc -> SDoc
whenPprDebug (Int -> SDoc -> SDoc
nest 2 (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
vcat [TvSubstEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr (StaticEnv -> TvSubstEnv
seTvSubst StaticEnv
se), [InAlt] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InAlt]
alts]) SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
data ArgInfo
= ArgInfo {
ArgInfo -> InId
ai_fun :: OutId,
ArgInfo -> [ArgSpec]
ai_args :: [ArgSpec],
ArgInfo -> OutType
ai_type :: OutType,
ArgInfo -> FunRules
ai_rules :: FunRules,
ArgInfo -> Bool
ai_encl :: Bool,
ArgInfo -> [Bool]
ai_strs :: [Bool],
ArgInfo -> [Int]
ai_discs :: [Int]
}
data ArgSpec
= ValArg OutExpr
| TyArg { ArgSpec -> OutType
as_arg_ty :: OutType
, ArgSpec -> OutType
as_hole_ty :: OutType }
| CastBy OutCoercion
instance Outputable ArgSpec where
ppr :: ArgSpec -> SDoc
ppr (ValArg e :: InExpr
e) = String -> SDoc
text "ValArg" SDoc -> SDoc -> SDoc
<+> InExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InExpr
e
ppr (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty }) = String -> SDoc
text "TyArg" SDoc -> SDoc -> SDoc
<+> OutType -> SDoc
forall a. Outputable a => a -> SDoc
ppr OutType
ty
ppr (CastBy c :: OutCoercion
c) = String -> SDoc
text "CastBy" SDoc -> SDoc -> SDoc
<+> OutCoercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr OutCoercion
c
addValArgTo :: ArgInfo -> OutExpr -> ArgInfo
addValArgTo :: ArgInfo -> InExpr -> ArgInfo
addValArgTo ai :: ArgInfo
ai arg :: InExpr
arg = ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = InExpr -> ArgSpec
ValArg InExpr
arg ArgSpec -> [ArgSpec] -> [ArgSpec]
forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai
, ai_type :: OutType
ai_type = OutType -> InExpr -> OutType
applyTypeToArg (ArgInfo -> OutType
ai_type ArgInfo
ai) InExpr
arg
, ai_rules :: FunRules
ai_rules = FunRules -> FunRules
decRules (ArgInfo -> FunRules
ai_rules ArgInfo
ai) }
addTyArgTo :: ArgInfo -> OutType -> ArgInfo
addTyArgTo :: ArgInfo -> OutType -> ArgInfo
addTyArgTo ai :: ArgInfo
ai arg_ty :: OutType
arg_ty = ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = ArgSpec
arg_spec ArgSpec -> [ArgSpec] -> [ArgSpec]
forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai
, ai_type :: OutType
ai_type = HasDebugCallStack => OutType -> OutType -> OutType
OutType -> OutType -> OutType
piResultTy OutType
poly_fun_ty OutType
arg_ty
, ai_rules :: FunRules
ai_rules = FunRules -> FunRules
decRules (ArgInfo -> FunRules
ai_rules ArgInfo
ai) }
where
poly_fun_ty :: OutType
poly_fun_ty = ArgInfo -> OutType
ai_type ArgInfo
ai
arg_spec :: ArgSpec
arg_spec = TyArg :: OutType -> OutType -> ArgSpec
TyArg { as_arg_ty :: OutType
as_arg_ty = OutType
arg_ty, as_hole_ty :: OutType
as_hole_ty = OutType
poly_fun_ty }
addCastTo :: ArgInfo -> OutCoercion -> ArgInfo
addCastTo :: ArgInfo -> OutCoercion -> ArgInfo
addCastTo ai :: ArgInfo
ai co :: OutCoercion
co = ArgInfo
ai { ai_args :: [ArgSpec]
ai_args = OutCoercion -> ArgSpec
CastBy OutCoercion
co ArgSpec -> [ArgSpec] -> [ArgSpec]
forall a. a -> [a] -> [a]
: ArgInfo -> [ArgSpec]
ai_args ArgInfo
ai
, ai_type :: OutType
ai_type = Pair OutType -> OutType
forall a. Pair a -> a
pSnd (OutCoercion -> Pair OutType
coercionKind OutCoercion
co) }
argInfoAppArgs :: [ArgSpec] -> [OutExpr]
argInfoAppArgs :: [ArgSpec] -> [InExpr]
argInfoAppArgs [] = []
argInfoAppArgs (CastBy {} : _) = []
argInfoAppArgs (ValArg e :: InExpr
e : as :: [ArgSpec]
as) = InExpr
e InExpr -> [InExpr] -> [InExpr]
forall a. a -> [a] -> [a]
: [ArgSpec] -> [InExpr]
argInfoAppArgs [ArgSpec]
as
argInfoAppArgs (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty } : as :: [ArgSpec]
as) = OutType -> InExpr
forall b. OutType -> Expr b
Type OutType
ty InExpr -> [InExpr] -> [InExpr]
forall a. a -> [a] -> [a]
: [ArgSpec] -> [InExpr]
argInfoAppArgs [ArgSpec]
as
pushSimplifiedArgs :: SimplEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs :: StaticEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs _env :: StaticEnv
_env [] k :: SimplCont
k = SimplCont
k
pushSimplifiedArgs env :: StaticEnv
env (arg :: ArgSpec
arg : args :: [ArgSpec]
args) k :: 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 :: OutType -> OutType -> SimplCont -> SimplCont
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 e :: InExpr
e -> ApplyToVal :: DupFlag -> InExpr -> StaticEnv -> SimplCont -> SimplCont
ApplyToVal { sc_arg :: InExpr
sc_arg = InExpr
e, sc_env :: StaticEnv
sc_env = StaticEnv
env, sc_dup :: DupFlag
sc_dup = DupFlag
Simplified, sc_cont :: SimplCont
sc_cont = SimplCont
rest }
CastBy c :: 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 :: InId -> [ArgSpec] -> InExpr
argInfoExpr fun :: InId
fun rev_args :: [ArgSpec]
rev_args
= [ArgSpec] -> InExpr
go [ArgSpec]
rev_args
where
go :: [ArgSpec] -> InExpr
go [] = InId -> InExpr
forall b. InId -> Expr b
Var InId
fun
go (ValArg a :: InExpr
a : as :: [ArgSpec]
as) = [ArgSpec] -> InExpr
go [ArgSpec]
as InExpr -> InExpr -> InExpr
forall b. Expr b -> Expr b -> Expr b
`App` InExpr
a
go (TyArg { as_arg_ty :: ArgSpec -> OutType
as_arg_ty = OutType
ty } : as :: [ArgSpec]
as) = [ArgSpec] -> InExpr
go [ArgSpec]
as InExpr -> InExpr -> InExpr
forall b. Expr b -> Expr b -> Expr b
`App` OutType -> InExpr
forall b. OutType -> Expr b
Type OutType
ty
go (CastBy co :: OutCoercion
co : as :: [ArgSpec]
as) = InExpr -> OutCoercion -> InExpr
mkCast ([ArgSpec] -> InExpr
go [ArgSpec]
as) OutCoercion
co
type FunRules = Maybe (Int, [CoreRule])
decRules :: FunRules -> FunRules
decRules :: FunRules -> FunRules
decRules (Just (n :: Int
n, rules :: [CoreRule]
rules)) = (Int, [CoreRule]) -> FunRules
forall a. a -> Maybe a
Just (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1, [CoreRule]
rules)
decRules Nothing = FunRules
forall a. Maybe a
Nothing
mkFunRules :: [CoreRule] -> FunRules
mkFunRules :: [CoreRule] -> FunRules
mkFunRules [] = FunRules
forall a. Maybe a
Nothing
mkFunRules rs :: [CoreRule]
rs = (Int, [CoreRule]) -> FunRules
forall a. a -> Maybe a
Just (Int
n_required, [CoreRule]
rs)
where
n_required :: Int
n_required = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((CoreRule -> Int) -> [CoreRule] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map CoreRule -> Int
ruleArity [CoreRule]
rs)
mkBoringStop :: OutType -> SimplCont
mkBoringStop :: OutType -> SimplCont
mkBoringStop ty :: OutType
ty = OutType -> CallCtxt -> SimplCont
Stop OutType
ty CallCtxt
BoringCtxt
mkRhsStop :: OutType -> SimplCont
mkRhsStop :: OutType -> SimplCont
mkRhsStop ty :: OutType
ty = OutType -> CallCtxt -> SimplCont
Stop OutType
ty CallCtxt
RhsCtxt
mkLazyArgStop :: OutType -> CallCtxt -> SimplCont
mkLazyArgStop :: OutType -> CallCtxt -> SimplCont
mkLazyArgStop ty :: OutType
ty cci :: 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 _ = Bool
False
contIsRhs :: SimplCont -> Bool
contIsRhs :: SimplCont -> Bool
contIsRhs (Stop _ RhsCtxt) = Bool
True
contIsRhs _ = Bool
False
contIsStop :: SimplCont -> Bool
contIsStop :: SimplCont -> Bool
contIsStop (Stop {}) = Bool
True
contIsStop _ = 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 _ k :: SimplCont
k) = SimplCont -> Bool
contIsDupable SimplCont
k
contIsDupable _ = 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 -> InExpr
sc_arg = Coercion _, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> Bool
contIsTrivial SimplCont
k
contIsTrivial (CastIt _ k :: SimplCont
k) = SimplCont -> Bool
contIsTrivial SimplCont
k
contIsTrivial _ = Bool
False
contResultType :: SimplCont -> OutType
contResultType :: SimplCont -> OutType
contResultType (Stop ty :: OutType
ty _) = OutType
ty
contResultType (CastIt _ k :: 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 _ k :: SimplCont
k) = SimplCont -> OutType
contResultType SimplCont
k
contHoleType :: SimplCont -> OutType
contHoleType :: SimplCont -> OutType
contHoleType (Stop ty :: OutType
ty _) = OutType
ty
contHoleType (TickIt _ k :: SimplCont
k) = SimplCont -> OutType
contHoleType SimplCont
k
contHoleType (CastIt co :: OutCoercion
co _) = Pair OutType -> OutType
forall a. Pair a -> a
pFst (OutCoercion -> Pair OutType
coercionKind OutCoercion
co)
contHoleType (StrictBind { sc_bndr :: SimplCont -> InId
sc_bndr = InId
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 (InId -> OutType
idType InId
b)
contHoleType (StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
ai }) = OutType -> OutType
funArgTy (ArgInfo -> OutType
ai_type ArgInfo
ai)
contHoleType (ApplyToTy { sc_hole_ty :: SimplCont -> OutType
sc_hole_ty = OutType
ty }) = OutType
ty
contHoleType (ApplyToVal { sc_arg :: SimplCont -> InExpr
sc_arg = InExpr
e, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= OutType -> OutType -> OutType
mkFunTy (DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy DupFlag
dup StaticEnv
se (InExpr -> OutType
exprType InExpr
e))
(SimplCont -> OutType
contHoleType SimplCont
k)
contHoleType (Select { sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
d, sc_bndr :: SimplCont -> InId
sc_bndr = InId
b, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se })
= DupFlag -> StaticEnv -> OutType -> OutType
perhapsSubstTy DupFlag
d StaticEnv
se (InId -> OutType
idType InId
b)
countArgs :: SimplCont -> Int
countArgs :: SimplCont -> Int
countArgs (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }) = 1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ SimplCont -> Int
countArgs SimplCont
cont
countArgs (ApplyToVal { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }) = 1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ SimplCont -> Int
countArgs SimplCont
cont
countArgs _ = 0
contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
contArgs cont :: 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 _ = Bool
True
go :: [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go args :: [ArgSummary]
args (ApplyToVal { sc_arg :: SimplCont -> InExpr
sc_arg = InExpr
arg, sc_env :: SimplCont -> StaticEnv
sc_env = StaticEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go (InExpr -> StaticEnv -> ArgSummary
is_interesting InExpr
arg StaticEnv
se ArgSummary -> [ArgSummary] -> [ArgSummary]
forall a. a -> [a] -> [a]
: [ArgSummary]
args) SimplCont
k
go args :: [ArgSummary]
args (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [ArgSummary]
args SimplCont
k
go args :: [ArgSummary]
args (CastIt _ k :: SimplCont
k) = [ArgSummary] -> SimplCont -> (Bool, [ArgSummary], SimplCont)
go [ArgSummary]
args SimplCont
k
go args :: [ArgSummary]
args k :: SimplCont
k = (Bool
False, [ArgSummary] -> [ArgSummary]
forall a. [a] -> [a]
reverse [ArgSummary]
args, SimplCont
k)
is_interesting :: InExpr -> StaticEnv -> ArgSummary
is_interesting arg :: InExpr
arg se :: StaticEnv
se = StaticEnv -> InExpr -> ArgSummary
interestingArg StaticEnv
se InExpr
arg
mkArgInfo :: SimplEnv
-> Id
-> [CoreRule]
-> Int
-> SimplCont
-> ArgInfo
mkArgInfo :: StaticEnv -> InId -> [CoreRule] -> Int -> SimplCont -> ArgInfo
mkArgInfo env :: StaticEnv
env fun :: InId
fun rules :: [CoreRule]
rules n_val_args :: Int
n_val_args call_cont :: SimplCont
call_cont
| Int
n_val_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< InId -> Int
idArity InId
fun
= ArgInfo :: InId
-> [ArgSpec]
-> OutType
-> FunRules
-> Bool
-> [Bool]
-> [Int]
-> ArgInfo
ArgInfo { ai_fun :: InId
ai_fun = InId
fun, ai_args :: [ArgSpec]
ai_args = [], ai_type :: OutType
ai_type = OutType
fun_ty
, ai_rules :: FunRules
ai_rules = FunRules
fun_rules
, ai_encl :: Bool
ai_encl = Bool
False
, ai_strs :: [Bool]
ai_strs = [Bool]
vanilla_stricts
, ai_discs :: [Int]
ai_discs = [Int]
vanilla_discounts }
| Bool
otherwise
= ArgInfo :: InId
-> [ArgSpec]
-> OutType
-> FunRules
-> Bool
-> [Bool]
-> [Int]
-> ArgInfo
ArgInfo { ai_fun :: InId
ai_fun = InId
fun, ai_args :: [ArgSpec]
ai_args = [], ai_type :: OutType
ai_type = OutType
fun_ty
, ai_rules :: FunRules
ai_rules = FunRules
fun_rules
, ai_encl :: Bool
ai_encl = [CoreRule] -> SimplCont -> Bool
interestingArgContext [CoreRule]
rules SimplCont
call_cont
, ai_strs :: [Bool]
ai_strs = [Bool]
arg_stricts
, ai_discs :: [Int]
ai_discs = [Int]
arg_discounts }
where
fun_ty :: OutType
fun_ty = InId -> OutType
idType InId
fun
fun_rules :: FunRules
fun_rules = [CoreRule] -> FunRules
mkFunRules [CoreRule]
rules
vanilla_discounts, arg_discounts :: [Int]
vanilla_discounts :: [Int]
vanilla_discounts = Int -> [Int]
forall a. a -> [a]
repeat 0
arg_discounts :: [Int]
arg_discounts = case InId -> Unfolding
idUnfolding InId
fun of
CoreUnfolding {uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfIfGoodArgs {ug_args :: UnfoldingGuidance -> [Int]
ug_args = [Int]
discounts}}
-> [Int]
discounts [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int]
vanilla_discounts
_ -> [Int]
vanilla_discounts
vanilla_stricts, arg_stricts :: [Bool]
vanilla_stricts :: [Bool]
vanilla_stricts = Bool -> [Bool]
forall a. a -> [a]
repeat Bool
False
arg_stricts :: [Bool]
arg_stricts
| Bool -> Bool
not (SimplMode -> Bool
sm_inline (StaticEnv -> SimplMode
seMode StaticEnv
env))
= [Bool]
vanilla_stricts
| Bool
otherwise
= OutType -> [Bool] -> [Bool]
add_type_str OutType
fun_ty ([Bool] -> [Bool]) -> [Bool] -> [Bool]
forall a b. (a -> b) -> a -> b
$
case StrictSig -> ([Demand], DmdResult)
splitStrictSig (InId -> StrictSig
idStrictness InId
fun) of
(demands :: [Demand]
demands, result_info :: DmdResult
result_info)
| Bool -> Bool
not ([Demand]
demands [Demand] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthExceeds` Int
n_val_args)
->
if DmdResult -> Bool
isBotRes DmdResult
result_info then
(Demand -> Bool) -> [Demand] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd [Demand]
demands
else
(Demand -> Bool) -> [Demand] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd [Demand]
demands [Bool] -> [Bool] -> [Bool]
forall a. [a] -> [a] -> [a]
++ [Bool]
vanilla_stricts
| Bool
otherwise
-> WARN( True, text "More demands than arity" <+> ppr fun <+> ppr (idArity fun)
<+> ppr n_val_args <+> ppr demands )
[Bool]
vanilla_stricts
add_type_str :: Type -> [Bool] -> [Bool]
add_type_str :: OutType -> [Bool] -> [Bool]
add_type_str _ [] = []
add_type_str fun_ty :: OutType
fun_ty all_strs :: [Bool]
all_strs@(str :: Bool
str:strs :: [Bool]
strs)
| Just (arg_ty :: OutType
arg_ty, fun_ty' :: OutType
fun_ty') <- OutType -> Maybe (OutType, OutType)
splitFunTy_maybe OutType
fun_ty
= (Bool
str Bool -> Bool -> Bool
|| Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== HasDebugCallStack => OutType -> Maybe Bool
OutType -> Maybe Bool
isLiftedType_maybe OutType
arg_ty)
Bool -> [Bool] -> [Bool]
forall a. a -> [a] -> [a]
: OutType -> [Bool] -> [Bool]
add_type_str OutType
fun_ty' [Bool]
strs
| Just (_, fun_ty' :: OutType
fun_ty') <- OutType -> Maybe (InId, OutType)
splitForAllTy_maybe OutType
fun_ty
= OutType -> [Bool] -> [Bool]
add_type_str OutType
fun_ty' [Bool]
all_strs
| Bool
otherwise
= [Bool]
all_strs
interestingCallContext :: SimplEnv -> SimplCont -> CallCtxt
interestingCallContext :: StaticEnv -> SimplCont -> CallCtxt
interestingCallContext env :: StaticEnv
env cont :: 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_cci :: SimplCont -> CallCtxt
sc_cci = CallCtxt
cci }) = CallCtxt
cci
interesting (StrictBind {}) = CallCtxt
BoringCtxt
interesting (Stop _ cci :: CallCtxt
cci) = CallCtxt
cci
interesting (TickIt _ k :: SimplCont
k) = SimplCont -> CallCtxt
interesting SimplCont
k
interesting (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k }) = SimplCont -> CallCtxt
interesting SimplCont
k
interesting (CastIt _ k :: SimplCont
k) = SimplCont -> CallCtxt
interesting SimplCont
k
interestingArgContext :: [CoreRule] -> SimplCont -> Bool
interestingArgContext :: [CoreRule] -> SimplCont -> Bool
interestingArgContext rules :: [CoreRule]
rules call_cont :: SimplCont
call_cont
= [CoreRule] -> Bool
forall a. [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_cci :: SimplCont -> CallCtxt
sc_cci = CallCtxt
cci }) = CallCtxt -> Bool
interesting CallCtxt
cci
go (StrictBind {}) = Bool
False
go (CastIt _ c :: SimplCont
c) = SimplCont -> Bool
go SimplCont
c
go (Stop _ cci :: CallCtxt
cci) = CallCtxt -> Bool
interesting CallCtxt
cci
go (TickIt _ c :: SimplCont
c) = SimplCont -> Bool
go SimplCont
c
interesting :: CallCtxt -> Bool
interesting RuleArgCtxt = Bool
True
interesting _ = Bool
False
interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
interestingArg :: StaticEnv -> InExpr -> ArgSummary
interestingArg env :: StaticEnv
env e :: InExpr
e = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env 0 InExpr
e
where
go :: StaticEnv -> Int -> InExpr -> ArgSummary
go env :: StaticEnv
env n :: Int
n (Var v :: InId
v)
= case StaticEnv -> InId -> SimplSR
substId StaticEnv
env InId
v of
DoneId v' :: InId
v' -> Int -> InId -> ArgSummary
go_var Int
n InId
v'
DoneEx e :: InExpr
e _ -> StaticEnv -> Int -> InExpr -> ArgSummary
go (StaticEnv -> StaticEnv
zapSubstEnv StaticEnv
env) Int
n InExpr
e
ContEx tvs :: TvSubstEnv
tvs cvs :: CvSubstEnv
cvs ids :: SimplIdSubst
ids e :: InExpr
e -> StaticEnv -> Int -> InExpr -> ArgSummary
go (StaticEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> StaticEnv
setSubstEnv StaticEnv
env TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids) Int
n InExpr
e
go _ _ (Lit {}) = ArgSummary
ValueArg
go _ _ (Type _) = ArgSummary
TrivArg
go _ _ (Coercion _) = ArgSummary
TrivArg
go env :: StaticEnv
env n :: Int
n (App fn :: InExpr
fn (Type _)) = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env Int
n InExpr
fn
go env :: StaticEnv
env n :: Int
n (App fn :: InExpr
fn _) = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) InExpr
fn
go env :: StaticEnv
env n :: Int
n (Tick _ a :: InExpr
a) = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env Int
n InExpr
a
go env :: StaticEnv
env n :: Int
n (Cast e :: InExpr
e _) = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env Int
n InExpr
e
go env :: StaticEnv
env n :: Int
n (Lam v :: InId
v e :: InExpr
e)
| InId -> Bool
isTyVar InId
v = StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env Int
n InExpr
e
| Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>0 = ArgSummary
NonTrivArg
| Bool
otherwise = ArgSummary
ValueArg
go _ _ (Case {}) = ArgSummary
NonTrivArg
go env :: StaticEnv
env n :: Int
n (Let b :: Bind InId
b e :: InExpr
e) = case StaticEnv -> Int -> InExpr -> ArgSummary
go StaticEnv
env' Int
n InExpr
e of
ValueArg -> ArgSummary
ValueArg
_ -> ArgSummary
NonTrivArg
where
env' :: StaticEnv
env' = StaticEnv
env StaticEnv -> [InId] -> StaticEnv
`addNewInScopeIds` Bind InId -> [InId]
forall b. Bind b -> [b]
bindersOf Bind InId
b
go_var :: Int -> InId -> ArgSummary
go_var n :: Int
n v :: InId
v
| InId -> Bool
isConLikeId InId
v = ArgSummary
ValueArg
| InId -> Int
idArity InId
v Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n = ArgSummary
ValueArg
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 = ArgSummary
NonTrivArg
| Bool
conlike_unfolding = ArgSummary
ValueArg
| Bool
otherwise = ArgSummary
TrivArg
where
conlike_unfolding :: Bool
conlike_unfolding = Unfolding -> Bool
isConLikeUnfolding (InId -> Unfolding
idUnfolding InId
v)
simplEnvForGHCi :: DynFlags -> SimplEnv
simplEnvForGHCi :: DynFlags -> StaticEnv
simplEnvForGHCi dflags :: DynFlags
dflags
= SimplMode -> StaticEnv
mkSimplEnv (SimplMode -> StaticEnv) -> SimplMode -> StaticEnv
forall a b. (a -> b) -> a -> b
$ SimplMode :: [String]
-> CompilerPhase
-> DynFlags
-> Bool
-> Bool
-> Bool
-> Bool
-> SimplMode
SimplMode { sm_names :: [String]
sm_names = ["GHCi"]
, sm_phase :: CompilerPhase
sm_phase = CompilerPhase
InitialPhase
, sm_dflags :: DynFlags
sm_dflags = DynFlags
dflags
, 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_case_case :: Bool
sm_case_case = Bool
True }
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
updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
updModeForStableUnfoldings inline_rule_act :: Activation
inline_rule_act current_mode :: SimplMode
current_mode
= SimplMode
current_mode { sm_phase :: CompilerPhase
sm_phase = Activation -> CompilerPhase
phaseFromActivation Activation
inline_rule_act
, sm_inline :: Bool
sm_inline = Bool
True
, sm_eta_expand :: Bool
sm_eta_expand = Bool
False }
where
phaseFromActivation :: Activation -> CompilerPhase
phaseFromActivation (ActiveAfter _ n :: Int
n) = Int -> CompilerPhase
Phase Int
n
phaseFromActivation _ = CompilerPhase
InitialPhase
updModeForRules :: SimplMode -> SimplMode
updModeForRules :: SimplMode -> SimplMode
updModeForRules current_mode :: 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_eta_expand :: Bool
sm_eta_expand = Bool
False }
activeUnfolding :: SimplMode -> Id -> Bool
activeUnfolding :: SimplMode -> InId -> Bool
activeUnfolding mode :: SimplMode
mode id :: InId
id
| Unfolding -> Bool
isCompulsoryUnfolding (InId -> Unfolding
realIdUnfolding InId
id)
= Bool
True
| Bool
otherwise
= CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode) (InId -> Activation
idInlineActivation InId
id)
Bool -> Bool -> Bool
&& SimplMode -> Bool
sm_inline SimplMode
mode
getUnfoldingInRuleMatch :: SimplEnv -> InScopeEnv
getUnfoldingInRuleMatch :: StaticEnv -> InScopeEnv
getUnfoldingInRuleMatch env :: StaticEnv
env
= (InScopeSet
in_scope, InId -> Unfolding
id_unf)
where
in_scope :: InScopeSet
in_scope = StaticEnv -> InScopeSet
seInScope StaticEnv
env
mode :: SimplMode
mode = StaticEnv -> SimplMode
getMode StaticEnv
env
id_unf :: InId -> Unfolding
id_unf id :: InId
id | InId -> Bool
unf_is_active InId
id = InId -> Unfolding
idUnfolding InId
id
| Bool
otherwise = Unfolding
NoUnfolding
unf_is_active :: InId -> Bool
unf_is_active id :: InId
id
| Bool -> Bool
not (SimplMode -> Bool
sm_rules SimplMode
mode) =
Unfolding -> Bool
isStableUnfolding (InId -> Unfolding
realIdUnfolding InId
id)
| Bool
otherwise = CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase SimplMode
mode) (InId -> Activation
idInlineActivation InId
id)
activeRule :: SimplMode -> Activation -> Bool
activeRule :: SimplMode -> Activation -> Bool
activeRule mode :: SimplMode
mode
| Bool -> Bool
not (SimplMode -> Bool
sm_rules SimplMode
mode) = \_ -> 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 -> InId -> InExpr -> StaticEnv -> Maybe StaticEnv
preInlineUnconditionally env :: StaticEnv
env top_lvl :: TopLevelFlag
top_lvl bndr :: InId
bndr rhs :: InExpr
rhs rhs_env :: StaticEnv
rhs_env
| Bool -> Bool
not Bool
pre_inline_unconditionally = Maybe StaticEnv
forall a. Maybe a
Nothing
| Bool -> Bool
not Bool
active = Maybe StaticEnv
forall a. Maybe a
Nothing
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
&& InId -> Bool
isBottomingId InId
bndr = Maybe StaticEnv
forall a. Maybe a
Nothing
| InId -> Bool
isCoVar InId
bndr = Maybe StaticEnv
forall a. Maybe a
Nothing
| InId -> Bool
isExitJoinId InId
bndr = Maybe StaticEnv
forall a. Maybe a
Nothing
| Bool -> Bool
not (OccInfo -> Bool
one_occ (InId -> OccInfo
idOccInfo InId
bndr)) = Maybe StaticEnv
forall a. Maybe a
Nothing
| Bool -> Bool
not (Unfolding -> Bool
isStableUnfolding Unfolding
unf) = StaticEnv -> Maybe StaticEnv
forall a. a -> Maybe a
Just (InExpr -> StaticEnv
extend_subst_with InExpr
rhs)
| InlinePragma -> Bool
isInlinablePragma InlinePragma
inline_prag
, Just inl :: InExpr
inl <- Unfolding -> Maybe InExpr
maybeUnfoldingTemplate Unfolding
unf = StaticEnv -> Maybe StaticEnv
forall a. a -> Maybe a
Just (InExpr -> StaticEnv
extend_subst_with InExpr
inl)
| Bool
otherwise = Maybe StaticEnv
forall a. Maybe a
Nothing
where
unf :: Unfolding
unf = InId -> Unfolding
idUnfolding InId
bndr
extend_subst_with :: InExpr -> StaticEnv
extend_subst_with inl_rhs :: InExpr
inl_rhs = StaticEnv -> InId -> SimplSR -> StaticEnv
extendIdSubst StaticEnv
env InId
bndr (StaticEnv -> InExpr -> SimplSR
mkContEx StaticEnv
rhs_env InExpr
inl_rhs)
one_occ :: OccInfo -> Bool
one_occ IAmDead = Bool
True
one_occ (OneOcc { occ_one_br :: OccInfo -> Bool
occ_one_br = Bool
True
, occ_in_lam :: OccInfo -> Bool
occ_in_lam = Bool
in_lam
, occ_int_cxt :: OccInfo -> Bool
occ_int_cxt = Bool
int_cxt })
| Bool -> Bool
not Bool
in_lam = TopLevelFlag -> Bool
isNotTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
|| Bool
early_phase
| Bool
otherwise = Bool
int_cxt Bool -> Bool -> Bool
&& InExpr -> Bool
canInlineInLam InExpr
rhs
one_occ _ = Bool
False
pre_inline_unconditionally :: Bool
pre_inline_unconditionally = GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SimplPreInlining (StaticEnv -> DynFlags
seDynFlags StaticEnv
env)
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 = InId -> InlinePragma
idInlinePragma InId
bndr
canInlineInLam :: InExpr -> Bool
canInlineInLam (Lit _) = Bool
True
canInlineInLam (Lam b :: InId
b e :: InExpr
e) = InId -> Bool
isRuntimeVar InId
b Bool -> Bool -> Bool
|| InExpr -> Bool
canInlineInLam InExpr
e
canInlineInLam (Tick t :: Tickish InId
t e :: InExpr
e) = Bool -> Bool
not (Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishIsCode Tickish InId
t) Bool -> Bool -> Bool
&& InExpr -> Bool
canInlineInLam InExpr
e
canInlineInLam _ = Bool
False
early_phase :: Bool
early_phase = case SimplMode -> CompilerPhase
sm_phase SimplMode
mode of
Phase 0 -> Bool
False
_ -> Bool
True
postInlineUnconditionally
:: SimplEnv -> TopLevelFlag
-> OutId
-> OccInfo
-> OutExpr
-> Bool
postInlineUnconditionally :: StaticEnv -> TopLevelFlag -> InId -> OccInfo -> InExpr -> Bool
postInlineUnconditionally env :: StaticEnv
env top_lvl :: TopLevelFlag
top_lvl bndr :: InId
bndr occ_info :: OccInfo
occ_info rhs :: InExpr
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
| InExpr -> Bool
exprIsTrivial InExpr
rhs = Bool
True
| Bool
otherwise
= case OccInfo
occ_info of
OneOcc { occ_in_lam :: OccInfo -> Bool
occ_in_lam = Bool
in_lam, occ_int_cxt :: OccInfo -> Bool
occ_int_cxt = Bool
int_cxt }
-> DynFlags -> Unfolding -> Bool
smallEnoughToInline DynFlags
dflags Unfolding
unfolding
Bool -> Bool -> Bool
&& (Bool -> Bool
not Bool
in_lam Bool -> Bool -> Bool
||
(Unfolding -> Bool
isCheapUnfolding Unfolding
unfolding Bool -> Bool -> Bool
&& Bool
int_cxt))
IAmDead -> Bool
True
_ -> Bool
False
where
unfolding :: Unfolding
unfolding = InId -> Unfolding
idUnfolding InId
bndr
dflags :: DynFlags
dflags = StaticEnv -> DynFlags
seDynFlags StaticEnv
env
active :: Bool
active = CompilerPhase -> Activation -> Bool
isActive (SimplMode -> CompilerPhase
sm_phase (StaticEnv -> SimplMode
getMode StaticEnv
env)) (InId -> Activation
idInlineActivation InId
bndr)
mkLam :: SimplEnv -> [OutBndr] -> OutExpr -> SimplCont -> SimplM OutExpr
mkLam :: StaticEnv -> [InId] -> InExpr -> SimplCont -> SimplM InExpr
mkLam _env :: StaticEnv
_env [] body :: InExpr
body _cont :: SimplCont
_cont
= InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return InExpr
body
mkLam env :: StaticEnv
env bndrs :: [InId]
bndrs body :: InExpr
body cont :: SimplCont
cont
= do { DynFlags
dflags <- SimplM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; DynFlags -> [InId] -> InExpr -> SimplM InExpr
mkLam' DynFlags
dflags [InId]
bndrs InExpr
body }
where
mkLam' :: DynFlags -> [OutBndr] -> OutExpr -> SimplM OutExpr
mkLam' :: DynFlags -> [InId] -> InExpr -> SimplM InExpr
mkLam' dflags :: DynFlags
dflags bndrs :: [InId]
bndrs (Cast body :: InExpr
body co :: OutCoercion
co)
| Bool -> Bool
not ((InId -> Bool) -> [InId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any InId -> Bool
bad [InId]
bndrs)
= do { InExpr
lam <- DynFlags -> [InId] -> InExpr -> SimplM InExpr
mkLam' DynFlags
dflags [InId]
bndrs InExpr
body
; InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (InExpr -> OutCoercion -> InExpr
mkCast InExpr
lam (Role -> [InId] -> OutCoercion -> OutCoercion
mkPiCos Role
Representational [InId]
bndrs OutCoercion
co)) }
where
co_vars :: TyCoVarSet
co_vars = OutCoercion -> TyCoVarSet
tyCoVarsOfCo OutCoercion
co
bad :: InId -> Bool
bad bndr :: InId
bndr = InId -> Bool
isCoVar InId
bndr Bool -> Bool -> Bool
&& InId
bndr InId -> TyCoVarSet -> Bool
`elemVarSet` TyCoVarSet
co_vars
mkLam' dflags :: DynFlags
dflags bndrs :: [InId]
bndrs body :: InExpr
body@(Lam {})
= DynFlags -> [InId] -> InExpr -> SimplM InExpr
mkLam' DynFlags
dflags ([InId]
bndrs [InId] -> [InId] -> [InId]
forall a. [a] -> [a] -> [a]
++ [InId]
bndrs1) InExpr
body1
where
(bndrs1 :: [InId]
bndrs1, body1 :: InExpr
body1) = InExpr -> ([InId], InExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders InExpr
body
mkLam' dflags :: DynFlags
dflags bndrs :: [InId]
bndrs (Tick t :: Tickish InId
t expr :: InExpr
expr)
| Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishFloatable Tickish InId
t
= Tickish InId -> InExpr -> InExpr
mkTick Tickish InId
t (InExpr -> InExpr) -> SimplM InExpr -> SimplM InExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynFlags -> [InId] -> InExpr -> SimplM InExpr
mkLam' DynFlags
dflags [InId]
bndrs InExpr
expr
mkLam' dflags :: DynFlags
dflags bndrs :: [InId]
bndrs body :: InExpr
body
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoEtaReduction DynFlags
dflags
, Just etad_lam :: InExpr
etad_lam <- [InId] -> InExpr -> Maybe InExpr
tryEtaReduce [InId]
bndrs InExpr
body
= do { Tick -> SimplM ()
tick (InId -> Tick
EtaReduction ([InId] -> InId
forall a. [a] -> a
head [InId]
bndrs))
; InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return InExpr
etad_lam }
| Bool -> Bool
not (SimplCont -> Bool
contIsRhs SimplCont
cont)
, SimplMode -> Bool
sm_eta_expand (StaticEnv -> SimplMode
getMode StaticEnv
env)
, (InId -> Bool) -> [InId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any InId -> Bool
isRuntimeVar [InId]
bndrs
, let body_arity :: Int
body_arity = DynFlags -> InExpr -> Int
exprEtaExpandArity DynFlags
dflags InExpr
body
, Int
body_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0
= do { Tick -> SimplM ()
tick (InId -> Tick
EtaExpansion ([InId] -> InId
forall a. [a] -> a
head [InId]
bndrs))
; let res :: InExpr
res = [InId] -> InExpr -> InExpr
forall b. [b] -> Expr b -> Expr b
mkLams [InId]
bndrs (Int -> InExpr -> InExpr
etaExpand Int
body_arity InExpr
body)
; String -> SDoc -> SimplM ()
traceSmpl "eta expand" ([SDoc] -> SDoc
vcat [String -> SDoc
text "before" SDoc -> SDoc -> SDoc
<+> InExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr ([InId] -> InExpr -> InExpr
forall b. [b] -> Expr b -> Expr b
mkLams [InId]
bndrs InExpr
body)
, String -> SDoc
text "after" SDoc -> SDoc -> SDoc
<+> InExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InExpr
res])
; InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return InExpr
res }
| Bool
otherwise
= InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return ([InId] -> InExpr -> InExpr
forall b. [b] -> Expr b -> Expr b
mkLams [InId]
bndrs InExpr
body)
tryEtaExpandRhs :: SimplMode -> OutId -> OutExpr
-> SimplM (Arity, Bool, OutExpr)
tryEtaExpandRhs :: SimplMode -> InId -> InExpr -> SimplM (Int, Bool, InExpr)
tryEtaExpandRhs mode :: SimplMode
mode bndr :: InId
bndr rhs :: InExpr
rhs
| Just join_arity :: Int
join_arity <- InId -> Maybe Int
isJoinId_maybe InId
bndr
= do { let (join_bndrs :: [InId]
join_bndrs, join_body :: InExpr
join_body) = Int -> InExpr -> ([InId], InExpr)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
join_arity InExpr
rhs
; (Int, Bool, InExpr) -> SimplM (Int, Bool, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return ((InId -> Bool) -> [InId] -> Int
forall a. (a -> Bool) -> [a] -> Int
count InId -> Bool
isId [InId]
join_bndrs, InExpr -> Bool
exprIsBottom InExpr
join_body, InExpr
rhs) }
| Bool
otherwise
= do { (new_arity :: Int
new_arity, is_bot :: Bool
is_bot, new_rhs :: InExpr
new_rhs) <- SimplM (Int, Bool, InExpr)
try_expand
; WARN( new_arity < old_id_arity,
(text "Arity decrease:" <+> (ppr bndr <+> ppr old_id_arity
<+> ppr old_arity <+> ppr new_arity) $$ ppr new_rhs) )
(Int, Bool, InExpr) -> SimplM (Int, Bool, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
new_arity, Bool
is_bot, InExpr
new_rhs) }
where
try_expand :: SimplM (Int, Bool, InExpr)
try_expand
| InExpr -> Bool
exprIsTrivial InExpr
rhs
= (Int, Bool, InExpr) -> SimplM (Int, Bool, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (InExpr -> Int
exprArity InExpr
rhs, Bool
False, InExpr
rhs)
| SimplMode -> Bool
sm_eta_expand SimplMode
mode
, Int
new_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
old_arity
= do { Tick -> SimplM ()
tick (InId -> Tick
EtaExpansion InId
bndr)
; (Int, Bool, InExpr) -> SimplM (Int, Bool, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
new_arity, Bool
is_bot, Int -> InExpr -> InExpr
etaExpand Int
new_arity InExpr
rhs) }
| Bool
otherwise
= (Int, Bool, InExpr) -> SimplM (Int, Bool, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
old_arity, Bool
is_bot Bool -> Bool -> Bool
&& Int
new_arity Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
old_arity, InExpr
rhs)
dflags :: DynFlags
dflags = SimplMode -> DynFlags
sm_dflags SimplMode
mode
old_arity :: Int
old_arity = InExpr -> Int
exprArity InExpr
rhs
old_id_arity :: Int
old_id_arity = InId -> Int
idArity InId
bndr
(new_arity1 :: Int
new_arity1, is_bot :: Bool
is_bot) = DynFlags -> InId -> InExpr -> Int -> (Int, Bool)
findRhsArity DynFlags
dflags InId
bndr InExpr
rhs Int
old_arity
new_arity2 :: Int
new_arity2 = InId -> Int
idCallArity InId
bndr
new_arity :: Int
new_arity = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
new_arity1 Int
new_arity2
abstractFloats :: DynFlags -> TopLevelFlag -> [OutTyVar] -> SimplFloats
-> OutExpr -> SimplM ([OutBind], OutExpr)
abstractFloats :: DynFlags
-> TopLevelFlag
-> [InId]
-> SimplFloats
-> InExpr
-> SimplM ([Bind InId], InExpr)
abstractFloats dflags :: DynFlags
dflags top_lvl :: TopLevelFlag
top_lvl main_tvs :: [InId]
main_tvs floats :: SimplFloats
floats body :: InExpr
body
= ASSERT( notNull body_floats )
ASSERT( isNilOL (sfJoinFloats floats) )
do { (subst :: Subst
subst, float_binds :: [Bind InId]
float_binds) <- (Subst -> Bind InId -> SimplM (Subst, Bind InId))
-> Subst -> [Bind InId] -> SimplM (Subst, [Bind InId])
forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM Subst -> Bind InId -> SimplM (Subst, Bind InId)
abstract Subst
empty_subst [Bind InId]
body_floats
; ([Bind InId], InExpr) -> SimplM ([Bind InId], InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Bind InId]
float_binds, SDoc -> Subst -> InExpr -> InExpr
CoreSubst.substExpr (String -> SDoc
text "abstract_floats1") Subst
subst InExpr
body) }
where
is_top_lvl :: Bool
is_top_lvl = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
main_tv_set :: TyCoVarSet
main_tv_set = [InId] -> TyCoVarSet
mkVarSet [InId]
main_tvs
body_floats :: [Bind InId]
body_floats = LetFloats -> [Bind InId]
letFloatBinds (SimplFloats -> LetFloats
sfLetFloats SimplFloats
floats)
empty_subst :: Subst
empty_subst = InScopeSet -> Subst
CoreSubst.mkEmptySubst (SimplFloats -> InScopeSet
sfInScope SimplFloats
floats)
abstract :: CoreSubst.Subst -> OutBind -> SimplM (CoreSubst.Subst, OutBind)
abstract :: Subst -> Bind InId -> SimplM (Subst, Bind InId)
abstract subst :: Subst
subst (NonRec id :: InId
id rhs :: InExpr
rhs)
= do { (poly_id1 :: InId
poly_id1, poly_app :: InExpr
poly_app) <- [InId] -> InId -> SimplM (InId, InExpr)
mk_poly1 [InId]
tvs_here InId
id
; let (poly_id2 :: InId
poly_id2, poly_rhs :: InExpr
poly_rhs) = InId -> [InId] -> InExpr -> (InId, InExpr)
mk_poly2 InId
poly_id1 [InId]
tvs_here InExpr
rhs'
subst' :: Subst
subst' = Subst -> InId -> InExpr -> Subst
CoreSubst.extendIdSubst Subst
subst InId
id InExpr
poly_app
; (Subst, Bind InId) -> SimplM (Subst, Bind InId)
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
subst', InId -> InExpr -> Bind InId
forall b. b -> Expr b -> Bind b
NonRec InId
poly_id2 InExpr
poly_rhs) }
where
rhs' :: InExpr
rhs' = SDoc -> Subst -> InExpr -> InExpr
CoreSubst.substExpr (String -> SDoc
text "abstract_floats2") Subst
subst InExpr
rhs
tvs_here :: [InId]
tvs_here = [InId] -> [InId]
scopedSort ([InId] -> [InId]) -> [InId] -> [InId]
forall a b. (a -> b) -> a -> b
$
(InId -> Bool) -> [InId] -> [InId]
forall a. (a -> Bool) -> [a] -> [a]
filter (InId -> TyCoVarSet -> Bool
`elemVarSet` TyCoVarSet
main_tv_set) ([InId] -> [InId]) -> [InId] -> [InId]
forall a b. (a -> b) -> a -> b
$
[InId] -> [InId]
closeOverKindsList ([InId] -> [InId]) -> [InId] -> [InId]
forall a b. (a -> b) -> a -> b
$
(InId -> Bool) -> InExpr -> [InId]
exprSomeFreeVarsList InId -> Bool
isTyVar InExpr
rhs'
abstract subst :: Subst
subst (Rec prs :: [(InId, InExpr)]
prs)
= do { (poly_ids :: [InId]
poly_ids, poly_apps :: [InExpr]
poly_apps) <- (InId -> SimplM (InId, InExpr))
-> [InId] -> SimplM ([InId], [InExpr])
forall (m :: * -> *) a b c.
Applicative m =>
(a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM ([InId] -> InId -> SimplM (InId, InExpr)
mk_poly1 [InId]
tvs_here) [InId]
ids
; let subst' :: Subst
subst' = Subst -> [(InId, InExpr)] -> Subst
CoreSubst.extendSubstList Subst
subst ([InId]
ids [InId] -> [InExpr] -> [(InId, InExpr)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [InExpr]
poly_apps)
poly_pairs :: [(InId, InExpr)]
poly_pairs = [ InId -> [InId] -> InExpr -> (InId, InExpr)
mk_poly2 InId
poly_id [InId]
tvs_here InExpr
rhs'
| (poly_id :: InId
poly_id, rhs :: InExpr
rhs) <- [InId]
poly_ids [InId] -> [InExpr] -> [(InId, InExpr)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [InExpr]
rhss
, let rhs' :: InExpr
rhs' = SDoc -> Subst -> InExpr -> InExpr
CoreSubst.substExpr (String -> SDoc
text "abstract_floats")
Subst
subst' InExpr
rhs ]
; (Subst, Bind InId) -> SimplM (Subst, Bind InId)
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
subst', [(InId, InExpr)] -> Bind InId
forall b. [(b, Expr b)] -> Bind b
Rec [(InId, InExpr)]
poly_pairs) }
where
(ids :: [InId]
ids,rhss :: [InExpr]
rhss) = [(InId, InExpr)] -> ([InId], [InExpr])
forall a b. [(a, b)] -> ([a], [b])
unzip [(InId, InExpr)]
prs
tvs_here :: [InId]
tvs_here = [InId] -> [InId]
scopedSort [InId]
main_tvs
mk_poly1 :: [TyVar] -> Id -> SimplM (Id, CoreExpr)
mk_poly1 :: [InId] -> InId -> SimplM (InId, InExpr)
mk_poly1 tvs_here :: [InId]
tvs_here var :: InId
var
= do { Unique
uniq <- SimplM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let poly_name :: Name
poly_name = Name -> Unique -> Name
setNameUnique (InId -> Name
idName InId
var) Unique
uniq
poly_ty :: OutType
poly_ty = [InId] -> OutType -> OutType
mkInvForAllTys [InId]
tvs_here (InId -> OutType
idType InId
var)
poly_id :: InId
poly_id = InId -> [InId] -> InId -> InId
transferPolyIdInfo InId
var [InId]
tvs_here (InId -> InId) -> InId -> InId
forall a b. (a -> b) -> a -> b
$
Name -> OutType -> InId
mkLocalIdOrCoVar Name
poly_name OutType
poly_ty
; (InId, InExpr) -> SimplM (InId, InExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (InId
poly_id, InExpr -> [OutType] -> InExpr
forall b. Expr b -> [OutType] -> Expr b
mkTyApps (InId -> InExpr
forall b. InId -> Expr b
Var InId
poly_id) ([InId] -> [OutType]
mkTyVarTys [InId]
tvs_here)) }
mk_poly2 :: Id -> [TyVar] -> CoreExpr -> (Id, CoreExpr)
mk_poly2 :: InId -> [InId] -> InExpr -> (InId, InExpr)
mk_poly2 poly_id :: InId
poly_id tvs_here :: [InId]
tvs_here rhs :: InExpr
rhs
= (InId
poly_id InId -> Unfolding -> InId
`setIdUnfolding` Unfolding
unf, InExpr
poly_rhs)
where
poly_rhs :: InExpr
poly_rhs = [InId] -> InExpr -> InExpr
forall b. [b] -> Expr b -> Expr b
mkLams [InId]
tvs_here InExpr
rhs
unf :: Unfolding
unf = DynFlags -> UnfoldingSource -> Bool -> Bool -> InExpr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
InlineRhs Bool
is_top_lvl Bool
False InExpr
poly_rhs
prepareAlts :: OutExpr -> OutId -> [InAlt] -> SimplM ([AltCon], [InAlt])
prepareAlts :: InExpr -> InId -> [InAlt] -> SimplM ([AltCon], [InAlt])
prepareAlts scrut :: InExpr
scrut case_bndr' :: InId
case_bndr' alts :: [InAlt]
alts
| Just (tc :: TyCon
tc, tys :: [OutType]
tys) <- HasDebugCallStack => OutType -> Maybe (TyCon, [OutType])
OutType -> Maybe (TyCon, [OutType])
splitTyConApp_maybe (InId -> OutType
varType InId
case_bndr')
= do { [Unique]
us <- SimplM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let (idcs1 :: [AltCon]
idcs1, alts1 :: [InAlt]
alts1) = TyCon -> [OutType] -> [AltCon] -> [InAlt] -> ([AltCon], [InAlt])
forall a.
TyCon
-> [OutType]
-> [AltCon]
-> [(AltCon, [InId], a)]
-> ([AltCon], [(AltCon, [InId], a)])
filterAlts TyCon
tc [OutType]
tys [AltCon]
imposs_cons [InAlt]
alts
(yes2 :: Bool
yes2, alts2 :: [InAlt]
alts2) = [Unique]
-> TyCon -> [OutType] -> [AltCon] -> [InAlt] -> (Bool, [InAlt])
refineDefaultAlt [Unique]
us TyCon
tc [OutType]
tys [AltCon]
idcs1 [InAlt]
alts1
(yes3 :: Bool
yes3, idcs3 :: [AltCon]
idcs3, alts3 :: [InAlt]
alts3) = [AltCon] -> [InAlt] -> (Bool, [AltCon], [InAlt])
combineIdenticalAlts [AltCon]
idcs1 [InAlt]
alts2
; Bool -> SimplM () -> SimplM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
yes2 (SimplM () -> SimplM ()) -> SimplM () -> SimplM ()
forall a b. (a -> b) -> a -> b
$ Tick -> SimplM ()
tick (InId -> Tick
FillInCaseDefault InId
case_bndr')
; Bool -> SimplM () -> SimplM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
yes3 (SimplM () -> SimplM ()) -> SimplM () -> SimplM ()
forall a b. (a -> b) -> a -> b
$ Tick -> SimplM ()
tick (InId -> Tick
AltMerge InId
case_bndr')
; ([AltCon], [InAlt]) -> SimplM ([AltCon], [InAlt])
forall (m :: * -> *) a. Monad m => a -> m a
return ([AltCon]
idcs3, [InAlt]
alts3) }
| Bool
otherwise
= ([AltCon], [InAlt]) -> SimplM ([AltCon], [InAlt])
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [InAlt]
alts)
where
imposs_cons :: [AltCon]
imposs_cons = case InExpr
scrut of
Var v :: InId
v -> Unfolding -> [AltCon]
otherCons (InId -> Unfolding
idUnfolding InId
v)
_ -> []
mkCase, mkCase1, mkCase2, mkCase3
:: DynFlags
-> OutExpr -> OutId
-> OutType -> [OutAlt]
-> SimplM OutExpr
mkCase :: DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase dflags :: DynFlags
dflags scrut :: InExpr
scrut outer_bndr :: InId
outer_bndr alts_ty :: OutType
alts_ty ((DEFAULT, _, deflt_rhs :: InExpr
deflt_rhs) : outer_alts :: [InAlt]
outer_alts)
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CaseMerge DynFlags
dflags
, (ticks :: [Tickish InId]
ticks, Case (Var inner_scrut_var :: InId
inner_scrut_var) inner_bndr :: InId
inner_bndr _ inner_alts :: [InAlt]
inner_alts)
<- (Tickish InId -> Bool) -> InExpr -> ([Tickish InId], InExpr)
forall b.
(Tickish InId -> Bool) -> Expr b -> ([Tickish InId], Expr b)
stripTicksTop Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishFloatable InExpr
deflt_rhs
, InId
inner_scrut_var InId -> InId -> Bool
forall a. Eq a => a -> a -> Bool
== InId
outer_bndr
= do { Tick -> SimplM ()
tick (InId -> Tick
CaseMerge InId
outer_bndr)
; let wrap_alt :: (a, t InId, InExpr) -> (a, t InId, InExpr)
wrap_alt (con :: a
con, args :: t InId
args, rhs :: InExpr
rhs) = ASSERT( outer_bndr `notElem` args )
(a
con, t InId
args, InExpr -> InExpr
wrap_rhs InExpr
rhs)
wrap_rhs :: InExpr -> InExpr
wrap_rhs rhs :: InExpr
rhs = Bind InId -> InExpr -> InExpr
forall b. Bind b -> Expr b -> Expr b
Let (InId -> InExpr -> Bind InId
forall b. b -> Expr b -> Bind b
NonRec InId
inner_bndr (InId -> InExpr
forall b. InId -> Expr b
Var InId
outer_bndr)) InExpr
rhs
wrapped_alts :: [InAlt]
wrapped_alts | InId -> Bool
isDeadBinder InId
inner_bndr = [InAlt]
inner_alts
| Bool
otherwise = (InAlt -> InAlt) -> [InAlt] -> [InAlt]
forall a b. (a -> b) -> [a] -> [b]
map InAlt -> InAlt
forall (t :: * -> *) a.
Foldable t =>
(a, t InId, InExpr) -> (a, t InId, InExpr)
wrap_alt [InAlt]
inner_alts
merged_alts :: [InAlt]
merged_alts = [InAlt] -> [InAlt] -> [InAlt]
forall a b.
[(AltCon, a, b)] -> [(AltCon, a, b)] -> [(AltCon, a, b)]
mergeAlts [InAlt]
outer_alts [InAlt]
wrapped_alts
; (InExpr -> InExpr) -> SimplM InExpr -> SimplM InExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Tickish InId] -> InExpr -> InExpr
mkTicks [Tickish InId]
ticks) (SimplM InExpr -> SimplM InExpr) -> SimplM InExpr -> SimplM InExpr
forall a b. (a -> b) -> a -> b
$
DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase1 DynFlags
dflags InExpr
scrut InId
outer_bndr OutType
alts_ty [InAlt]
merged_alts
}
mkCase dflags :: DynFlags
dflags scrut :: InExpr
scrut bndr :: InId
bndr alts_ty :: OutType
alts_ty alts :: [InAlt]
alts = DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase1 DynFlags
dflags InExpr
scrut InId
bndr OutType
alts_ty [InAlt]
alts
mkCase1 :: DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase1 _dflags :: DynFlags
_dflags scrut :: InExpr
scrut case_bndr :: InId
case_bndr _ alts :: [InAlt]
alts@((_,_,rhs1 :: InExpr
rhs1) : _)
| (InAlt -> Bool) -> [InAlt] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all InAlt -> Bool
forall b. (AltCon, [InId], Expr b) -> Bool
identity_alt [InAlt]
alts
= do { Tick -> SimplM ()
tick (InId -> Tick
CaseIdentity InId
case_bndr)
; InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return ([Tickish InId] -> InExpr -> InExpr
mkTicks [Tickish InId]
ticks (InExpr -> InExpr) -> InExpr -> InExpr
forall a b. (a -> b) -> a -> b
$ InExpr -> InExpr -> InExpr
forall b b. Expr b -> Expr b -> Expr b
re_cast InExpr
scrut InExpr
rhs1) }
where
ticks :: [Tickish InId]
ticks = (InAlt -> [Tickish InId]) -> [InAlt] -> [Tickish InId]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Tickish InId -> Bool) -> InExpr -> [Tickish InId]
forall b. (Tickish InId -> Bool) -> Expr b -> [Tickish InId]
stripTicksT Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishFloatable (InExpr -> [Tickish InId])
-> (InAlt -> InExpr) -> InAlt -> [Tickish InId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InAlt -> InExpr
forall a b c. (a, b, c) -> c
thdOf3) ([InAlt] -> [InAlt]
forall a. [a] -> [a]
tail [InAlt]
alts)
identity_alt :: (AltCon, [InId], Expr b) -> Bool
identity_alt (con :: AltCon
con, args :: [InId]
args, rhs :: Expr b
rhs) = Expr b -> AltCon -> [InId] -> Bool
forall b. Expr b -> AltCon -> [InId] -> Bool
check_eq Expr b
rhs AltCon
con [InId]
args
check_eq :: Expr b -> AltCon -> [InId] -> Bool
check_eq (Cast rhs :: Expr b
rhs co :: OutCoercion
co) con :: AltCon
con args :: [InId]
args
= Bool -> Bool
not ((InId -> Bool) -> [InId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (InId -> TyCoVarSet -> Bool
`elemVarSet` OutCoercion -> TyCoVarSet
tyCoVarsOfCo OutCoercion
co) [InId]
args) Bool -> Bool -> Bool
&& Expr b -> AltCon -> [InId] -> Bool
check_eq Expr b
rhs AltCon
con [InId]
args
check_eq (Tick t :: Tickish InId
t e :: Expr b
e) alt :: AltCon
alt args :: [InId]
args
= Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishFloatable Tickish InId
t Bool -> Bool -> Bool
&& Expr b -> AltCon -> [InId] -> Bool
check_eq Expr b
e AltCon
alt [InId]
args
check_eq (Lit lit :: Literal
lit) (LitAlt lit' :: Literal
lit') _ = Literal
lit Literal -> Literal -> Bool
forall a. Eq a => a -> a -> Bool
== Literal
lit'
check_eq (Var v :: InId
v) _ _ | InId
v InId -> InId -> Bool
forall a. Eq a => a -> a -> Bool
== InId
case_bndr = Bool
True
check_eq (Var v :: InId
v) (DataAlt con :: DataCon
con) args :: [InId]
args
| [OutType] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [OutType]
arg_tys, [InId] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [InId]
args = InId
v InId -> InId -> Bool
forall a. Eq a => a -> a -> Bool
== DataCon -> InId
dataConWorkId DataCon
con
check_eq rhs :: Expr b
rhs (DataAlt con :: DataCon
con) args :: [InId]
args = (Tickish InId -> Bool) -> Expr b -> Expr b -> Bool
forall b. (Tickish InId -> Bool) -> Expr b -> Expr b -> Bool
cheapEqExpr' Tickish InId -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr b
rhs (Expr b -> Bool) -> Expr b -> Bool
forall a b. (a -> b) -> a -> b
$
DataCon -> [OutType] -> [InId] -> Expr b
forall b. DataCon -> [OutType] -> [InId] -> Expr b
mkConApp2 DataCon
con [OutType]
arg_tys [InId]
args
check_eq _ _ _ = Bool
False
arg_tys :: [OutType]
arg_tys = OutType -> [OutType]
tyConAppArgs (InId -> OutType
idType InId
case_bndr)
re_cast :: Expr b -> Expr b -> Expr b
re_cast scrut :: Expr b
scrut (Cast rhs :: Expr b
rhs co :: OutCoercion
co) = Expr b -> OutCoercion -> Expr b
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 scrut :: Expr b
scrut _ = Expr b
scrut
mkCase1 dflags :: DynFlags
dflags scrut :: InExpr
scrut bndr :: InId
bndr alts_ty :: OutType
alts_ty alts :: [InAlt]
alts = DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase2 DynFlags
dflags InExpr
scrut InId
bndr OutType
alts_ty [InAlt]
alts
mkCase2 :: DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase2 dflags :: DynFlags
dflags scrut :: InExpr
scrut bndr :: InId
bndr alts_ty :: OutType
alts_ty alts :: [InAlt]
alts
|
case [InAlt]
alts of
[(DEFAULT,_,_)] -> Bool
False
_ -> Bool
True
, GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CaseFolding DynFlags
dflags
, Just (scrut' :: InExpr
scrut', tx_con :: AltCon -> Maybe AltCon
tx_con, mk_orig :: InId -> InExpr
mk_orig) <- DynFlags
-> InExpr -> Maybe (InExpr, AltCon -> Maybe AltCon, InId -> InExpr)
caseRules DynFlags
dflags InExpr
scrut
= do { InId
bndr' <- FastString -> OutType -> SimplM InId
newId (String -> FastString
fsLit "lwild") (InExpr -> OutType
exprType InExpr
scrut')
; [InAlt]
alts' <- (InAlt -> SimplM (Maybe InAlt)) -> [InAlt] -> SimplM [InAlt]
forall (m :: * -> *) a b.
Applicative m =>
(a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM ((AltCon -> Maybe AltCon)
-> (InId -> InExpr) -> InId -> InAlt -> SimplM (Maybe InAlt)
tx_alt AltCon -> Maybe AltCon
tx_con InId -> InExpr
mk_orig InId
bndr') [InAlt]
alts
; DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase3 DynFlags
dflags InExpr
scrut' InId
bndr' OutType
alts_ty ([InAlt] -> SimplM InExpr) -> [InAlt] -> SimplM InExpr
forall a b. (a -> b) -> a -> b
$
[InAlt] -> [InAlt]
add_default ([InAlt] -> [InAlt]
re_sort [InAlt]
alts')
}
| Bool
otherwise
= DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase3 DynFlags
dflags InExpr
scrut InId
bndr OutType
alts_ty [InAlt]
alts
where
tx_alt :: (AltCon -> Maybe AltCon) -> (Id -> CoreExpr) -> Id
-> CoreAlt -> SimplM (Maybe CoreAlt)
tx_alt :: (AltCon -> Maybe AltCon)
-> (InId -> InExpr) -> InId -> InAlt -> SimplM (Maybe InAlt)
tx_alt tx_con :: AltCon -> Maybe AltCon
tx_con mk_orig :: InId -> InExpr
mk_orig new_bndr :: InId
new_bndr (con :: AltCon
con, bs :: [InId]
bs, rhs :: InExpr
rhs)
= case AltCon -> Maybe AltCon
tx_con AltCon
con of
Nothing -> Maybe InAlt -> SimplM (Maybe InAlt)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe InAlt
forall a. Maybe a
Nothing
Just con' :: AltCon
con' -> do { [InId]
bs' <- InId -> AltCon -> SimplM [InId]
forall (m :: * -> *). MonadUnique m => InId -> AltCon -> m [InId]
mk_new_bndrs InId
new_bndr AltCon
con'
; Maybe InAlt -> SimplM (Maybe InAlt)
forall (m :: * -> *) a. Monad m => a -> m a
return (InAlt -> Maybe InAlt
forall a. a -> Maybe a
Just (AltCon
con', [InId]
bs', InExpr
rhs')) }
where
rhs' :: InExpr
rhs' | InId -> Bool
isDeadBinder InId
bndr = InExpr
rhs
| Bool
otherwise = InId -> InExpr -> InExpr -> InExpr
bindNonRec InId
bndr InExpr
orig_val InExpr
rhs
orig_val :: InExpr
orig_val = case AltCon
con of
DEFAULT -> InId -> InExpr
mk_orig InId
new_bndr
LitAlt l :: Literal
l -> Literal -> InExpr
forall b. Literal -> Expr b
Lit Literal
l
DataAlt dc :: DataCon
dc -> DataCon -> [OutType] -> [InId] -> InExpr
forall b. DataCon -> [OutType] -> [InId] -> Expr b
mkConApp2 DataCon
dc (OutType -> [OutType]
tyConAppArgs (InId -> OutType
idType InId
bndr)) [InId]
bs
mk_new_bndrs :: InId -> AltCon -> m [InId]
mk_new_bndrs new_bndr :: InId
new_bndr (DataAlt dc :: DataCon
dc)
| Bool -> Bool
not (DataCon -> Bool
isNullaryRepDataCon DataCon
dc)
=
do { [Unique]
us <- m [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
; let (ex_tvs :: [InId]
ex_tvs, arg_ids :: [InId]
arg_ids) = [Unique] -> DataCon -> [OutType] -> ([InId], [InId])
dataConRepInstPat [Unique]
us DataCon
dc
(OutType -> [OutType]
tyConAppArgs (InId -> OutType
idType InId
new_bndr))
; [InId] -> m [InId]
forall (m :: * -> *) a. Monad m => a -> m a
return ([InId]
ex_tvs [InId] -> [InId] -> [InId]
forall a. [a] -> [a] -> [a]
++ [InId]
arg_ids) }
mk_new_bndrs _ _ = [InId] -> m [InId]
forall (m :: * -> *) a. Monad m => a -> m a
return []
re_sort :: [CoreAlt] -> [CoreAlt]
re_sort :: [InAlt] -> [InAlt]
re_sort alts :: [InAlt]
alts = (InAlt -> InAlt -> Ordering) -> [InAlt] -> [InAlt]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy InAlt -> InAlt -> Ordering
forall a b. (AltCon, a, b) -> (AltCon, a, b) -> Ordering
cmpAlt [InAlt]
alts
add_default :: [CoreAlt] -> [CoreAlt]
add_default :: [InAlt] -> [InAlt]
add_default ((LitAlt {}, bs :: [InId]
bs, rhs :: InExpr
rhs) : alts :: [InAlt]
alts) = (AltCon
DEFAULT, [InId]
bs, InExpr
rhs) InAlt -> [InAlt] -> [InAlt]
forall a. a -> [a] -> [a]
: [InAlt]
alts
add_default alts :: [InAlt]
alts = [InAlt]
alts
mkCase3 :: DynFlags -> InExpr -> InId -> OutType -> [InAlt] -> SimplM InExpr
mkCase3 _dflags :: DynFlags
_dflags scrut :: InExpr
scrut bndr :: InId
bndr alts_ty :: OutType
alts_ty alts :: [InAlt]
alts
= InExpr -> SimplM InExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (InExpr -> InId -> OutType -> [InAlt] -> InExpr
forall b. Expr b -> b -> OutType -> [Alt b] -> Expr b
Case InExpr
scrut InId
bndr OutType
alts_ty [InAlt]
alts)
isExitJoinId :: Var -> Bool
isExitJoinId :: InId -> Bool
isExitJoinId id :: InId
id = InId -> Bool
isJoinId InId
id Bool -> Bool -> Bool
&& OccInfo -> Bool
isOneOcc (InId -> OccInfo
idOccInfo InId
id) Bool -> Bool -> Bool
&& OccInfo -> Bool
occ_in_lam (InId -> OccInfo
idOccInfo InId
id)