[project @ 2001-12-11 12:39:04 by sewardj]
[ghc-hetmet.git] / ghc / compiler / basicTypes / IdInfo.lhs
index 017b3eb..d364222 100644 (file)
@@ -24,14 +24,14 @@ module IdInfo (
        arityInfo, setArityInfo, ppArityInfo, 
 
        -- New demand and strictness info
-       newStrictnessInfo, setNewStrictnessInfo, mkNewStrictnessInfo,
-       newDemandInfo, setNewDemandInfo, newDemand, oldDemand,
+       newStrictnessInfo, setNewStrictnessInfo, 
+       newDemandInfo, setNewDemandInfo,
 
        -- Strictness; imported from Demand
        StrictnessInfo(..),
        mkStrictnessInfo, noStrictnessInfo,
        ppStrictnessInfo,isBottomingStrictness, 
-       strictnessInfo, setStrictnessInfo,      
+       setAllStrictnessInfo,
 
         -- Usage generalisation
         TyGenInfo(..),
@@ -45,8 +45,17 @@ module IdInfo (
        -- Unfolding
        unfoldingInfo, setUnfoldingInfo, 
 
-       -- DemandInfo
+#ifdef DEBUG
+       -- Old DemandInfo and StrictnessInfo
        demandInfo, setDemandInfo, 
+       strictnessInfo, setStrictnessInfo,
+        cprInfoFromNewStrictness,
+       oldStrictnessFromNew, newStrictnessFromOld,
+       oldDemand, newDemand,
+
+        -- Constructed Product Result Info
+        CprInfo(..), cprInfo, setCprInfo, ppCprInfo, noCprInfo,
+#endif
 
        -- Inline prags
        InlinePragInfo, 
@@ -68,9 +77,6 @@ module IdInfo (
        -- CAF info
        CafInfo(..), ppCafInfo, setCafInfo, mayHaveCafRefs,
 
-        -- Constructed Product Result Info
-        CprInfo(..), cprInfo, setCprInfo, ppCprInfo, noCprInfo,
-
         -- Lambda-bound variable info
         LBVarInfo(..), lbvarInfo, setLBVarInfo, noLBVarInfo, hasNoLBVarInfo
     ) where
@@ -94,32 +100,32 @@ import DataCon             ( DataCon )
 import ForeignCall     ( ForeignCall )
 import FieldLabel      ( FieldLabel )
 import Type            ( usOnce, usMany )
-import Demand          hiding( Demand )
+import Demand          hiding( Demand, seqDemand )
 import qualified Demand
-import NewDemand       ( Demand(..), Keepity(..), DmdResult(..),
-                         lazyDmd, topDmd, dmdTypeDepth, isStrictDmd,
-                         StrictSig, mkStrictSig, mkTopDmdType
-                       )
+import NewDemand
 import Outputable      
 import Util            ( seqList, listLengthCmp )
 import List            ( replicate )
 
-infixl         1 `setDemandInfo`,
-         `setTyGenInfo`,
-         `setStrictnessInfo`,
+-- infixl so you can say (id `set` a `set` b)
+infixl         1 `setTyGenInfo`,
          `setSpecInfo`,
          `setArityInfo`,
          `setInlinePragInfo`,
          `setUnfoldingInfo`,
-         `setCprInfo`,
          `setWorkerInfo`,
          `setLBVarInfo`,
          `setOccInfo`,
          `setCgInfo`,
          `setCafInfo`,
          `setNewStrictnessInfo`,
+         `setAllStrictnessInfo`,
          `setNewDemandInfo`
-       -- infixl so you can say (id `set` a `set` b)
+#ifdef DEBUG
+         , `setCprInfo`
+         , `setDemandInfo`
+         , `setStrictnessInfo`
+#endif
 \end{code}
 
 %************************************************************************
@@ -131,22 +137,54 @@ infixl    1 `setDemandInfo`,
 To be removed later
 
 \begin{code}
-mkNewStrictnessInfo :: Id -> Arity -> Demand.StrictnessInfo -> CprInfo -> StrictSig
-mkNewStrictnessInfo id arity (Demand.StrictnessInfo ds res) cpr
+-- setAllStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
+-- Set old and new strictness info
+setAllStrictnessInfo info Nothing
+  = info { newStrictnessInfo = Nothing
+#ifdef DEBUG
+         , strictnessInfo = NoStrictnessInfo
+         , cprInfo = NoCPRInfo
+#endif
+         }
+
+setAllStrictnessInfo info (Just sig)
+  = info { newStrictnessInfo = Just sig
+#ifdef DEBUG
+         , strictnessInfo = oldStrictnessFromNew sig
+         , cprInfo = cprInfoFromNewStrictness sig
+#endif
+         }
+
+seqNewStrictnessInfo Nothing = ()
+seqNewStrictnessInfo (Just ty) = seqStrictSig ty
+
+#ifdef DEBUG
+oldStrictnessFromNew :: StrictSig -> Demand.StrictnessInfo
+oldStrictnessFromNew sig = mkStrictnessInfo (map oldDemand dmds, isBotRes res_info)
+                        where
+                          (dmds, res_info) = splitStrictSig sig
+
+cprInfoFromNewStrictness :: StrictSig -> CprInfo
+cprInfoFromNewStrictness sig = case strictSigResInfo sig of
+                                 RetCPR -> ReturnsCPR
+                                 other  -> NoCPRInfo
+
+newStrictnessFromOld :: Name -> Arity -> Demand.StrictnessInfo -> CprInfo -> StrictSig
+newStrictnessFromOld name arity (Demand.StrictnessInfo ds res) cpr
   | listLengthCmp ds arity /= GT -- length ds <= arity
        -- Sometimes the old strictness analyser has more
        -- demands than the arity justifies
-  = mk_strict_sig id arity $
+  = mk_strict_sig name arity $
     mkTopDmdType (map newDemand ds) (newRes res cpr)
 
-mkNewStrictnessInfo id arity other cpr
+newStrictnessFromOld name arity other cpr
   =    -- Either no strictness info, or arity is too small
        -- In either case we can't say anything useful
-    mk_strict_sig id arity $
+    mk_strict_sig name arity $
     mkTopDmdType (replicate arity lazyDmd) (newRes False cpr)
 
-mk_strict_sig id arity dmd_ty
-  = WARN( arity /= dmdTypeDepth dmd_ty, ppr id <+> (ppr arity $$ ppr dmd_ty) )
+mk_strict_sig name arity dmd_ty
+  = WARN( arity /= dmdTypeDepth dmd_ty, ppr name <+> (ppr arity $$ ppr dmd_ty) )
     mkStrictSig dmd_ty
 
 newRes True  _                 = BotRes
@@ -155,20 +193,25 @@ newRes False NoCPRInfo  = TopRes
 
 newDemand :: Demand.Demand -> NewDemand.Demand
 newDemand (WwLazy True)      = Abs
-newDemand (WwLazy False)     = Lazy
-newDemand WwStrict          = Eval
-newDemand (WwUnpack unpk ds) = Seq Drop (map newDemand ds)
-newDemand WwPrim            = Lazy
-newDemand WwEnum            = Eval
+newDemand (WwLazy False)     = lazyDmd
+newDemand WwStrict          = evalDmd
+newDemand (WwUnpack unpk ds) = Eval (Prod (map newDemand ds))
+newDemand WwPrim            = lazyDmd
+newDemand WwEnum            = evalDmd
 
 oldDemand :: NewDemand.Demand -> Demand.Demand
-oldDemand Abs       = WwLazy True
-oldDemand Lazy      = WwLazy False
-oldDemand Bot       = WwStrict
-oldDemand Err       = WwStrict
-oldDemand Eval      = WwStrict
-oldDemand (Seq _ ds) = WwUnpack True (map oldDemand ds)
-oldDemand (Call _)   = WwStrict
+oldDemand Abs             = WwLazy True
+oldDemand Top             = WwLazy False
+oldDemand Bot             = WwStrict
+oldDemand (Box Bot)       = WwStrict
+oldDemand (Box Abs)       = WwLazy False
+oldDemand (Box (Eval _))   = WwStrict  -- Pass box only
+oldDemand (Defer d)        = WwLazy False
+oldDemand (Eval (Prod ds)) = WwUnpack True (map oldDemand ds)
+oldDemand (Eval (Poly _))  = WwStrict
+oldDemand (Call _)         = WwStrict
+
+#endif /* DEBUG */
 \end{code}
 
 
@@ -234,15 +277,17 @@ case.  KSW 1999-04).
 \begin{code}
 data IdInfo
   = IdInfo {
-       arityInfo       :: ArityInfo,           -- Its arity
-       demandInfo      :: Demand.Demand,       -- Whether or not it is definitely demanded
+       arityInfo       :: !ArityInfo,          -- Its arity
        specInfo        :: CoreRules,           -- Specialisations of this function which exist
         tyGenInfo       :: TyGenInfo,           -- Restrictions on usage-generalisation of this Id
+#ifdef DEBUG
+       cprInfo         :: CprInfo,             -- Function always constructs a product result
+       demandInfo      :: Demand.Demand,       -- Whether or not it is definitely demanded
        strictnessInfo  :: StrictnessInfo,      -- Strictness properties
+#endif
         workerInfo      :: WorkerInfo,          -- Pointer to Worker Function
        unfoldingInfo   :: Unfolding,           -- Its unfolding
        cgInfo          :: CgInfo,              -- Code generator info (arity, CAF info)
-       cprInfo         :: CprInfo,             -- Function always constructs a product result
         lbvarInfo      :: LBVarInfo,           -- Info about a lambda-bound variable
        inlinePragInfo  :: InlinePragInfo,      -- Inline pragma
        occInfo         :: OccInfo,             -- How it occurs
@@ -259,21 +304,26 @@ seqIdInfo (IdInfo {}) = ()
 
 megaSeqIdInfo :: IdInfo -> ()
 megaSeqIdInfo info
-  = seqArity (arityInfo info)                  `seq`
-    seqDemand (demandInfo info)                        `seq`
-    seqRules (specInfo info)                   `seq`
+  = seqRules (specInfo info)                   `seq`
     seqTyGenInfo (tyGenInfo info)               `seq`
-    seqStrictnessInfo (strictnessInfo info)    `seq`
     seqWorker (workerInfo info)                        `seq`
 
---    seqUnfolding (unfoldingInfo info)        `seq`
 -- Omitting this improves runtimes a little, presumably because
 -- some unfoldings are not calculated at all
+--    seqUnfolding (unfoldingInfo info)                `seq`
+
+    seqDemand (newDemandInfo info)             `seq`
+    seqNewStrictnessInfo (newStrictnessInfo info) `seq`
+
+#ifdef DEBUG
+    Demand.seqDemand (demandInfo info)         `seq`
+    seqStrictnessInfo (strictnessInfo info)    `seq`
+    seqCpr (cprInfo info)                      `seq`
+#endif
 
 -- CgInfo is involved in a loop, so we have to be careful not to seq it
 -- too early.
 --    seqCg (cgInfo info)                      `seq`
-    seqCpr (cprInfo info)              `seq`
     seqLBVar (lbvarInfo info)          `seq`
     seqOccInfo (occInfo info) 
 \end{code}
@@ -286,7 +336,9 @@ setSpecInfo           info sp = sp `seq` info { specInfo = sp }
 setTyGenInfo      info tg = tg `seq` info { tyGenInfo = tg }
 setInlinePragInfo info pr = pr `seq` info { inlinePragInfo = pr }
 setOccInfo       info oc = oc `seq` info { occInfo = oc }
+#ifdef DEBUG
 setStrictnessInfo info st = st `seq` info { strictnessInfo = st }
+#endif
        -- Try to avoid spack leaks by seq'ing
 
 setUnfoldingInfo  info uf 
@@ -300,21 +352,25 @@ setUnfoldingInfo  info uf
        --      let x = (a,b) in h a b x
        -- and now x is not demanded (I'm assuming h is lazy)
        -- This really happens.  The solution here is a bit ad hoc...
-  = info { unfoldingInfo = uf, newDemandInfo = Lazy }
+  = info { unfoldingInfo = uf, newDemandInfo = Top }
 
   | otherwise
        -- We do *not* seq on the unfolding info, For some reason, doing so 
        -- actually increases residency significantly. 
   = info { unfoldingInfo = uf }
 
+#ifdef DEBUG
 setDemandInfo    info dd = info { demandInfo = dd }
+setCprInfo        info cp = info { cprInfo = cp }
+#endif
+
 setArityInfo     info ar = info { arityInfo = ar  }
 setCgInfo         info cg = info { cgInfo = cg }
-setCprInfo        info cp = info { cprInfo = cp }
-setLBVarInfo      info lb = info { lbvarInfo = lb }
 
-setNewDemandInfo     info dd = info { newDemandInfo = dd }
-setNewStrictnessInfo info dd = info { newStrictnessInfo = dd }
+setLBVarInfo      info lb = {-lb `seq`-} info { lbvarInfo = lb }
+
+setNewDemandInfo     info dd = dd `seq` info { newDemandInfo = dd }
+setNewStrictnessInfo info dd = dd `seq` info { newStrictnessInfo = dd }
 \end{code}
 
 
@@ -324,13 +380,15 @@ vanillaIdInfo
   = IdInfo {
            cgInfo              = noCgInfo,
            arityInfo           = unknownArity,
+#ifdef DEBUG
+           cprInfo             = NoCPRInfo,
            demandInfo          = wwLazy,
+           strictnessInfo      = NoStrictnessInfo,
+#endif
            specInfo            = emptyCoreRules,
             tyGenInfo          = noTyGenInfo,
            workerInfo          = NoWorker,
-           strictnessInfo      = NoStrictnessInfo,
            unfoldingInfo       = noUnfolding,
-           cprInfo             = NoCPRInfo,
            lbvarInfo           = NoLBVarInfo,
            inlinePragInfo      = AlwaysActive,
            occInfo             = NoOccInfo,
@@ -366,9 +424,6 @@ type ArityInfo = Arity
        -- The arity might increase later in the compilation process, if
        -- an extra lambda floats up to the binding site.
 
-seqArity :: ArityInfo -> ()
-seqArity a = a `seq` ()
-
 unknownArity = 0 :: Arity
 
 ppArityInfo 0 = empty
@@ -475,7 +530,7 @@ instance Show TyGenInfo where
 
 If this Id has a worker then we store a reference to it. Worker
 functions are generated by the worker/wrapper pass.  This uses
-information from the strictness and CPR analyses.
+information from strictness analysis.
 
 There might not be a worker, even for a strict function, because:
 (a) the function might be small enough to inline, so no need 
@@ -507,7 +562,7 @@ data WorkerInfo = NoWorker
        -- w/w split. See comments in MkIface.ifaceId, with the 'Worker' code.
 
 seqWorker :: WorkerInfo -> ()
-seqWorker (HasWorker id _) = id `seq` ()
+seqWorker (HasWorker id a) = id `seq` a `seq` ()
 seqWorker NoWorker        = ()
 
 ppWorkerInfo NoWorker            = empty
@@ -616,6 +671,7 @@ function has the CPR property and which components of the result are
 also CPRs.   
 
 \begin{code}
+#ifdef DEBUG
 data CprInfo
   = NoCPRInfo
   | ReturnsCPR -- Yes, this function returns a constructed product
@@ -626,9 +682,7 @@ data CprInfo
 
        -- We used to keep nested info about sub-components, but
        -- we never used it so I threw it away
-\end{code}
 
-\begin{code}
 seqCpr :: CprInfo -> ()
 seqCpr ReturnsCPR = ()
 seqCpr NoCPRInfo  = ()
@@ -643,6 +697,7 @@ instance Outputable CprInfo where
 
 instance Show CprInfo where
     showsPrec p c = showsPrecSDoc p (ppr c)
+#endif
 \end{code}
 
 
@@ -717,7 +772,7 @@ zapLamInfo info@(IdInfo {occInfo = occ, newDemandInfo = demand})
   = Nothing
   | otherwise
   = Just (info {occInfo = safe_occ,
-               newDemandInfo = Lazy})
+               newDemandInfo = Top})
   where
        -- The "unsafe" occ info is the ones that say I'm not in a lambda
        -- because that might not be true for an unsaturated lambda
@@ -734,7 +789,7 @@ zapLamInfo info@(IdInfo {occInfo = occ, newDemandInfo = demand})
 zapDemandInfo :: IdInfo -> Maybe IdInfo
 zapDemandInfo info@(IdInfo {newDemandInfo = demand})
   | not (isStrictDmd demand) = Nothing
-  | otherwise               = Just (info {newDemandInfo = Lazy})
+  | otherwise               = Just (info {newDemandInfo = Top})
 \end{code}
 
 
@@ -796,8 +851,11 @@ shortableIdInfo info = isEmptyCoreRules (specInfo info)
 copyIdInfo :: IdInfo   -- f_local
           -> IdInfo    -- f (the exported one)
           -> IdInfo    -- New info for f
-copyIdInfo f_local f = f { strictnessInfo = strictnessInfo f_local,
-                          workerInfo     = workerInfo     f_local,
-                          cprInfo        = cprInfo        f_local
+copyIdInfo f_local f = f { newStrictnessInfo = newStrictnessInfo f_local,
+#ifdef DEBUG
+                          strictnessInfo = strictnessInfo f_local,
+                          cprInfo        = cprInfo        f_local,
+#endif
+                          workerInfo     = workerInfo     f_local
                          }
 \end{code}