Commit 60e9e613 authored by simonpj@microsoft.com's avatar simonpj@microsoft.com
Browse files

Rejig the auto-scc wrapping stuff

parent afaceeff
...@@ -9,7 +9,9 @@ module Desugar ( deSugar, deSugarExpr ) where ...@@ -9,7 +9,9 @@ module Desugar ( deSugar, deSugarExpr ) where
#include "HsVersions.h" #include "HsVersions.h"
import DynFlags ( DynFlag(..), DynFlags(..), dopt, GhcMode(..) ) import DynFlags ( DynFlag(..), DynFlags(..), dopt, GhcMode(..) )
import StaticFlags ( opt_SccProfilingOn ) import StaticFlags ( opt_SccProfilingOn,
opt_AutoSccsOnAllToplevs,
opt_AutoSccsOnExportedToplevs )
import DriverPhases ( isHsBoot ) import DriverPhases ( isHsBoot )
import HscTypes ( ModGuts(..), HscEnv(..), import HscTypes ( ModGuts(..), HscEnv(..),
Dependencies(..), ForeignStubs(..), TypeEnv, IsBootInterface ) Dependencies(..), ForeignStubs(..), TypeEnv, IsBootInterface )
...@@ -76,6 +78,8 @@ deSugar hsc_env ...@@ -76,6 +78,8 @@ deSugar hsc_env
= do { showPass dflags "Desugar" = do { showPass dflags "Desugar"
-- Desugar the program -- Desugar the program
; let auto_scc = mkAutoScc mod exports
; mb_res <- case ghcMode dflags of ; mb_res <- case ghcMode dflags of
JustTypecheck -> return (Just ([], [], NoStubs)) JustTypecheck -> return (Just ([], [], NoStubs))
_ -> initDs hsc_env mod rdr_env type_env $ do _ -> initDs hsc_env mod rdr_env type_env $ do
...@@ -93,7 +97,7 @@ deSugar hsc_env ...@@ -93,7 +97,7 @@ deSugar hsc_env
{ -- Add export flags to bindings { -- Add export flags to bindings
keep_alive <- readIORef keep_var keep_alive <- readIORef keep_var
; let final_prs = addExportFlags ghci_mode exports keep_alive ; let final_prs = addExportFlags ghci_mode exports keep_alive
all_prs ds_rules all_prs ds_rules
ds_binds = [Rec final_prs] ds_binds = [Rec final_prs]
-- Notice that we put the whole lot in a big Rec, even the foreign binds -- Notice that we put the whole lot in a big Rec, even the foreign binds
-- When compiling PrelFloat, which defines data Float = F# Float# -- When compiling PrelFloat, which defines data Float = F# Float#
...@@ -163,8 +167,18 @@ deSugar hsc_env ...@@ -163,8 +167,18 @@ deSugar hsc_env
where where
dflags = hsc_dflags hsc_env dflags = hsc_dflags hsc_env
ghci_mode = ghcMode (hsc_dflags hsc_env) ghci_mode = ghcMode (hsc_dflags hsc_env)
auto_scc | opt_SccProfilingOn = TopLevel
| otherwise = NoSccs mkAutoScc :: Module -> NameSet -> AutoScc
mkAutoScc mod exports
| not opt_SccProfilingOn -- No profiling
= NoSccs
| opt_AutoSccsOnAllToplevs -- Add auto-scc on all top-level things
= AddSccs mod (\id -> True)
| opt_AutoSccsOnExportedToplevs -- Only on exported things
= AddSccs mod (\id -> idName id `elemNameSet` exports)
| otherwise
= NoSccs
deSugarExpr :: HscEnv deSugarExpr :: HscEnv
-> Module -> GlobalRdrEnv -> TypeEnv -> Module -> GlobalRdrEnv -> TypeEnv
......
...@@ -27,19 +27,18 @@ import HsSyn -- lots of things ...@@ -27,19 +27,18 @@ import HsSyn -- lots of things
import CoreSyn -- lots of things import CoreSyn -- lots of things
import CoreUtils ( exprType, mkInlineMe, mkSCC ) import CoreUtils ( exprType, mkInlineMe, mkSCC )
import StaticFlags ( opt_AutoSccsOnAllToplevs,
opt_AutoSccsOnExportedToplevs )
import OccurAnal ( occurAnalyseExpr ) import OccurAnal ( occurAnalyseExpr )
import CostCentre ( mkAutoCC, IsCafCC(..) ) import CostCentre ( mkAutoCC, IsCafCC(..) )
import Id ( Id, DictId, idType, idName, isExportedId, mkLocalId, setInlinePragma ) import Id ( Id, DictId, idType, idName, mkLocalId, setInlinePragma )
import Rules ( addIdSpecialisations, mkLocalRule ) import Rules ( addIdSpecialisations, mkLocalRule )
import Var ( TyVar, Var, isGlobalId, setIdNotExported ) import Var ( TyVar, Var, isGlobalId, setIdNotExported )
import VarEnv import VarEnv
import Type ( mkTyVarTy, substTyWith ) import Type ( mkTyVarTy, substTyWith )
import TysWiredIn ( voidTy ) import TysWiredIn ( voidTy )
import Module ( Module )
import Outputable import Outputable
import SrcLoc ( Located(..) ) import SrcLoc ( Located(..) )
import Maybes ( isJust, catMaybes, orElse ) import Maybes ( catMaybes, orElse )
import Bag ( bagToList ) import Bag ( bagToList )
import BasicTypes ( Activation(..), InlineSpec(..), isAlwaysActive ) import BasicTypes ( Activation(..), InlineSpec(..), isAlwaysActive )
import Monad ( foldM ) import Monad ( foldM )
...@@ -90,13 +89,11 @@ dsHsBind auto_scc rest (VarBind var expr) ...@@ -90,13 +89,11 @@ dsHsBind auto_scc rest (VarBind var expr)
dsHsBind auto_scc rest (FunBind { fun_id = L _ fun, fun_matches = matches, fun_co_fn = co_fn }) dsHsBind auto_scc rest (FunBind { fun_id = L _ fun, fun_matches = matches, fun_co_fn = co_fn })
= matchWrapper (FunRhs (idName fun)) matches `thenDs` \ (args, body) -> = matchWrapper (FunRhs (idName fun)) matches `thenDs` \ (args, body) ->
dsCoercion co_fn (return (mkLams args body)) `thenDs` \ rhs -> dsCoercion co_fn (return (mkLams args body)) `thenDs` \ rhs ->
addAutoScc auto_scc (fun, rhs) `thenDs` \ pair -> returnDs ((fun,rhs) : rest)
returnDs (pair : rest)
dsHsBind auto_scc rest (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = ty }) dsHsBind auto_scc rest (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = ty })
= dsGuarded grhss ty `thenDs` \ body_expr -> = dsGuarded grhss ty `thenDs` \ body_expr ->
mkSelectorBinds pat body_expr `thenDs` \ sel_binds -> mkSelectorBinds pat body_expr `thenDs` \ sel_binds ->
mappM (addAutoScc auto_scc) sel_binds `thenDs` \ sel_binds ->
returnDs (sel_binds ++ rest) returnDs (sel_binds ++ rest)
-- Note [Rules and inlining] -- Note [Rules and inlining]
...@@ -123,11 +120,11 @@ dsHsBind auto_scc rest (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = t ...@@ -123,11 +120,11 @@ dsHsBind auto_scc rest (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = t
-- float the f_lcl binding out and then inline M.f at its call site -- float the f_lcl binding out and then inline M.f at its call site
dsHsBind auto_scc rest (AbsBinds [] [] exports binds) dsHsBind auto_scc rest (AbsBinds [] [] exports binds)
= do { core_prs <- ds_lhs_binds (addSccs auto_scc exports) binds = do { core_prs <- ds_lhs_binds NoSccs binds
; let env = mkVarEnv [ (lcl_id, (gbl_id, prags)) ; let env = mkABEnv exports
| (_, gbl_id, lcl_id, prags) <- exports]
do_one (lcl_id, rhs) | Just (gbl_id, prags) <- lookupVarEnv env lcl_id do_one (lcl_id, rhs) | Just (gbl_id, prags) <- lookupVarEnv env lcl_id
= addInlinePrags prags gbl_id rhs = addInlinePrags prags gbl_id $
addAutoScc auto_scc gbl_id rhs
| otherwise = (lcl_id, rhs) | otherwise = (lcl_id, rhs)
locals' = [(lcl_id, Var gbl_id) | (_, gbl_id, lcl_id, _) <- exports] locals' = [(lcl_id, Var gbl_id) | (_, gbl_id, lcl_id, _) <- exports]
; return (map do_one core_prs ++ locals' ++ rest) } ; return (map do_one core_prs ++ locals' ++ rest) }
...@@ -139,7 +136,7 @@ dsHsBind auto_scc rest (AbsBinds [] [] exports binds) ...@@ -139,7 +136,7 @@ dsHsBind auto_scc rest (AbsBinds [] [] exports binds)
dsHsBind auto_scc rest dsHsBind auto_scc rest
(AbsBinds all_tyvars dicts exports@[(tyvars, global, local, prags)] binds) (AbsBinds all_tyvars dicts exports@[(tyvars, global, local, prags)] binds)
= ASSERT( all (`elem` tyvars) all_tyvars ) = ASSERT( all (`elem` tyvars) all_tyvars )
ds_lhs_binds (addSccs auto_scc exports) binds `thenDs` \ core_prs -> ds_lhs_binds NoSccs binds `thenDs` \ core_prs ->
let let
-- Always treat the binds as recursive, because the typechecker -- Always treat the binds as recursive, because the typechecker
-- makes rather mixed-up dictionary bindings -- makes rather mixed-up dictionary bindings
...@@ -151,56 +148,63 @@ dsHsBind auto_scc rest ...@@ -151,56 +148,63 @@ dsHsBind auto_scc rest
(spec_binds, rules) = unzip (catMaybes mb_specs) (spec_binds, rules) = unzip (catMaybes mb_specs)
global' = addIdSpecialisations global rules global' = addIdSpecialisations global rules
rhs' = mkLams tyvars $ mkLams dicts $ Let core_bind (Var local) rhs' = mkLams tyvars $ mkLams dicts $ Let core_bind (Var local)
bind = addInlinePrags prags global' $ addAutoScc auto_scc global' rhs'
in in
returnDs (addInlinePrags prags global' rhs' : spec_binds ++ rest) returnDs (bind : spec_binds ++ rest)
dsHsBind auto_scc rest (AbsBinds all_tyvars dicts exports binds) dsHsBind auto_scc rest (AbsBinds all_tyvars dicts exports binds)
= ds_lhs_binds (addSccs auto_scc exports) binds `thenDs` \ core_prs -> = do { core_prs <- ds_lhs_binds NoSccs binds
let ; let env = mkABEnv exports
add_inline (bndr,rhs) | Just prags <- lookupVarEnv inline_env bndr do_one (lcl_id,rhs) | Just (gbl_id, prags) <- lookupVarEnv env lcl_id
= addInlinePrags prags bndr rhs = addInlinePrags prags lcl_id $
| otherwise = (bndr,rhs) addAutoScc auto_scc gbl_id rhs
inline_env = mkVarEnv [(lcl_id, prags) | (_, _, lcl_id, prags) <- exports] | otherwise = (lcl_id,rhs)
-- Rec because of mixed-up dictionary bindings -- Rec because of mixed-up dictionary bindings
core_bind = Rec (map add_inline core_prs) core_bind = Rec (map do_one core_prs)
tup_expr = mkTupleExpr locals tup_expr = mkTupleExpr locals
tup_ty = exprType tup_expr tup_ty = exprType tup_expr
poly_tup_expr = mkLams all_tyvars $ mkLams dicts $ poly_tup_expr = mkLams all_tyvars $ mkLams dicts $
Let core_bind tup_expr Let core_bind tup_expr
locals = [local | (_, _, local, _) <- exports] locals = [local | (_, _, local, _) <- exports]
local_tys = map idType locals local_tys = map idType locals
in
newSysLocalDs (exprType poly_tup_expr) `thenDs` \ poly_tup_id -> ; poly_tup_id <- newSysLocalDs (exprType poly_tup_expr)
let
dict_args = map Var dicts ; let dict_args = map Var dicts
mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local
= -- Need to make fresh locals to bind in the selector, because = -- Need to make fresh locals to bind in the selector, because
-- some of the tyvars will be bound to voidTy -- some of the tyvars will be bound to voidTy
newSysLocalsDs (map substitute local_tys) `thenDs` \ locals' -> do { locals' <- newSysLocalsDs (map substitute local_tys)
newSysLocalDs (substitute tup_ty) `thenDs` \ tup_id -> ; tup_id <- newSysLocalDs (substitute tup_ty)
mapM (dsSpec all_tyvars dicts tyvars global local core_bind) ; mb_specs <- mapM (dsSpec all_tyvars dicts tyvars global local core_bind)
prags `thenDs` \ mb_specs -> prags
let ; let (spec_binds, rules) = unzip (catMaybes mb_specs)
(spec_binds, rules) = unzip (catMaybes mb_specs) global' = addIdSpecialisations global rules
global' = addIdSpecialisations global rules rhs = mkLams tyvars $ mkLams dicts $
rhs = mkLams tyvars $ mkLams dicts $ mkTupleSelector locals' (locals' !! n) tup_id $
mkTupleSelector locals' (locals' !! n) tup_id $ mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args
mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args ; returnDs ((global', rhs) : spec_binds) }
in where
returnDs ((global', rhs) : spec_binds) mk_ty_arg all_tyvar | all_tyvar `elem` tyvars = mkTyVarTy all_tyvar
where | otherwise = voidTy
mk_ty_arg all_tyvar | all_tyvar `elem` tyvars = mkTyVarTy all_tyvar ty_args = map mk_ty_arg all_tyvars
| otherwise = voidTy substitute = substTyWith all_tyvars ty_args
ty_args = map mk_ty_arg all_tyvars
substitute = substTyWith all_tyvars ty_args ; export_binds_s <- mappM mk_bind (exports `zip` [0..])
in -- don't scc (auto-)annotate the tuple itself.
mappM mk_bind (exports `zip` [0..]) `thenDs` \ export_binds_s ->
-- don't scc (auto-)annotate the tuple itself. ; returnDs ((poly_tup_id, poly_tup_expr) :
(concat export_binds_s ++ rest)) }
mkABEnv :: [([TyVar], Id, Id, [Prag])] -> VarEnv (Id, [Prag])
-- Takes the exports of a AbsBinds, and returns a mapping
-- lcl_id -> (gbl_id, prags)
mkABEnv exports = mkVarEnv [ (lcl_id, (gbl_id, prags))
| (_, gbl_id, lcl_id, prags) <- exports]
returnDs ((poly_tup_id, poly_tup_expr) : (concat export_binds_s ++ rest))
dsSpec :: [TyVar] -> [DictId] -> [TyVar] dsSpec :: [TyVar] -> [DictId] -> [TyVar]
-> Id -> Id -- Global, local -> Id -> Id -- Global, local
...@@ -360,36 +364,20 @@ addInlineInfo (Inline phase is_inline) bndr rhs ...@@ -360,36 +364,20 @@ addInlineInfo (Inline phase is_inline) bndr rhs
%************************************************************************ %************************************************************************
\begin{code} \begin{code}
data AutoScc data AutoScc = NoSccs
= TopLevel | AddSccs Module (Id -> Bool)
| TopLevelAddSccs (Id -> Maybe Id) -- The (Id->Bool) says which Ids to add SCCs to
| NoSccs
addAutoScc :: AutoScc
addSccs :: AutoScc -> [(a,Id,Id,[Prag])] -> AutoScc -> Id -- Binder
addSccs auto_scc@(TopLevelAddSccs _) exports = auto_scc -> CoreExpr -- Rhs
addSccs NoSccs exports = NoSccs -> CoreExpr -- Scc'd Rhs
addSccs TopLevel exports
= TopLevelAddSccs (\id -> case [ exp | (_,exp,loc,_) <- exports, loc == id ] of addAutoScc NoSccs _ rhs
(exp:_) | opt_AutoSccsOnAllToplevs || = rhs
(isExportedId exp && addAutoScc (AddSccs mod add_scc) id rhs
opt_AutoSccsOnExportedToplevs) | add_scc id = mkSCC (mkAutoCC id mod NotCafCC) rhs
-> Just exp | otherwise = rhs
_ -> Nothing)
addAutoScc :: AutoScc -- if needs be, decorate toplevs?
-> (Id, CoreExpr)
-> DsM (Id, CoreExpr)
addAutoScc (TopLevelAddSccs auto_scc_fn) pair@(bndr, core_expr)
| do_auto_scc
= getModuleDs `thenDs` \ mod ->
returnDs (bndr, mkSCC (mkAutoCC top_bndr mod NotCafCC) core_expr)
where do_auto_scc = isJust maybe_auto_scc
maybe_auto_scc = auto_scc_fn bndr
(Just top_bndr) = maybe_auto_scc
addAutoScc _ pair
= returnDs pair
\end{code} \end{code}
If profiling and dealing with a dict binding, If profiling and dealing with a dict binding,
...@@ -436,5 +424,3 @@ dsCoercion (WpLet bs) thing_inside = do { prs <- dsLHsBinds bs ...@@ -436,5 +424,3 @@ dsCoercion (WpLet bs) thing_inside = do { prs <- dsLHsBinds bs
; expr <- thing_inside ; expr <- thing_inside
; return (Let (Rec prs) expr) } ; return (Let (Rec prs) expr) }
\end{code} \end{code}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment