[project @ 1999-11-01 17:09:54 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / BinderInfo.lhs
index d899916..1623bcd 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 %************************************************************************
 %*                                                                     *
@@ -8,31 +8,25 @@
 %************************************************************************
 
 \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.
@@ -49,27 +43,25 @@ data BinderInfo
 
   | 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)
@@ -79,160 +71,95 @@ data BinderInfo
 --     (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}
-