[project @ 1997-12-17 20:09:12 by sof]
[ghc-hetmet.git] / ghc / compiler / simplCore / BinderInfo.lhs
index f668ecf..39e436d 100644 (file)
@@ -16,11 +16,14 @@ module BinderInfo (
 
        addBinderInfo, orBinderInfo, andBinderInfo,
 
-       argOccurrence, funOccurrence, dangerousArgOcc, noBinderInfo,
+       deadOccurrence, argOccurrence, funOccurrence, dangerousArgOcc, noBinderInfo,
+
        markMany, markDangerousToDup, markInsideSCC,
        getBinderInfoArity,
        setBinderInfoArityToZero,
 
+       okToInline, isOneOcc, isOneFunOcc, isOneSafeFunOcc, isDeadOcc,
+
        isFun, isDupDanger -- for Simon Marlow deforestation
     ) where
 
@@ -28,6 +31,10 @@ IMP_Ubiq(){-uitous-}
 
 import Pretty
 import Util            ( panic )
+#if __GLASGOW_HASKELL__ >= 202
+import Outputable 
+#endif
+
 \end{code}
 
 The @BinderInfo@ describes how a variable is used in a given scope.
@@ -100,6 +107,23 @@ noBinderInfo = ManyOcc 0   -- A non-committal value
 
 
 \begin{code}
+isOneOcc :: BinderInfo -> Bool
+isOneOcc (OneOcc _ _ _ _ _) = True
+isOneOcc other_bind        = False
+
+isOneFunOcc :: BinderInfo -> Bool
+isOneFunOcc (OneOcc FunOcc _ _ _ _) = True
+isOneFunOcc other_bind                     = False
+
+isOneSafeFunOcc :: Bool -> BinderInfo -> Bool
+isOneSafeFunOcc ok_to_dup (OneOcc FunOcc NoDupDanger NotInsideSCC n_alts _)
+  = ok_to_dup || n_alts <= 1
+isOneSafeFunOcc ok_to_dup other_bind       = False
+
+isDeadOcc :: BinderInfo -> Bool
+isDeadOcc DeadCode = True
+isDeadOcc other    = False
+
 isFun :: FunOrArg -> Bool
 isFun FunOcc = True
 isFun _ = False
@@ -109,29 +133,38 @@ isDupDanger DupDanger = True
 isDupDanger _ = False
 \end{code}
 
-@inlineUnconditionally@ decides whether a let-bound thing can
-definitely be inlined.
 
 \begin{code}
-{-     NOT USED
-
-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
--}
+okToInline :: Bool             -- The thing is WHNF or bottom; 
+          -> Bool              -- It's small enough to duplicate the code
+          -> BinderInfo
+          -> Bool              -- True <=> inline it
+
+-- A non-WHNF can be inlined if it doesn't occur inside a lambda,
+-- and occurs exactly once or 
+--     occurs once in each branch of a case and is small
+okToInline False small_enough (OneOcc _ NoDupDanger _ n_alts _)
+  = n_alts <= 1 || small_enough
+
+-- If the thing isn't a redex, there's no danger of duplicating work, 
+-- so we can inline if it occurs once, or is small
+okToInline True small_enough occ_info 
+ = small_enough || one_occ
+ where
+   one_occ = case occ_info of
+               OneOcc _ _ _ n_alts _ -> n_alts <= 1
+               other                 -> False
+
+okToInline whnf_or_bot small_enough any_occ = False
 \end{code}
 
 
 Construction
 ~~~~~~~~~~~~~
 \begin{code}
+deadOccurrence :: BinderInfo
+deadOccurrence = DeadCode
+
 argOccurrence, funOccurrence :: Int -> BinderInfo
 
 funOccurrence = OneOcc FunOcc NoDupDanger NotInsideSCC 1
@@ -159,7 +192,9 @@ addBinderInfo, orBinderInfo
 addBinderInfo DeadCode info2 = info2
 addBinderInfo info1 DeadCode = info1
 addBinderInfo info1 info2
