summaryrefslogtreecommitdiff
path: root/compiler/GHC/Stg/InferTags.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Stg/InferTags.hs')
-rw-r--r--compiler/GHC/Stg/InferTags.hs94
1 files changed, 60 insertions, 34 deletions
diff --git a/compiler/GHC/Stg/InferTags.hs b/compiler/GHC/Stg/InferTags.hs
index 3c342d93bc..a3a659af23 100644
--- a/compiler/GHC/Stg/InferTags.hs
+++ b/compiler/GHC/Stg/InferTags.hs
@@ -13,6 +13,8 @@ module GHC.Stg.InferTags ( inferTags ) where
import GHC.Prelude
import GHC.Core.DataCon
+import GHC.Core.TyCon
+import GHC.Core.Type
import GHC.Types.Id
import GHC.Stg.Syntax
import GHC.Types.Basic ( Arity, TopLevelFlag(..), RecFlag(..) )
@@ -148,6 +150,11 @@ seemed more efficient.
* *
********************************************************************* -}
+type OutputableInferPass p = (Outputable (TagEnv p)
+ , Outputable (GenStgExpr p)
+ , Outputable (BinderP p)
+ , Outputable (GenStgRhs p))
+
inferTags :: [GenStgTopBinding 'Vanilla] -> [GenStgTopBinding 'InferTaggedBinders]
inferTags binds =
-- pprTrace "Binds" (pprGenStgTopBindings shortStgPprOpts $ binds) $
@@ -165,7 +172,7 @@ inferTagTopBind env (StgTopLifted bind)
-----------------------
-inferTagExpr :: Outputable (TagEnv p)
+inferTagExpr :: OutputableInferPass p
=> TagEnv p -> GenStgExpr p -> (TagInfo, GenStgExpr 'InferTaggedBinders)
inferTagExpr env (StgApp _ext fun args)
= (info, StgApp noEnterInfo fun args)
@@ -174,7 +181,8 @@ inferTagExpr env (StgApp _ext fun args)
, arity == length args -- Saturated
= res_info
| otherwise
- = TagDunno
+ = --pprTrace "inferAppUnknown" (ppr fun) $
+ TagDunno
inferTagExpr env (StgConApp con cn args tys)
= (info, StgConApp con cn args tys)
@@ -214,27 +222,47 @@ inferTagExpr env (StgLetNoEscape ext bind body)
inferTagExpr env (StgCase scrut bndr ty alts)
| [(DataAlt con, bndrs, rhs)] <- alts
, isUnboxedTupleDataCon con
- , TagTuple infos <- scrut_info
+ , Just infos <- scrut_infos bndrs
+ -- , pprTrace "scrut info:" (ppr infos $$ ppr scrut $$ ppr bndrs) True
, let bndrs' = zipWithEqual "inferTagExpr" mk_bndr bndrs infos
- mk_bndr bndr info = (getBinderId env bndr, TagSig 0 info)
+ mk_bndr bndr info =
+ -- pprTrace "mk_ubx_bndr_info" ( ppr bndr <+> ppr info ) $
+ (getBinderId env bndr, TagSig 0 info)
+ -- no case binder in alt_env here, unboxed tuple binders are dead after unarise
alt_env = extendSigEnv env bndrs'
(info, rhs') = inferTagExpr alt_env rhs
- = (info, StgCase scrut' (noSig env bndr) ty [(DataAlt con, bndrs', rhs')])
+ = -- pprTrace "inferCase1" (ppr scrut $$ ppr bndr $$ ppr infos $$ ppr bndrs') $
+ (info, StgCase scrut' (noSig env bndr) ty [(DataAlt con, bndrs', rhs')])
+
| null alts -- Empty case, but I might just be paranoid.
- = (TagDunno, StgCase scrut' bndr' ty [])
+ = -- pprTrace "inferCase2" empty $
+ (TagDunno, StgCase scrut' bndr' ty [])
+ -- More than one alternative OR non-tuple single alternative.
| otherwise
- = ( foldr combineAltInfo TagProper infos
+ = -- pprTrace "inferCase3" empty $
+ let
+ alt_env = extendSigEnv env [bndr']
+ (infos, alts')
+ = unzip [ (info, (con, bndrs', rhs'))
+ | (con, bndrs, rhs) <- alts
+ , let (info, rhs') = inferTagExpr alt_env rhs
+ bndrs' = addAltBndrInfo env con bndrs ]
+ alt_info = foldr combineAltInfo TagTagged infos
+ in -- pprTrace "combine alts:" (ppr alt_info $$ ppr infos)
+ ( foldr combineAltInfo TagTagged infos
, StgCase scrut' bndr' ty alts')
where
+ -- Single unboxed tuple alternative
+ scrut_infos bndrs = case scrut_info of
+ TagTagged -> Just $ replicate (length bndrs) TagProper
+ TagTuple infos -> Just infos
+ _ -> Nothing
(scrut_info, scrut') = inferTagExpr env scrut
bndr' = (getBinderId env bndr, TagSig 0 TagProper)
- alt_env = extendSigEnv env [bndr']
- (infos, alts')
- = unzip [ (info, (con, bndrs', rhs'))
- | (con, bndrs, rhs) <- alts
- , let (info, rhs') = inferTagExpr alt_env rhs
- bndrs' = addAltBndrInfo env con bndrs ]
+
+
+-- Not used if we have tuple info about the scrutinee
addAltBndrInfo :: TagEnv p -> AltCon -> [BinderP p] -> [BinderP 'InferTaggedBinders]
addAltBndrInfo env (DataAlt con) bndrs
= zipWithEqual "inferTagAlt" mk_bndr bndrs marks
@@ -249,14 +277,14 @@ addAltBndrInfo env (DataAlt con) bndrs
addAltBndrInfo env _ bndrs = map (noSig env) bndrs
-----------------------------
-inferTagBind :: Outputable (TagEnv p)
+inferTagBind :: OutputableInferPass p
=> TopLevelFlag -> TagEnv p -> GenStgBinding p -> (TagEnv p, GenStgBinding 'InferTaggedBinders)
inferTagBind top env (StgNonRec bndr rhs)
= (env', StgNonRec (id, sig) rhs')
where
id = getBinderId env bndr
env' = extendSigEnv env [(id, sig)]
- (sig,rhs') = inferTagRhs top [] env rhs
+ (sig,rhs') = inferTagRhs top [id] env rhs
inferTagBind top env (StgRec pairs)
= (env { te_env = sig_env }, StgRec pairs')
@@ -266,7 +294,7 @@ inferTagBind top env (StgRec pairs)
init_sigs = map initSig rhss
(sig_env, pairs') = go env init_sigs rhss
- go :: forall q. TagEnv q -> [TagSig] -> [GenStgRhs q]
+ go :: forall q. OutputableInferPass q => TagEnv q -> [TagSig] -> [GenStgRhs q]
-> (TagSigEnv, [((Id,TagSig), GenStgRhs 'InferTaggedBinders)])
go env sigs rhss
-- | pprTrace "go" (ppr ids $$ ppr sigs $$ ppr sigs') False
@@ -281,11 +309,11 @@ inferTagBind top env (StgRec pairs)
initSig :: GenStgRhs p -> TagSig
-- Initial signature for the fixpoint loop
-initSig StgRhsCon {} = TagSig 0 TagProper
-initSig (StgRhsClosure _ _ _ bndrs _) = TagSig (length bndrs) TagProper
+initSig (StgRhsCon {}) = TagSig 0 TagProper
+initSig (StgRhsClosure _ _ _ bndrs _) = TagSig (length bndrs) TagTagged
-----------------------------
-inferTagRhs :: Outputable (TagEnv p)
+inferTagRhs :: OutputableInferPass p
=> TopLevelFlag -- ^
-> [Id] -- ^ List of ids in the recursive group, or [] otherwise
-> TagEnv p -- ^
@@ -307,29 +335,27 @@ inferTagRhs _top _grp_ids env (StgRhsClosure ext cc upd bndrs body)
| otherwise = info
bndrs' = map (noSig env) bndrs
-inferTagRhs top grp_ids env (StgRhsCon cc con cn ticks args)
+inferTagRhs _top _grp_ids env rhs@(StgRhsCon cc con cn ticks args)
-- Top level constructors, which have untagged arguments to strict fields
-- become thunks. Same goes for rhs which are part of a recursive group.
-- We encode this by giving changing RhsCon nodes the info TagDunno
= --pprTrace "inferTagRhsCon" (ppr grp_ids) $
let
strictArgs = zipEqual "inferTagRhs" args (dataConRuntimeRepStrictness con)
+ -- argInfo = [(lookupInfo env (StgVarArg v)) | StgVarArg v <- args ]
strictUntaggedIds = [v | (StgVarArg v, MarkedStrict) <- strictArgs
- , lookupInfo env (StgVarArg v) /= TagProper] :: [Id]
-
- mkResult x = (TagSig 0 x, StgRhsCon cc con cn ticks args)
+ , not (isTaggedInfo (lookupInfo env (StgVarArg v))) ] :: [Id]
+
+ mkResult x =
+ -- pprTrace "inferTagRhsCon"
+ -- ( ppr _grp_ids <+> ppr x <+> ppr rhs $$
+ -- ppr strictArgs $$
+ -- ppr strictUntaggedIds $$
+ -- ppr argInfo $$
+ -- text "con:" <> ppr con
+ -- ) $
+ (TagSig 0 x, StgRhsCon cc con cn ticks args)
in case () of
-- All fields tagged or non-strict
_ | null strictUntaggedIds -> mkResult TagProper
- -- -- Non-recursive local let
- -- | null grp_ids
- -- , NotTopLevel <- top
- -- -> mkResult TagProper
- -- Recursive local let, no bindings from grp in args
- -- | NotTopLevel <- top
- -- , mkVarSet grp_ids `disjointVarSet` mkVarSet strictUntaggedIds
- -- -> mkResult TagProper
- -- Otherwise we have a top level let with untagged args,
- -- or a recursive group where a bindings of the group is
- -- passed into a strict field
| otherwise -> mkResult TagDunno