%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
%************************************************************************
%* *
%************************************************************************
\begin{code}
-
-#include "HsVersions.h"
-
module BinderInfo (
- BinderInfo(..),
- FunOrArg, DuplicationDanger, InsideSCC, -- NB: all abstract (yay!)
+ BinderInfo,
- inlineUnconditionally, oneTextualOcc, oneSafeOcc,
+ addBinderInfo, orBinderInfo,
- combineBinderInfo, combineAltsBinderInfo,
+ deadOccurrence, funOccurrence, noBinderInfo,
- argOccurrence, funOccurrence,
- markMany, markDangerousToDup, markInsideSCC,
+ markMany, markInsideLam, markInsideSCC,
getBinderInfoArity,
setBinderInfoArityToZero,
-
- isFun, isDupDanger -- for Simon Marlow deforestation
+
+ binderInfoToOccInfo
) where
-IMPORT_Trace -- ToDo: rm (debugging)
+#include "HsVersions.h"
-import PlainCore
+import IdInfo ( OccInfo(..), InsideLam, OneBranch, insideLam, notInsideLam, oneBranch )
+import GlaExts ( Int(..), (+#) )
import Outputable
-import Pretty
-import Util -- for pragmas only
\end{code}
The @BinderInfo@ describes how a variable is used in a given scope.
| ManyOcc -- Everything else besides DeadCode and OneOccs
- Int -- number of arguments on stack when called
+ !Int -- number of arguments on stack when called; this is a minimum guarantee
- | OneOcc -- Just one occurrence (or one each in
+ | SingleOcc -- Just one occurrence (or one each in
-- mutually-exclusive case alts).
- FunOrArg -- How it occurs
-
- DuplicationDanger
+ !InsideLam
- InsideSCC
+ !InsideSCC
- Int -- Number of mutually-exclusive case alternatives
+ !Int -- Number of mutually-exclusive case alternatives
-- in which it occurs
-- Note that we only worry about the case-alt counts
- -- if the OneOcc is substitutable -- that's the only
+ -- if the SingleOcc is substitutable -- that's the only
-- time we *use* the info; we could be more clever for
-- other cases if we really had to. (WDP/PS)
- Int -- number of arguments on stack when called
+ !Int -- number of arguments on stack when called; minimum guarantee
-- In general, we are feel free to substitute unless
-- (a) is in an argument position (ArgOcc)
-- (because the RHS will be inlined regardless of its size)
-- [again, DupDanger]
-data FunOrArg
- = FunOcc -- An occurrence in a function position
- | ArgOcc -- Other arg occurrence
-
- -- When combining branches of a case, only report FunOcc if
- -- both branches are FunOccs
-
-data DuplicationDanger
- = DupDanger -- Inside a non-linear lambda (that is, a lambda which
- -- is sure to be instantiated only once), or inside
- -- the rhs of an INLINE-pragma'd thing. Either way,
- -- substituting a redex for this occurrence is
- -- dangerous because it might duplicate work.
-
- | NoDupDanger -- It's ok; substitution won't duplicate work.
-
data InsideSCC
= InsideSCC -- Inside an SCC; so be careful when substituting.
| NotInsideSCC -- It's ok.
-\end{code}
-
-Predicates
-~~~~~~~~~~
-
-@oneTextualOcc@ checks for one occurrence, in any position.
-The occurrence may be inside a lambda, that's all right.
+noBinderInfo = ManyOcc 0 -- A non-committal value
+\end{code}
\begin{code}
-oneTextualOcc :: Bool -> BinderInfo -> Bool
-
-oneTextualOcc ok_to_dup (OneOcc _ _ _ n_alts _) = n_alts <= 1 || ok_to_dup
-oneTextualOcc _ other = False
+binderInfoToOccInfo :: BinderInfo -> OccInfo
+binderInfoToOccInfo DeadCode = IAmDead
+binderInfoToOccInfo (SingleOcc in_lam NotInsideSCC n_alts _) = OneOcc in_lam (n_alts==1)
+binderInfoToOccInfo other = NoOccInfo
\end{code}
-@safeSingleOcc@ detects single occurences of values that are safe to
-inline, {\em including} ones in an argument position.
-
-\begin{code}
-oneSafeOcc :: Bool -> BinderInfo -> Bool
-oneSafeOcc ok_to_dup (OneOcc _ NoDupDanger NotInsideSCC n_alts _)
- = n_alts <= 1 || ok_to_dup
-oneSafeOcc _ other = False
-\end{code}
-
-@inlineUnconditionally@ decides whether a let-bound thing can
-definitely be inlined.
-
-\begin{code}
-inlineUnconditionally :: Bool -> BinderInfo -> Bool
-
---inlineUnconditionally ok_to_dup DeadCode = True
-inlineUnconditionally ok_to_dup (OneOcc FunOcc NoDupDanger NotInsideSCC n_alt_occs _)
- = n_alt_occs <= 1 || ok_to_dup
- -- We [i.e., Patrick] don't mind the code explosion,
- -- though. We could have a flag to limit the
- -- damage, e.g., limit to M alternatives.
-
-inlineUnconditionally _ _ = False
-\end{code}
-
-\begin{code}
-isFun :: FunOrArg -> Bool
-isFun FunOcc = True
-isFun _ = False
-
-isDupDanger :: DuplicationDanger -> Bool
-isDupDanger DupDanger = True
-isDupDanger _ = False
-\end{code}
Construction
~~~~~~~~~~~~~
\begin{code}
-argOccurrence, funOccurrence :: Int -> BinderInfo
+deadOccurrence :: BinderInfo
+deadOccurrence = DeadCode
+
+funOccurrence :: Int -> BinderInfo
+funOccurrence = SingleOcc notInsideLam NotInsideSCC 1
-funOccurrence = OneOcc FunOcc NoDupDanger NotInsideSCC 1
-argOccurrence = OneOcc ArgOcc NoDupDanger NotInsideSCC 1
+markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
-markMany, markDangerousToDup, markInsideSCC :: BinderInfo -> BinderInfo
+markMany (SingleOcc _ _ _ ar) = ManyOcc ar
+markMany (ManyOcc ar) = ManyOcc ar
+markMany DeadCode = panic "markMany"
-markMany (OneOcc _ _ _ _ ar) = ManyOcc ar
-markMany (ManyOcc ar) = ManyOcc ar
-markMany DeadCode = panic "markMany"
+markInsideLam (SingleOcc _ in_scc n_alts ar) = SingleOcc insideLam in_scc n_alts ar
+markInsideLam other = other
-markDangerousToDup (OneOcc posn _ in_scc n_alts ar)
- = OneOcc posn DupDanger in_scc n_alts ar
-markDangerousToDup other = other
+markInsideSCC (SingleOcc dup_danger _ n_alts ar) = SingleOcc dup_danger InsideSCC n_alts ar
+markInsideSCC other = other
-markInsideSCC (OneOcc posn dup_danger _ n_alts ar)
- = OneOcc posn dup_danger InsideSCC n_alts ar
-markInsideSCC other = other
+addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
-combineBinderInfo, combineAltsBinderInfo
- :: BinderInfo -> BinderInfo -> BinderInfo
+addBinderInfo DeadCode info2 = info2
+addBinderInfo info1 DeadCode = info1
+addBinderInfo info1 info2
+ = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
-combineBinderInfo DeadCode info2 = info2
-combineBinderInfo info1 DeadCode = info1
-combineBinderInfo info1 info2
- = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+-- (orBinderInfo orig new) is used
+-- when combining occurrence info from branches of a case
-combineAltsBinderInfo DeadCode info2 = info2
-combineAltsBinderInfo info1 DeadCode = info1
-combineAltsBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
- (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
- = OneOcc (combine_posns posn1 posn2)
- (combine_dups dup1 dup2)
- (combine_sccs scc1 scc2)
- (n_alts1 + n_alts2)
- (min ar_1 ar_2)
- where
- combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
- combine_posns _ _ = ArgOcc
+orBinderInfo DeadCode info2 = info2
+orBinderInfo info1 DeadCode = info1
+orBinderInfo (SingleOcc dup1 scc1 n_alts1 ar_1)
+ (SingleOcc dup2 scc2 n_alts2 ar_2)
+ = let
+ scc = or_sccs scc1 scc2
+ dup = or_dups dup1 dup2
+ alts = n_alts1 + n_alts2
+ ar = min ar_1 ar_2
+ in
+ SingleOcc dup scc alts ar
- combine_dups DupDanger _ = DupDanger -- Too paranoid?? ToDo
- combine_dups _ DupDanger = DupDanger
- combine_dups _ _ = NoDupDanger
+orBinderInfo info1 info2
+ = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
- combine_sccs InsideSCC _ = InsideSCC -- Too paranoid?? ToDo
- combine_sccs _ InsideSCC = InsideSCC
- combine_sccs _ _ = NotInsideSCC
+or_dups in_lam1 in_lam2 = in_lam1 || in_lam2
-combineAltsBinderInfo info1 info2
- = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+or_sccs InsideSCC _ = InsideSCC
+or_sccs _ InsideSCC = InsideSCC
+or_sccs _ _ = NotInsideSCC
setBinderInfoArityToZero :: BinderInfo -> BinderInfo
setBinderInfoArityToZero DeadCode = DeadCode
setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
-setBinderInfoArityToZero (OneOcc fa dd sc i _) = OneOcc fa dd sc i 0
+setBinderInfoArityToZero (SingleOcc dd sc i _) = SingleOcc dd sc i 0
\end{code}
\begin{code}
getBinderInfoArity (DeadCode) = 0
getBinderInfoArity (ManyOcc i) = i
-getBinderInfoArity (OneOcc _ _ _ _ i) = i
+getBinderInfoArity (SingleOcc _ _ _ i) = i
\end{code}
\begin{code}
instance Outputable BinderInfo where
- ppr sty DeadCode = ppStr "Dead"
- ppr sty (ManyOcc ar) = ppBesides [ ppStr "Many-", ppInt ar ]
- ppr sty (OneOcc posn dup_danger in_scc n_alts ar)
- = ppBesides [ ppStr "One-", pp_posn posn, ppChar '-', pp_danger dup_danger,
- ppChar '-', pp_scc in_scc, ppChar '-', ppInt n_alts,
- ppChar '-', ppInt ar ]
+ ppr DeadCode = ptext SLIT("Dead")
+ ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
+ ppr (SingleOcc dup_danger in_scc n_alts ar)
+ = hcat [ ptext SLIT("One-"), ppr dup_danger,
+ char '-', pp_scc in_scc, char '-', int n_alts,
+ char '-', int ar ]
where
- pp_posn FunOcc = ppStr "fun"
- pp_posn ArgOcc = ppStr "arg"
-
- pp_danger DupDanger = ppStr "*dup*"
- pp_danger NoDupDanger = ppStr "nodup"
-
- pp_scc InsideSCC = ppStr "*SCC*"
- pp_scc NotInsideSCC = ppStr "noscc"
+ pp_scc InsideSCC = ptext SLIT("*SCC*")
+ pp_scc NotInsideSCC = ptext SLIT("noscc")
\end{code}
-