summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Opt/CprAnal.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core/Opt/CprAnal.hs')
-rw-r--r--compiler/GHC/Core/Opt/CprAnal.hs66
1 files changed, 43 insertions, 23 deletions
diff --git a/compiler/GHC/Core/Opt/CprAnal.hs b/compiler/GHC/Core/Opt/CprAnal.hs
index 0a35583acf..a697dd65d0 100644
--- a/compiler/GHC/Core/Opt/CprAnal.hs
+++ b/compiler/GHC/Core/Opt/CprAnal.hs
@@ -16,6 +16,7 @@ import GHC.Types.Cpr
import GHC.Core
import GHC.Core.Seq
import GHC.Utils.Outputable
+import GHC.Builtin.Names ( runRWKey )
import GHC.Types.Var.Env
import GHC.Types.Basic
import GHC.Types.Id
@@ -148,8 +149,6 @@ cprAnal' _ (Lit lit) = (topCprType, Lit lit)
cprAnal' _ (Type ty) = (topCprType, Type ty) -- Doesn't happen, in fact
cprAnal' _ (Coercion co) = (topCprType, Coercion co)
-cprAnal' env (Var var) = (cprTransform env var, Var var)
-
cprAnal' env (Cast e co)
= (cpr_ty, Cast e' co)
where
@@ -160,19 +159,10 @@ cprAnal' env (Tick t e)
where
(cpr_ty, e') = cprAnal env e
-cprAnal' env (App fun (Type ty))
- = (fun_ty, App fun' (Type ty))
- where
- (fun_ty, fun') = cprAnal env fun
-
-cprAnal' env (App fun arg)
- = (res_ty, App fun' arg')
- where
- (fun_ty, fun') = cprAnal env fun
- -- In contrast to DmdAnal, there is no useful (non-nested) CPR info to be
- -- had by looking into the CprType of arg.
- (_, arg') = cprAnal env arg
- res_ty = applyCprTy fun_ty
+cprAnal' env e@(Var{})
+ = cprAnalApp env e [] []
+cprAnal' env e@(App{})
+ = cprAnalApp env e [] []
cprAnal' env (Lam var body)
| isTyVar var
@@ -234,26 +224,56 @@ cprAnalAlt env scrut_ty (Alt con bndrs rhs)
-- * CPR transformer
--
-cprTransform :: AnalEnv -- ^ The analysis environment
- -> Id -- ^ The function
- -> CprType -- ^ The demand type of the function
-cprTransform env id
- = -- pprTrace "cprTransform" (vcat [ppr id, ppr sig])
+cprAnalApp :: AnalEnv -> CoreExpr -> [CoreArg] -> [CprType] -> (CprType, CoreExpr)
+cprAnalApp env e args' arg_tys
+ -- Collect CprTypes for (value) args (inlined collectArgs):
+ | App fn arg <- e, isTypeArg arg -- Don't analyse Type args
+ = cprAnalApp env fn (arg:args') arg_tys
+ | App fn arg <- e
+ , (arg_ty, arg') <- cprAnal env arg
+ = cprAnalApp env fn (arg':args') (arg_ty:arg_tys)
+
+ | Var fn <- e
+ = (cprTransform env fn arg_tys, mkApps e args')
+
+ | otherwise -- e is not an App and not a Var
+ , (e_ty, e') <- cprAnal env e
+ = (applyCprTy e_ty (length arg_tys), mkApps e' args')
+
+cprTransform :: AnalEnv -- ^ The analysis environment
+ -> Id -- ^ The function
+ -> [CprType] -- ^ info about incoming /value/ arguments
+ -> CprType -- ^ The demand type of the application
+cprTransform env id args
+ = -- pprTrace "cprTransform" (vcat [ppr id, ppr args, ppr sig])
sig
where
sig
- -- Top-level binding, local let-binding or case binder
+ -- Top-level binding, local let-binding, lambda arg or case binder
| Just sig <- lookupSigEnv env id
- = getCprSig sig
+ = applyCprTy (getCprSig sig) (length args)
+ -- CPR transformers for special Ids
+ | Just cpr_ty <- cprTransformSpecial id args
+ = cpr_ty
-- See Note [CPR for data structures]
| Just rhs <- cprDataStructureUnfolding_maybe id
= fst $ cprAnal env rhs
-- Imported function or data con worker
| isGlobalId id
- = getCprSig (idCprSig id)
+ = applyCprTy (getCprSig (idCprSig id)) (length args)
| otherwise
= topCprType
+-- | CPR transformers for special Ids
+cprTransformSpecial :: Id -> [CprType] -> Maybe CprType
+cprTransformSpecial id args
+ -- See Note [Simplification of runRW#] in GHC.CoreToStg.Prep
+ | idUnique id == runRWKey -- `runRW (\s -> e)`
+ , [arg] <- args -- `\s -> e` has CPR type `arg` (e.g. `. -> 2`)
+ = Just $ applyCprTy arg 1 -- `e` has CPR type `2`
+ | otherwise
+ = Nothing
+
--
-- * Bindings
--