-       = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+ = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
+     (I# i#) -> ManyOcc (I# i#)
+      -- ManyOcc min (getBinderInfoArity info1) (getBinderInfoArity info2))
 
 -- (orBinderInfo orig new) is used when combining occurrence 
 -- info from branches of a case
@@ -168,13 +203,26 @@ orBinderInfo DeadCode info2 = info2
 orBinderInfo info1 DeadCode = info1
 orBinderInfo (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)
+  = let
+      -- Seriously maligned in order to make it stricter,
+      -- let's hope it is worth it..
+     posn = combine_posns posn1 posn2
+     scc  = combine_sccs  scc1  scc2
+     dup  = combine_dups  dup1  dup2
+     alts = n_alts1 + n_alts2
+     ar   = min ar_1 ar_2
+
+      -- No CSE, please!
+     cont1 = case scc  of { InsideSCC -> cont2; _ -> cont2 }
+     cont2 = case dup  of { DupDanger -> cont3; _ -> cont3 }
+     cont3 = case alts of { (I# 0#)   -> cont4; _ -> cont4 }
+     cont4 = case ar   of { (I# 0#)   -> cont5; _ -> cont5 }
+     cont5 = OneOcc posn dup scc alts ar
+    in
+    case posn of { FunOcc -> cont1; _ -> cont1 }
 orBinderInfo info1 info2
-       = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+ = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
+     (I# i#) -> ManyOcc (I# i#)
 
 -- (andBinderInfo orig new) is used in two situations:
 -- First, when a variable whose occurrence info
@@ -190,14 +238,27 @@ orBinderInfo info1 info2
 
 andBinderInfo DeadCode info2 = DeadCode
 andBinderInfo info1 DeadCode = DeadCode
-andBinderInfo (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)
-          ar_1                                 -- Min arity just from orig
-andBinderInfo info1 info2 = ManyOcc (getBinderInfoArity info1)
+andBinderInfo (OneOcc posn1 dup1 scc1 (I# n_alts1#) (I# ar_1#))
+             (OneOcc posn2 dup2 scc2 (I# n_alts2#) ar_2)
+  = let
+      -- Perversly maligned in order to make it stricter.
+     posn = combine_posns posn1 posn2
+     scc  = combine_sccs  scc1  scc2
+     dup  = combine_dups  dup1  dup2
+     alts = I# (n_alts1# +# n_alts2#)
+
+      -- No CSE, please!
+     cont1 = case scc  of { InsideSCC -> cont2; _ -> cont2 }
+     cont2 = case dup  of { DupDanger -> cont3; _ -> cont3 }
+     cont3 = case alts of { (I# 0#) -> cont4;   _ -> cont4 }
+     cont4 = OneOcc posn dup scc alts (I# ar_1#)
+    in
+    case posn of {FunOcc -> cont1; _ -> cont1}
+
+andBinderInfo info1 info2 = 
+ case getBinderInfoArity info1 of
+   (I# i#) -> ManyOcc (I# i#)
+               --ManyOcc (getBinderInfoArity info1)
 
 
 combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
@@ -225,20 +286,20 @@ getBinderInfoArity (OneOcc _ _ _ _ i) = i
 
 \begin{code}
 instance Outputable BinderInfo where
-  ppr sty DeadCode     = ppStr "Dead"
-  ppr sty (ManyOcc ar) = ppBesides [ ppStr "Many-", ppInt ar ]
+  ppr sty DeadCode     = ptext SLIT("Dead")
+  ppr sty (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int 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 ]
+    = hcat [ ptext SLIT("One-"), pp_posn posn, char '-', pp_danger 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_posn FunOcc = ptext SLIT("fun")
+      pp_posn ArgOcc = ptext SLIT("arg")
 
-      pp_danger DupDanger   = ppStr "*dup*"
-      pp_danger NoDupDanger = ppStr "nodup"
+      pp_danger DupDanger   = ptext SLIT("*dup*")
+      pp_danger NoDupDanger = ptext SLIT("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}