[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / compiler / simplCore / BinderInfo.lhs
index 39e436d..6723bc6 100644 (file)
@@ -8,8 +8,6 @@
 %************************************************************************
 
 \begin{code}
-#include "HsVersions.h"
-
 module BinderInfo (
        BinderInfo(..),
        FunOrArg, DuplicationDanger, InsideSCC,  -- NB: all abstract (yay!)
@@ -22,18 +20,17 @@ module BinderInfo (
        getBinderInfoArity,
        setBinderInfoArityToZero,
 
-       okToInline, isOneOcc, isOneFunOcc, isOneSafeFunOcc, isDeadOcc,
+       isOneOcc, isOneFunOcc, isOneSafeFunOcc, isOneSameSCCFunOcc, 
+       isDeadOcc, isInlinableOcc,
 
        isFun, isDupDanger -- for Simon Marlow deforestation
     ) where
 
-IMP_Ubiq(){-uitous-}
+#include "HsVersions.h"
 
-import Pretty
 import Util            ( panic )
-#if __GLASGOW_HASKELL__ >= 202
-import Outputable 
-#endif
+import GlaExts         ( Int(..), (+#) )
+import Outputable
 
 \end{code}
 
@@ -51,19 +48,19 @@ data BinderInfo
 
   | ManyOcc    -- Everything else besides DeadCode and OneOccs
 
-       Int     -- number of arguments on stack when called; this is a minimum guarantee
+       !Int    -- number of arguments on stack when called; this is a minimum guarantee
 
 
   | OneOcc     -- Just one occurrence (or one each in
                -- mutually-exclusive case alts).
 
-      FunOrArg -- How it occurs
+      !FunOrArg        -- How it occurs
 
-      DuplicationDanger
+      !DuplicationDanger
 
-      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
@@ -71,7 +68,7 @@ data BinderInfo
                -- 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; minimum guarantee
+      !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)
@@ -115,10 +112,30 @@ 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
+isOneSameSCCFunOcc :: BinderInfo -> Bool
+isOneSameSCCFunOcc (OneOcc FunOcc _ NotInsideSCC _ _) = True
+isOneSameSCCFunOcc other_bind                        = False
+
+isOneSafeFunOcc :: BinderInfo -> Bool  -- Completely safe
+isOneSafeFunOcc (OneOcc FunOcc NoDupDanger NotInsideSCC n_alts _) = n_alts <= 1
+isOneSafeFunOcc other                                            = False
+
+-- 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
+--
+-- If the thing is in WHNF, there's no danger of duplicating work, 
+-- so we can inline if it occurs once, or is small
+isInlinableOcc :: Bool         -- True <=> don't worry about dup-danger
+              -> Bool  -- True <=> don't worry about code size
+              -> BinderInfo
+              -> Bool  -- Inlinable
+isInlinableOcc whnf small (ManyOcc _) 
+  = whnf && small
+isInlinableOcc whnf small (OneOcc _ dup_danger _ n_alts _)
+  =  (whnf || (case dup_danger of {NoDupDanger -> True; other -> False}))
+  && (small || n_alts <= 1)
+isInlinableOcc _ _ DeadCode = False
 
 isDeadOcc :: BinderInfo -> Bool
 isDeadOcc DeadCode = True
@@ -134,30 +151,6 @@ isDupDanger _ = False
 \end{code}
 
 
-\begin{code}
-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
 ~~~~~~~~~~~~~
@@ -192,73 +185,52 @@ addBinderInfo, orBinderInfo
 addBinderInfo DeadCode info2 = info2
 addBinderInfo info1 DeadCode = info1
 addBinderInfo info1 info2
- = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
-     (I# i#) -> ManyOcc (I# i#)
-      -- ManyOcc min (getBinderInfoArity info1) (getBinderInfoArity info2))
+ = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
 
--- (orBinderInfo orig new) is used when combining occurrence 
--- info from branches of a case
+-- (orBinderInfo orig new) is used in two situations:
+-- First, when a variable whose occurrence info
+--   is currently "orig" is bound to a variable whose occurrence info is "new"
+--     eg  (\new -> e) orig
+--   What we want to do is to *worsen* orig's info to take account of new's
+--
+-- Second, when combining occurrence info from branches of a case
 
 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)
   = 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
+   in
+   OneOcc posn dup scc alts ar
 
-      -- 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
- = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
-     (I# i#) -> ManyOcc (I# i#)
+ = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
 
--- (andBinderInfo orig new) is used in two situations:
--- First, when a variable whose occurrence info
---   is currently "orig" is bound to a variable whose occurrence info is "new"
---     eg  (\new -> e) orig
---   What we want to do is to *worsen* orig's info to take account of new's
---
--- second, when completing a let-binding
+-- (andBinderInfo orig new) is used 
+-- when completing a let-binding
 --     let new = ...orig...
--- we compute the way orig occurs in (...orig...), and then use orBinderInfo
+-- we compute the way orig occurs in (...orig...), and then use andBinderInfo
 -- to worsen this info by the way new occurs in the let body; then we use
 -- that to worsen orig's currently recorded occurrence info.
 
 andBinderInfo DeadCode info2 = DeadCode
 andBinderInfo info1 DeadCode = DeadCode
-andBinderInfo (OneOcc posn1 dup1 scc1 (I# n_alts1#) (I# ar_1#))
-             (OneOcc posn2 dup2 scc2 (I# n_alts2#) ar_2)
+andBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
+             (OneOcc posn2 dup2 scc2 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#)
+       posn = combine_posns posn1 posn2
+       scc  = combine_sccs  scc1  scc2
+       dup  = combine_dups  dup1  dup2
+       alts = n_alts1 + n_alts2
     in
-    case posn of {FunOcc -> cont1; _ -> cont1}
+    OneOcc posn dup scc alts ar_1
 
-andBinderInfo info1 info2 = 
- case getBinderInfoArity info1 of
-   (I# i#) -> ManyOcc (I# i#)
-               --ManyOcc (getBinderInfoArity info1)
+andBinderInfo info1 info2 = ManyOcc (getBinderInfoArity info1)
 
 
 combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
@@ -266,7 +238,7 @@ combine_posns _      _  = ArgOcc
 
 combine_dups DupDanger _ = DupDanger   -- Too paranoid?? ToDo
 combine_dups _ DupDanger = DupDanger
-combine_dups _ _            = NoDupDanger
+combine_dups _ _        = NoDupDanger
 
 combine_sccs InsideSCC _ = InsideSCC   -- Too paranoid?? ToDo
 combine_sccs _ InsideSCC = InsideSCC
@@ -286,9 +258,9 @@ getBinderInfoArity (OneOcc _ _ _ _ i) = i
 
 \begin{code}
 instance Outputable BinderInfo where
-  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)
+  ppr DeadCode     = ptext SLIT("Dead")
+  ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
+  ppr (OneOcc posn dup_danger in_scc n_alts 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 ]