Remove the (very) old strictness analyser
authorsimonpj@microsoft.com <unknown>
Thu, 19 Nov 2009 15:43:47 +0000 (15:43 +0000)
committersimonpj@microsoft.com <unknown>
Thu, 19 Nov 2009 15:43:47 +0000 (15:43 +0000)
I finally got tired of the #ifdef OLD_STRICTNESS stuff.  I had been
keeping it around in the hope of doing old-to-new comparisions, but
have failed to do so for many years, so I don't think it's going to
happen.  This patch deletes the clutter.

30 files changed:
compiler/basicTypes/Demand.lhs
compiler/basicTypes/Id.lhs
compiler/basicTypes/IdInfo.lhs
compiler/basicTypes/MkId.lhs
compiler/basicTypes/NewDemand.lhs [deleted file]
compiler/coreSyn/CoreArity.lhs
compiler/coreSyn/CoreLint.lhs
compiler/coreSyn/CorePrep.lhs
compiler/coreSyn/CoreTidy.lhs
compiler/coreSyn/PprCore.lhs
compiler/cprAnalysis/CprAnalyse.lhs [deleted file]
compiler/ghc.cabal.in
compiler/iface/BinIface.hs
compiler/iface/IfaceSyn.lhs
compiler/iface/MkIface.lhs
compiler/iface/TcIface.lhs
compiler/main/DynFlags.hs
compiler/main/TidyPgm.lhs
compiler/prelude/PrimOp.lhs
compiler/simplCore/SetLevels.lhs
compiler/simplCore/SimplCore.lhs
compiler/simplCore/SimplUtils.lhs
compiler/simplCore/Simplify.lhs
compiler/specialise/SpecConstr.lhs
compiler/stranal/DmdAnal.lhs
compiler/stranal/SaAbsInt.lhs [deleted file]
compiler/stranal/SaLib.lhs [deleted file]
compiler/stranal/StrictAnal.lhs [deleted file]
compiler/stranal/WorkWrap.lhs
compiler/stranal/WwLib.lhs

index d85315a..b1e9ccb 100644 (file)
 \section[Demand]{@Demand@: the amount of demand on a value}
 
 \begin{code}
-#ifndef OLD_STRICTNESS
-module Demand () where
-#else
-
 module Demand(
-       Demand(..),
-
-       wwLazy, wwStrict, wwUnpack, wwPrim, wwEnum, 
-       isStrict, isLazy, isPrim,
-
-       pprDemands, seqDemand, seqDemands,
-
-       StrictnessInfo(..),     
-       mkStrictnessInfo,
-       noStrictnessInfo,
-       ppStrictnessInfo, seqStrictnessInfo,
-       isBottomingStrictness, appIsBottom,
-
+       Demand(..), 
+       topDmd, lazyDmd, seqDmd, evalDmd, errDmd, isStrictDmd, 
+       isTop, isAbsent, seqDemand,
+
+       DmdType(..), topDmdType, botDmdType, mkDmdType, mkTopDmdType, 
+               dmdTypeDepth, seqDmdType,
+       DmdEnv, emptyDmdEnv,
+       DmdResult(..), retCPR, isBotRes, returnsCPR, resTypeArgDmd,
+       
+       Demands(..), mapDmds, zipWithDmds, allTop, seqDemands,
+
+       StrictSig(..), mkStrictSig, topSig, botSig, cprSig,
+        isTopSig,
+       splitStrictSig, increaseStrictSigArity,
+       pprIfaceStrictSig, appIsBottom, isBottomingSig, seqStrictSig,
      ) where
 
 #include "HsVersions.h"
 
-import Outputable
+import StaticFlags
+import BasicTypes
+import VarEnv
+import UniqFM
 import Util
+import Outputable
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsection{The @Demand@ data type}
+\subsection{Demands}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
 data Demand
-  = WwLazy             -- Argument is lazy as far as we know
-       MaybeAbsent     -- (does not imply worker's existence [etc]).
-                       -- If MaybeAbsent == True, then it is
-                       --  *definitely* lazy.  (NB: Absence implies
-                       -- a worker...)
-
-  | WwStrict           -- Argument is strict but that's all we know
-                       -- (does not imply worker's existence or any
-                       -- calling-convention magic)
-
-  | WwUnpack           -- Argument is strict & a single-constructor type
-       Bool            -- True <=> wrapper unpacks it; False <=> doesn't
-       [Demand]        -- Its constituent parts (whose StrictInfos
-                       -- are in the list) should be passed
-                       -- as arguments to the worker.
-
-  | WwPrim             -- Argument is of primitive type, therefore
-                       -- strict; doesn't imply existence of a worker;
-                       -- argument should be passed as is to worker.
-
-  | WwEnum             -- Argument is strict & an enumeration type;
-                       -- an Int# representing the tag (start counting
-                       -- at zero) should be passed to the worker.
-  deriving( Eq )
+  = Top                        -- T; used for unlifted types too, so that
+                       --      A `lub` T = T
+  | Abs                        -- A
 
-type MaybeAbsent = Bool -- True <=> not even used
+  | Call Demand                -- C(d)
 
--- versions that don't worry about Absence:
-wwLazy, wwStrict, wwPrim, wwEnum :: Demand
-wwUnpack :: [Demand] -> Demand
+  | Eval Demands       -- U(ds)
 
-wwLazy     = WwLazy      False
-wwStrict    = WwStrict
-wwUnpack xs = WwUnpack False xs
-wwPrim     = WwPrim
-wwEnum     = WwEnum
+  | Defer Demands      -- D(ds)
 
-seqDemand :: Demand -> ()
-seqDemand (WwLazy a)      = a `seq` ()
-seqDemand (WwUnpack b ds) = b `seq` seqDemands ds
-seqDemand _               = ()
-
-seqDemands :: [Demand] -> ()
-seqDemands [] = ()
-seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
-\end{code}
+  | Box Demand         -- B(d)
 
+  | Bot                        -- B
+  deriving( Eq )
+       -- Equality needed for fixpoints in DmdAnal
+
+data Demands = Poly Demand     -- Polymorphic case
+            | Prod [Demand]    -- Product case
+            deriving( Eq )
+
+allTop :: Demands -> Bool
+allTop (Poly d)  = isTop d
+allTop (Prod ds) = all isTop ds
+
+isTop :: Demand -> Bool
+isTop Top = True
+isTop _   = False 
+
+isAbsent :: Demand -> Bool
+isAbsent Abs = True
+isAbsent _   = False 
+
+mapDmds :: (Demand -> Demand) -> Demands -> Demands
+mapDmds f (Poly d)  = Poly (f d)
+mapDmds f (Prod ds) = Prod (map f ds)
+
+zipWithDmds :: (Demand -> Demand -> Demand)
+           -> Demands -> Demands -> Demands
+zipWithDmds f (Poly d1)  (Poly d2)  = Poly (d1 `f` d2)
+zipWithDmds f (Prod ds1) (Poly d2)  = Prod [d1 `f` d2 | d1 <- ds1]
+zipWithDmds f (Poly d1)  (Prod ds2) = Prod [d1 `f` d2 | d2 <- ds2]
+zipWithDmds f (Prod ds1) (Prod ds2) 
+  | length ds1 == length ds2 = Prod (zipWithEqual "zipWithDmds" f ds1 ds2)
+  | otherwise               = Poly topDmd
+       -- This really can happen with polymorphism
+       -- \f. case f x of (a,b) -> ...
+       --     case f y of (a,b,c) -> ...
+       -- Here the two demands on f are C(LL) and C(LLL)!
+
+topDmd, lazyDmd, seqDmd, evalDmd, errDmd :: Demand
+topDmd  = Top                  -- The most uninformative demand
+lazyDmd = Box Abs
+seqDmd  = Eval (Poly Abs)      -- Polymorphic seq demand
+evalDmd = Box seqDmd           -- Evaluate and return
+errDmd  = Box Bot              -- This used to be called X
+
+isStrictDmd :: Demand -> Bool
+isStrictDmd Bot      = True
+isStrictDmd (Eval _) = True
+isStrictDmd (Call _) = True
+isStrictDmd (Box d)  = isStrictDmd d
+isStrictDmd _        = False
 
-%************************************************************************
-%*                                                                     *
-\subsection{Functions over @Demand@}
-%*                                                                     *
-%************************************************************************
+seqDemand :: Demand -> ()
+seqDemand (Call d)   = seqDemand d
+seqDemand (Eval ds)  = seqDemands ds
+seqDemand (Defer ds) = seqDemands ds
+seqDemand (Box d)    = seqDemand d
+seqDemand _          = ()
 
-\begin{code}
-isLazy :: Demand -> Bool
-isLazy (WwLazy _) = True
-isLazy _         = False
+seqDemands :: Demands -> ()
+seqDemands (Poly d)  = seqDemand d
+seqDemands (Prod ds) = seqDemandList ds
 
-isStrict :: Demand -> Bool
-isStrict d = not (isLazy d)
+seqDemandList :: [Demand] -> ()
+seqDemandList [] = ()
+seqDemandList (d:ds) = seqDemand d `seq` seqDemandList ds
 
-isPrim :: Demand -> Bool
-isPrim WwPrim = True
-isPrim _      = False
+instance Outputable Demand where
+    ppr Top  = char 'T'
+    ppr Abs  = char 'A'
+    ppr Bot  = char 'B'
+
+    ppr (Defer ds)      = char 'D' <> ppr ds
+    ppr (Eval ds)       = char 'U' <> ppr ds
+                                     
+    ppr (Box (Eval ds)) = char 'S' <> ppr ds
+    ppr (Box Abs)      = char 'L'
+    ppr (Box Bot)      = char 'X'
+    ppr d@(Box _)      = pprPanic "ppr: Bad boxed demand" (ppr d)
+
+    ppr (Call d)       = char 'C' <> parens (ppr d)
+
+
+instance Outputable Demands where
+    ppr (Poly Abs) = empty
+    ppr (Poly d)   = parens (ppr d <> char '*')
+    ppr (Prod ds)  = parens (hcat (map ppr ds))
+       -- At one time I printed U(AAA) as U, but that
+       -- confuses (Poly Abs) with (Prod AAA), and the
+       -- worker/wrapper generation differs slightly for these two
+       -- [Reason: in the latter case we can avoid passing the arg;
+       --  see notes with WwLib.mkWWstr_one.]
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsection{Instances}
+\subsection{Demand types}
 %*                                                                     *
 %************************************************************************
 
-
 \begin{code}
-pprDemands :: [Demand] -> Bool -> SDoc
-pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
-                      where
-                        pp_bot | bot       = ptext (sLit "B")
-                               | otherwise = empty
-
-
-pprDemand :: Demand -> SDoc
-pprDemand (WwLazy False)        = char 'L'
-pprDemand (WwLazy True)         = char 'A'
-pprDemand WwStrict              = char 'S'
-pprDemand WwPrim                = char 'P'
-pprDemand WwEnum                = char 'E'
-pprDemand (WwUnpack wu args)     = char ch <> parens (hcat (map pprDemand args))
-                                     where
-                                       ch = if wu then 'U' else 'u'
-
-instance Outputable Demand where
-    ppr (WwLazy False) = empty
-    ppr other_demand   = ptext (sLit "__D") <+> pprDemand other_demand
-
-instance Show Demand where
-    showsPrec p d = showsPrecSDoc p (ppr d)
-
--- Reading demands is done in Lex.lhs
+data DmdType = DmdType 
+                   DmdEnv      -- Demand on explicitly-mentioned 
+                               --      free variables
+                   [Demand]    -- Demand on arguments
+                   DmdResult   -- Nature of result
+
+       --              IMPORTANT INVARIANT
+       -- The default demand on free variables not in the DmdEnv is:
+       -- DmdResult = BotRes        <=>  Bot
+       -- DmdResult = TopRes/ResCPR <=>  Abs
+
+       --              ANOTHER IMPORTANT INVARIANT
+       -- The Demands in the argument list are never
+       --      Bot, Defer d
+       -- Handwavey reason: these don't correspond to calling conventions
+       -- See DmdAnal.funArgDemand for details
+
+
+-- This guy lets us switch off CPR analysis
+-- by making sure that everything uses TopRes instead of RetCPR
+-- Assuming, of course, that they don't mention RetCPR by name.
+-- They should onlyu use retCPR
+retCPR :: DmdResult
+retCPR | opt_CprOff = TopRes
+       | otherwise  = RetCPR
+
+seqDmdType :: DmdType -> ()
+seqDmdType (DmdType _env ds res) = 
+  {- ??? env `seq` -} seqDemandList ds `seq` res `seq` ()
+
+type DmdEnv = VarEnv Demand
+
+data DmdResult = TopRes        -- Nothing known        
+              | RetCPR -- Returns a constructed product
+              | BotRes -- Diverges or errors
+              deriving( Eq, Show )
+       -- Equality for fixpoints
+       -- Show needed for Show in Lex.Token (sigh)
+
+-- Equality needed for fixpoints in DmdAnal
+instance Eq DmdType where
+  (==) (DmdType fv1 ds1 res1)
+       (DmdType fv2 ds2 res2) =  ufmToList fv1 == ufmToList fv2
+                             && ds1 == ds2 && res1 == res2
+
+instance Outputable DmdType where
+  ppr (DmdType fv ds res) 
+    = hsep [text "DmdType",
+           hcat (map ppr ds) <> ppr res,
+           if null fv_elts then empty
+           else braces (fsep (map pp_elt fv_elts))]
+    where
+      pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
+      fv_elts = ufmToList fv
+
+instance Outputable DmdResult where
+  ppr TopRes = empty     -- Keep these distinct from Demand letters
+  ppr RetCPR = char 'm'          -- so that we can print strictness sigs as
+  ppr BotRes = char 'b'   --    dddr
+                         -- without ambiguity
+
+emptyDmdEnv :: VarEnv Demand
+emptyDmdEnv = emptyVarEnv
+
+topDmdType, botDmdType, cprDmdType :: DmdType
+topDmdType = DmdType emptyDmdEnv [] TopRes
+botDmdType = DmdType emptyDmdEnv [] BotRes
+cprDmdType = DmdType emptyVarEnv [] retCPR
+
+isTopDmdType :: DmdType -> Bool
+-- Only used on top-level types, hence the assert
+isTopDmdType (DmdType env [] TopRes) = ASSERT( isEmptyVarEnv env) True 
+isTopDmdType _                       = False
+
+isBotRes :: DmdResult -> Bool
+isBotRes BotRes = True
+isBotRes _      = False
+
+resTypeArgDmd :: DmdResult -> Demand
+-- TopRes and BotRes are polymorphic, so that
+--     BotRes = Bot -> BotRes
+--     TopRes = Top -> TopRes
+-- This function makes that concrete
+-- We can get a RetCPR, because of the way in which we are (now)
+-- giving CPR info to strict arguments.  On the first pass, when
+-- nothing has demand info, we optimistically give CPR info or RetCPR to all args
+resTypeArgDmd TopRes = Top
+resTypeArgDmd RetCPR = Top
+resTypeArgDmd BotRes = Bot
+
+returnsCPR :: DmdResult -> Bool
+returnsCPR RetCPR = True
+returnsCPR _      = False
+
+mkDmdType :: DmdEnv -> [Demand] -> DmdResult -> DmdType
+mkDmdType fv ds res = DmdType fv ds res
+
+mkTopDmdType :: [Demand] -> DmdResult -> DmdType
+mkTopDmdType ds res = DmdType emptyDmdEnv ds res
+
+dmdTypeDepth :: DmdType -> Arity
+dmdTypeDepth (DmdType _ ds _) = length ds
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsection[strictness-IdInfo]{Strictness info about an @Id@}
+\subsection{Strictness signature
 %*                                                                     *
 %************************************************************************
 
-We specify the strictness of a function by giving information about
-each of the ``wrapper's'' arguments (see the description about
-worker/wrapper-style transformations in the PJ/Launchbury paper on
-unboxed types).
+In a let-bound Id we record its strictness info.  
+In principle, this strictness info is a demand transformer, mapping
+a demand on the Id into a DmdType, which gives
+       a) the free vars of the Id's value
+       b) the Id's arguments
+       c) an indication of the result of applying 
+          the Id to its arguments
 
-The list of @Demands@ specifies: (a)~the strictness properties of a
-function's arguments; and (b)~the type signature of that worker (if it
-exists); i.e. its calling convention.
+However, in fact we store in the Id an extremely emascuated demand transfomer,
+namely 
+               a single DmdType
+(Nevertheless we dignify StrictSig as a distinct type.)
 
-Note that the existence of a worker function is now denoted by the Id's
-workerInfo field.
+This DmdType gives the demands unleashed by the Id when it is applied
+to as many arguments as are given in by the arg demands in the DmdType.
 
-\begin{code}
-data StrictnessInfo
-  = NoStrictnessInfo
+For example, the demand transformer described by the DmdType
+               DmdType {x -> U(LL)} [V,A] Top
+says that when the function is applied to two arguments, it
+unleashes demand U(LL) on the free var x, V on the first arg,
+and A on the second.  
 
-  | StrictnessInfo [Demand]    -- Demands on the arguments.
+If this same function is applied to one arg, all we can say is
+that it uses x with U*(LL), and its arg with demand L.
 
-                  Bool         -- True <=> the function diverges regardless of its arguments
-                               -- Useful for "error" and other disguised variants thereof.  
-                               -- BUT NB: f = \x y. error "urk"
-                               --         will have info  SI [SS] True
-                               -- but still (f) and (f 2) are not bot; only (f 3 2) is bot
-  deriving( Eq )
+\begin{code}
+newtype StrictSig = StrictSig DmdType
+                 deriving( Eq )
 
-       -- NOTA BENE: if the arg demands are, say, [S,L], this means that
-       --      (f bot) is not necy bot, only (f bot x) is bot
-       -- We simply cannot express accurately the strictness of a function
-       -- like         f = \x -> case x of (a,b) -> \y -> ...
-       -- The up-side is that we don't need to restrict the strictness info
-       -- to the visible arity of the function.
+instance Outputable StrictSig where
+   ppr (StrictSig ty) = ppr ty
 
-seqStrictnessInfo :: StrictnessInfo -> ()
-seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
-seqStrictnessInfo _                     = ()
-\end{code}
+instance Show StrictSig where
+   show (StrictSig ty) = showSDoc (ppr ty)
 
-\begin{code}
-mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
+mkStrictSig :: DmdType -> StrictSig
+mkStrictSig dmd_ty = StrictSig dmd_ty
+
+splitStrictSig :: StrictSig -> ([Demand], DmdResult)
+splitStrictSig (StrictSig (DmdType _ dmds res)) = (dmds, res)
 
-mkStrictnessInfo (xs, is_bot)
-  | all totally_boring xs && not is_bot        = NoStrictnessInfo              -- Uninteresting
-  | otherwise                          = StrictnessInfo xs is_bot
-  where
-    totally_boring (WwLazy False) = True
-    totally_boring _              = False
+increaseStrictSigArity :: Int -> StrictSig -> StrictSig
+-- Add extra arguments to a strictness signature
+increaseStrictSigArity arity_increase (StrictSig (DmdType env dmds res))
+  = StrictSig (DmdType env (replicate arity_increase topDmd ++ dmds) res)
 
-noStrictnessInfo :: StrictnessInfo
-noStrictnessInfo = NoStrictnessInfo
+isTopSig :: StrictSig -> Bool
+isTopSig (StrictSig ty) = isTopDmdType ty
 
-isBottomingStrictness :: StrictnessInfo -> Bool
-isBottomingStrictness (StrictnessInfo _ bot) = bot
-isBottomingStrictness NoStrictnessInfo       = False
+topSig, botSig, cprSig :: StrictSig
+topSig = StrictSig topDmdType
+botSig = StrictSig botDmdType
+cprSig = StrictSig cprDmdType
+       
 
 -- appIsBottom returns true if an application to n args would diverge
-appIsBottom :: StrictnessInfo -> Int -> Bool
-appIsBottom (StrictnessInfo ds bot)   n = bot && (listLengthCmp ds n /=GT) -- not more than 'n' elts in 'ds'.
-appIsBottom  NoStrictnessInfo         _ = False
+appIsBottom :: StrictSig -> Int -> Bool
+appIsBottom (StrictSig (DmdType _ ds BotRes)) n = listLengthCmp ds n /= GT
+appIsBottom _                                _ = False
 
-ppStrictnessInfo :: StrictnessInfo -> SDoc
-ppStrictnessInfo NoStrictnessInfo                 = empty
-ppStrictnessInfo (StrictnessInfo wrapper_args bot) = hsep [pprDemands wrapper_args bot]
-\end{code}
+isBottomingSig :: StrictSig -> Bool
+isBottomingSig (StrictSig (DmdType _ _ BotRes)) = True
+isBottomingSig _                               = False
 
-\begin{code}
-#endif /* OLD_STRICTNESS */
+seqStrictSig :: StrictSig -> ()
+seqStrictSig (StrictSig ty) = seqDmdType ty
+
+pprIfaceStrictSig :: StrictSig -> SDoc
+-- Used for printing top-level strictness pragmas in interface files
+pprIfaceStrictSig (StrictSig (DmdType _ dmds res))
+  = hcat (map ppr dmds) <> ppr res
 \end{code}
+    
+
index b72d8c2..ceba599 100644 (file)
@@ -67,34 +67,23 @@ module Id (
 
        -- ** Reading 'IdInfo' fields
        idArity, 
-       idNewDemandInfo, idNewDemandInfo_maybe,
-       idNewStrictness, idNewStrictness_maybe, 
+       idDemandInfo, idDemandInfo_maybe,
+       idStrictness, idStrictness_maybe, 
        idUnfolding, realIdUnfolding,
        idSpecialisation, idCoreRules, idHasRules,
        idCafInfo,
        idLBVarInfo,
        idOccInfo,
 
-#ifdef OLD_STRICTNESS
-       idDemandInfo, 
-       idStrictness, 
-       idCprInfo,
-#endif
-
        -- ** Writing 'IdInfo' fields
        setIdUnfolding,
        setIdArity,
-       setIdNewDemandInfo, 
-       setIdNewStrictness, zapIdNewStrictness,
+       setIdDemandInfo, 
+       setIdStrictness, zapIdStrictness,
        setIdSpecialisation,
        setIdCafInfo,
        setIdOccInfo, zapIdOccInfo,
 
-#ifdef OLD_STRICTNESS
-       setIdStrictness, 
-       setIdDemandInfo, 
-       setIdCprInfo,
-#endif
     ) where
 
 #include "HsVersions.h"
@@ -114,11 +103,8 @@ import TyCon
 import Type
 import TcType
 import TysPrim
-#ifdef OLD_STRICTNESS
-import qualified Demand
-#endif
 import DataCon
-import NewDemand
+import Demand
 import Name
 import Module
 import Class
@@ -136,16 +122,11 @@ import StaticFlags
 -- infixl so you can say (id `set` a `set` b)
 infixl         1 `setIdUnfolding`,
          `setIdArity`,
-         `setIdNewDemandInfo`,
-         `setIdNewStrictness`,
+         `setIdDemandInfo`,
+         `setIdStrictness`,
          `setIdSpecialisation`,
          `setInlinePragma`,
          `idCafInfo`
-#ifdef OLD_STRICTNESS
-         ,`idCprInfo`
-         ,`setIdStrictness`
-         ,`setIdDemandInfo`
-#endif
 \end{code}
 
 %************************************************************************
@@ -469,31 +450,21 @@ idArity id = arityInfo (idInfo id)
 setIdArity :: Id -> Arity -> Id
 setIdArity id arity = modifyIdInfo (`setArityInfo` arity) id
 
-#ifdef OLD_STRICTNESS
-       ---------------------------------
-       -- (OLD) STRICTNESS 
-idStrictness :: Id -> StrictnessInfo
-idStrictness id = strictnessInfo (idInfo id)
-
-setIdStrictness :: Id -> StrictnessInfo -> Id
-setIdStrictness id strict_info = modifyIdInfo (`setStrictnessInfo` strict_info) id
-#endif
-
 -- | Returns true if an application to n args would diverge
 isBottomingId :: Id -> Bool
-isBottomingId id = isBottomingSig (idNewStrictness id)
+isBottomingId id = isBottomingSig (idStrictness id)
 
-idNewStrictness_maybe :: Id -> Maybe StrictSig
-idNewStrictness :: Id -> StrictSig
+idStrictness_maybe :: Id -> Maybe StrictSig
+idStrictness :: Id -> StrictSig
 
-idNewStrictness_maybe id = newStrictnessInfo (idInfo id)
-idNewStrictness       id = idNewStrictness_maybe id `orElse` topSig
+idStrictness_maybe id = strictnessInfo (idInfo id)
+idStrictness       id = idStrictness_maybe id `orElse` topSig
 
-setIdNewStrictness :: Id -> StrictSig -> Id
-setIdNewStrictness id sig = modifyIdInfo (`setNewStrictnessInfo` Just sig) id
+setIdStrictness :: Id -> StrictSig -> Id
+setIdStrictness id sig = modifyIdInfo (`setStrictnessInfo` Just sig) id
 
-zapIdNewStrictness :: Id -> Id
-zapIdNewStrictness id = modifyIdInfo (`setNewStrictnessInfo` Nothing) id
+zapIdStrictness :: Id -> Id
+zapIdStrictness id = modifyIdInfo (`setStrictnessInfo` Nothing) id
 
 -- | This predicate says whether the 'Id' has a strict demand placed on it or
 -- has a type such that it can always be evaluated strictly (e.g., an
@@ -504,7 +475,7 @@ zapIdNewStrictness id = modifyIdInfo (`setNewStrictnessInfo` Nothing) id
 isStrictId :: Id -> Bool
 isStrictId id
   = ASSERT2( isId id, text "isStrictId: not an id: " <+> ppr id )
-           (isStrictDmd (idNewDemandInfo id)) || 
+           (isStrictDmd (idDemandInfo id)) || 
            (isStrictType (idType id))
 
        ---------------------------------
@@ -524,24 +495,14 @@ realIdUnfolding id = unfoldingInfo (idInfo id)
 setIdUnfolding :: Id -> Unfolding -> Id
 setIdUnfolding id unfolding = modifyIdInfo (`setUnfoldingInfo` unfolding) id
 
-#ifdef OLD_STRICTNESS
-       ---------------------------------
-       -- (OLD) DEMAND
-idDemandInfo :: Id -> Demand.Demand
-idDemandInfo id = demandInfo (idInfo id)
-
-setIdDemandInfo :: Id -> Demand.Demand -> Id
-setIdDemandInfo id demand_info = modifyIdInfo (`setDemandInfo` demand_info) id
-#endif
-
-idNewDemandInfo_maybe :: Id -> Maybe NewDemand.Demand
-idNewDemandInfo       :: Id -> NewDemand.Demand
+idDemandInfo_maybe :: Id -> Maybe Demand
+idDemandInfo       :: Id -> Demand
 
-idNewDemandInfo_maybe id = newDemandInfo (idInfo id)
-idNewDemandInfo       id = newDemandInfo (idInfo id) `orElse` NewDemand.topDmd
+idDemandInfo_maybe id = demandInfo (idInfo id)
+idDemandInfo       id = demandInfo (idInfo id) `orElse` topDmd
 
-setIdNewDemandInfo :: Id -> NewDemand.Demand -> Id
-setIdNewDemandInfo id dmd = modifyIdInfo (`setNewDemandInfo` Just dmd) id
+setIdDemandInfo :: Id -> Demand -> Id
+setIdDemandInfo id dmd = modifyIdInfo (`setDemandInfo` Just dmd) id
 
        ---------------------------------
        -- SPECIALISATION
@@ -563,28 +524,12 @@ setIdSpecialisation id spec_info = modifyIdInfo (`setSpecInfo` spec_info) id
        ---------------------------------
        -- CAF INFO
 idCafInfo :: Id -> CafInfo
-#ifdef OLD_STRICTNESS
-idCafInfo id = case cgInfo (idInfo id) of
-                 NoCgInfo -> pprPanic "idCafInfo" (ppr id)
-                 info     -> cgCafInfo info
-#else
 idCafInfo id = cafInfo (idInfo id)
-#endif
 
 setIdCafInfo :: Id -> CafInfo -> Id
 setIdCafInfo id caf_info = modifyIdInfo (`setCafInfo` caf_info) id
 
        ---------------------------------
-       -- CPR INFO
-#ifdef OLD_STRICTNESS
-idCprInfo :: Id -> CprInfo
-idCprInfo id = cprInfo (idInfo id)
-
-setIdCprInfo :: Id -> CprInfo -> Id
-setIdCprInfo id cpr_info = modifyIdInfo (`setCprInfo` cpr_info) id
-#endif
-
-       ---------------------------------
        -- Occcurrence INFO
 idOccInfo :: Id -> OccInfo
 idOccInfo id = occInfo (idInfo id)
@@ -751,10 +696,10 @@ transferPolyIdInfo old_id abstract_wrt new_id
     old_arity       = arityInfo old_info
     old_inline_prag = inlinePragInfo old_info
     new_arity       = old_arity + arity_increase
-    old_strictness  = newStrictnessInfo old_info
+    old_strictness  = strictnessInfo old_info
     new_strictness  = fmap (increaseStrictSigArity arity_increase) old_strictness
 
-    transfer new_info = new_info `setNewStrictnessInfo` new_strictness
+    transfer new_info = new_info `setStrictnessInfo` new_strictness
                                 `setArityInfo` new_arity
                                 `setInlinePragInfo` old_inline_prag
 \end{code}
index 9b74a48..0a173d9 100644 (file)
@@ -26,28 +26,8 @@ module IdInfo (
        arityInfo, setArityInfo, ppArityInfo, 
 
        -- ** Demand and strictness Info
-       newStrictnessInfo, setNewStrictnessInfo, 
-       newDemandInfo, setNewDemandInfo, pprNewStrictness,
-       setAllStrictnessInfo,
-
-#ifdef OLD_STRICTNESS
-       -- ** Old strictness Info
-       StrictnessInfo(..),
-       mkStrictnessInfo, noStrictnessInfo,
-       ppStrictnessInfo, isBottomingStrictness, 
-       strictnessInfo, setStrictnessInfo,
-       
-        oldStrictnessFromNew, newStrictnessFromOld,
-
-       -- ** Old demand Info
-       demandInfo, setDemandInfo, 
-       oldDemand, newDemand,
-
-        -- ** Old Constructed Product Result Info
-        CprInfo(..), 
-        cprInfo, setCprInfo, ppCprInfo, noCprInfo,
-        cprInfoFromNewStrictness,
-#endif
+       strictnessInfo, setStrictnessInfo, 
+       demandInfo, setDemandInfo, pprStrictness,
 
        -- ** Unfolding Info
        unfoldingInfo, setUnfoldingInfo, setUnfoldingInfoLazily,
@@ -94,20 +74,13 @@ import BasicTypes
 import DataCon
 import TyCon
 import ForeignCall
-import NewDemand
+import Demand
 import Outputable      
 import Module
 import FastString
 
 import Data.Maybe
 
-#ifdef OLD_STRICTNESS
-import Demand
-import qualified Demand
-import Util
-import Data.List
-#endif
-
 -- infixl so you can say (id `set` a `set` b)
 infixl         1 `setSpecInfo`,
          `setArityInfo`,
@@ -116,117 +89,12 @@ infixl    1 `setSpecInfo`,
          `setLBVarInfo`,
          `setOccInfo`,
          `setCafInfo`,
-         `setNewStrictnessInfo`,
-         `setAllStrictnessInfo`,
-         `setNewDemandInfo`
-#ifdef OLD_STRICTNESS
-         , `setCprInfo`
-         , `setDemandInfo`
-         , `setStrictnessInfo`
-#endif
+         `setStrictnessInfo`,
+         `setDemandInfo`
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection{New strictness info}
-%*                                                                     *
-%************************************************************************
-
-To be removed later
-
-\begin{code}
--- | Set old and new strictness information together
-setAllStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
-setAllStrictnessInfo info Nothing
-  = info { newStrictnessInfo = Nothing
-#ifdef OLD_STRICTNESS
-         , strictnessInfo = NoStrictnessInfo
-         , cprInfo = NoCPRInfo
-#endif
-         }
-
-setAllStrictnessInfo info (Just sig)
-  = info { newStrictnessInfo = Just sig
-#ifdef OLD_STRICTNESS
-         , strictnessInfo = oldStrictnessFromNew sig
-         , cprInfo = cprInfoFromNewStrictness sig
-#endif
-         }
-
-seqNewStrictnessInfo :: Maybe StrictSig -> ()
-seqNewStrictnessInfo Nothing = ()
-seqNewStrictnessInfo (Just ty) = seqStrictSig ty
-
-pprNewStrictness :: Maybe StrictSig -> SDoc
-pprNewStrictness Nothing    = empty
-pprNewStrictness (Just sig) = ppr sig
-
-#ifdef OLD_STRICTNESS
-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 name arity $
-    mkTopDmdType (map newDemand ds) (newRes res 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 name arity $
-    mkTopDmdType (replicate arity lazyDmd) (newRes False cpr)
-
-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
-newRes False ReturnsCPR = retCPR
-newRes False NoCPRInfo  = TopRes
-
-newDemand :: Demand.Demand -> NewDemand.Demand
-newDemand (WwLazy True)      = Abs
-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 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 /* OLD_STRICTNESS */
-\end{code}
-
-
-\begin{code}
-seqNewDemandInfo :: Maybe Demand -> ()
-seqNewDemandInfo Nothing    = ()
-seqNewDemandInfo (Just dmd) = seqDemand dmd
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
                      IdDetails
 %*                                                                     *
 %************************************************************************
@@ -311,23 +179,18 @@ data IdInfo
        arityInfo       :: !ArityInfo,          -- ^ 'Id' arity
        specInfo        :: SpecInfo,            -- ^ Specialisations of the 'Id's function which exist
                                                -- See Note [Specialisations and RULES in IdInfo]
-#ifdef OLD_STRICTNESS
-       cprInfo         :: CprInfo,             -- ^ If the 'Id's function always constructs a product result
-       demandInfo      :: Demand.Demand,       -- ^ Whether or not the 'Id' is definitely demanded
-       strictnessInfo  :: StrictnessInfo,      -- ^ 'Id' strictness properties
-#endif
        unfoldingInfo   :: Unfolding,           -- ^ The 'Id's unfolding
        cafInfo         :: CafInfo,             -- ^ 'Id' CAF info
         lbvarInfo      :: LBVarInfo,           -- ^ Info about a lambda-bound variable, if the 'Id' is one
        inlinePragInfo  :: InlinePragma,        -- ^ Any inline pragma atached to the 'Id'
        occInfo         :: OccInfo,             -- ^ How the 'Id' occurs in the program
 
-       newStrictnessInfo :: Maybe StrictSig,   -- ^ Id strictness information. Reason for Maybe: 
+       strictnessInfo :: Maybe StrictSig,      -- ^ Id strictness information. Reason for Maybe: 
                                                -- the DmdAnal phase needs to know whether
                                                -- this is the first visit, so it can assign botSig.
                                                -- Other customers want topSig.  So @Nothing@ is good.
 
-       newDemandInfo     :: Maybe Demand       -- ^ Id demand information. Similarly we want to know 
+       demandInfo        :: Maybe Demand       -- ^ Id demand information. Similarly we want to know 
                                                -- if there's no known demand yet, for when we are looking
                                                -- for CPR info
     }
@@ -346,18 +209,20 @@ megaSeqIdInfo info
 -- some unfoldings are not calculated at all
 --    seqUnfolding (unfoldingInfo info)                `seq`
 
-    seqNewDemandInfo (newDemandInfo info)      `seq`
-    seqNewStrictnessInfo (newStrictnessInfo info) `seq`
-
-#ifdef OLD_STRICTNESS
-    Demand.seqDemand (demandInfo info)         `seq`
-    seqStrictnessInfo (strictnessInfo info)    `seq`
-    seqCpr (cprInfo info)                      `seq`
-#endif
+    seqDemandInfo (demandInfo info)    `seq`
+    seqStrictnessInfo (strictnessInfo info) `seq`
 
     seqCaf (cafInfo info)                      `seq`
     seqLBVar (lbvarInfo info)                  `seq`
     seqOccInfo (occInfo info) 
+
+seqStrictnessInfo :: Maybe StrictSig -> ()
+seqStrictnessInfo Nothing = ()
+seqStrictnessInfo (Just ty) = seqStrictSig ty
+
+seqDemandInfo :: Maybe Demand -> ()
+seqDemandInfo Nothing    = ()
+seqDemandInfo (Just dmd) = seqDemand dmd
 \end{code}
 
 Setters
@@ -369,9 +234,6 @@ setInlinePragInfo :: IdInfo -> InlinePragma -> IdInfo
 setInlinePragInfo info pr = pr `seq` info { inlinePragInfo = pr }
 setOccInfo :: IdInfo -> OccInfo -> IdInfo
 setOccInfo       info oc = oc `seq` info { occInfo = oc }
-#ifdef OLD_STRICTNESS
-setStrictnessInfo info st = st `seq` info { strictnessInfo = st }
-#endif
        -- Try to avoid spack leaks by seq'ing
 
 setUnfoldingInfoLazily :: IdInfo -> Unfolding -> IdInfo
@@ -385,11 +247,6 @@ setUnfoldingInfo info uf
        -- actually increases residency significantly. 
   = info { unfoldingInfo = uf }
 
-#ifdef OLD_STRICTNESS
-setDemandInfo    info dd = info { demandInfo = dd }
-setCprInfo        info cp = info { cprInfo = cp }
-#endif
-
 setArityInfo :: IdInfo -> ArityInfo -> IdInfo
 setArityInfo     info ar  = info { arityInfo = ar  }
 setCafInfo :: IdInfo -> CafInfo -> IdInfo
@@ -398,10 +255,11 @@ setCafInfo        info caf = info { cafInfo = caf }
 setLBVarInfo :: IdInfo -> LBVarInfo -> IdInfo
 setLBVarInfo      info lb = {-lb `seq`-} info { lbvarInfo = lb }
 
-setNewDemandInfo :: IdInfo -> Maybe Demand -> IdInfo
-setNewDemandInfo     info dd = dd `seq` info { newDemandInfo = dd }
-setNewStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
-setNewStrictnessInfo info dd = dd `seq` info { newStrictnessInfo = dd }
+setDemandInfo :: IdInfo -> Maybe Demand -> IdInfo
+setDemandInfo     info dd = dd `seq` info { demandInfo = dd }
+
+setStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
+setStrictnessInfo info dd = dd `seq` info { strictnessInfo = dd }
 \end{code}
 
 
@@ -412,18 +270,13 @@ vanillaIdInfo
   = IdInfo {
            cafInfo             = vanillaCafInfo,
            arityInfo           = unknownArity,
-#ifdef OLD_STRICTNESS
-           cprInfo             = NoCPRInfo,
-           demandInfo          = wwLazy,
-           strictnessInfo      = NoStrictnessInfo,
-#endif
            specInfo            = emptySpecInfo,
            unfoldingInfo       = noUnfolding,
            lbvarInfo           = NoLBVarInfo,
            inlinePragInfo      = defaultInlinePragma,
            occInfo             = NoOccInfo,
-           newDemandInfo       = Nothing,
-           newStrictnessInfo   = Nothing
+           demandInfo  = Nothing,
+           strictnessInfo   = Nothing
           }
 
 -- | More informative 'IdInfo' we can use when we know the 'Id' has no CAF references
@@ -485,6 +338,19 @@ type InlinePragInfo = InlinePragma
 
 %************************************************************************
 %*                                                                     *
+               Strictness
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+pprStrictness :: Maybe StrictSig -> SDoc
+pprStrictness Nothing    = empty
+pprStrictness (Just sig) = ppr sig
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
        SpecInfo
 %*                                                                     *
 %************************************************************************
@@ -586,59 +452,6 @@ ppCafInfo MayHaveCafRefs = empty
 
 %************************************************************************
 %*                                                                     *
-\subsection[cpr-IdInfo]{Constructed Product Result info about an @Id@}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#ifdef OLD_STRICTNESS
--- | If the @Id@ is a function then it may have Constructed Product Result 
--- (CPR) info. A CPR analysis phase detects whether:
--- 
--- 1. The function's return value has a product type, i.e. an algebraic  type 
--- with a single constructor. Examples of such types are tuples and boxed
--- primitive values.
---
--- 2. The function always 'constructs' the value that it is returning.  It
--- must do this on every path through,  and it's OK if it calls another
--- function which constructs the result.
--- 
--- If this is the case then we store a template which tells us the
--- function has the CPR property and which components of the result are
--- also CPRs.
-data CprInfo
-  = NoCPRInfo   -- ^ No, this function does not return a constructed product
-  | ReturnsCPR -- ^ Yes, this function returns a constructed product
-               
-               -- Implicitly, this means "after the function has been applied
-               -- to all its arguments", so the worker\/wrapper builder in 
-               -- WwLib.mkWWcpr checks that that it is indeed saturated before
-               -- making use of the CPR info
-
-       -- We used to keep nested info about sub-components, but
-       -- we never used it so I threw it away
-
--- | It's always safe to assume that an 'Id' does not have the CPR property
-noCprInfo :: CprInt
-noCprInfo = NoCPRInfo
-
-seqCpr :: CprInfo -> ()
-seqCpr ReturnsCPR = ()
-seqCpr NoCPRInfo  = ()
-
-ppCprInfo NoCPRInfo  = empty
-ppCprInfo ReturnsCPR = ptext (sLit "__M")
-
-instance Outputable CprInfo where
-    ppr = ppCprInfo
-
-instance Show CprInfo where
-    showsPrec p c = showsPrecSDoc p (ppr c)
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
 \subsection[lbvar-IdInfo]{Lambda-bound var info about an @Id@}
 %*                                                                     *
 %************************************************************************
@@ -690,11 +503,11 @@ instance Show LBVarInfo where
 --
 -- > (\x1. \x2. e) arg1
 zapLamInfo :: IdInfo -> Maybe IdInfo
-zapLamInfo info@(IdInfo {occInfo = occ, newDemandInfo = demand})
+zapLamInfo info@(IdInfo {occInfo = occ, demandInfo = demand})
   | is_safe_occ occ && is_safe_dmd demand
   = Nothing
   | otherwise
-  = Just (info {occInfo = safe_occ, newDemandInfo = Nothing})
+  = Just (info {occInfo = safe_occ, demandInfo = Nothing})
   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
@@ -712,8 +525,8 @@ zapLamInfo info@(IdInfo {occInfo = occ, newDemandInfo = demand})
 \begin{code}
 -- | Remove demand info on the 'IdInfo' if it is present, otherwise return @Nothing@
 zapDemandInfo :: IdInfo -> Maybe IdInfo
-zapDemandInfo info@(IdInfo {newDemandInfo = dmd})
-  | isJust dmd = Just (info {newDemandInfo = Nothing})
+zapDemandInfo info@(IdInfo {demandInfo = dmd})
+  | isJust dmd = Just (info {demandInfo = Nothing})
   | otherwise  = Nothing
 \end{code}
 
index 6d8df87..1eacea9 100644 (file)
@@ -65,7 +65,7 @@ import DataCon
 import Id
 import Var              ( Var, TyVar, mkCoVar, mkExportedLocalVar )
 import IdInfo
-import NewDemand
+import Demand
 import CoreSyn
 import Unique
 import PrelNames
@@ -265,7 +265,7 @@ mkDataConIds wrap_name wkr_name data_con
     wkr_arity = dataConRepArity data_con
     wkr_info  = noCafIdInfo
                 `setArityInfo`          wkr_arity
-                `setAllStrictnessInfo`  Just wkr_sig
+                `setStrictnessInfo`  Just wkr_sig
                 `setUnfoldingInfo`      evaldUnfolding  -- Record that it's evaluated,
                                                         -- even if arity = 0
 
@@ -329,7 +329,7 @@ mkDataConIds wrap_name wkr_name data_con
                         -- It's important to specify the arity, so that partial
                         -- applications are treated as values
                     `setUnfoldingInfo`     wrap_unf
-                    `setAllStrictnessInfo` Just wrap_sig
+                    `setStrictnessInfo` Just wrap_sig
 
     all_strict_marks = dataConExStricts data_con ++ dataConStrictMarks data_con
     wrap_sig = mkStrictSig (mkTopDmdType arg_dmds cpr_info)
@@ -459,7 +459,7 @@ mkDictSelId no_unf name clas
 
     base_info = noCafIdInfo
                 `setArityInfo`      1
-                `setAllStrictnessInfo`  Just strict_sig
+                `setStrictnessInfo`  Just strict_sig
                 `setUnfoldingInfo`  (if no_unf then noUnfolding
                                     else mkImplicitUnfolding rhs)
                   -- In module where class op is defined, we must add
@@ -763,7 +763,7 @@ mkPrimOpId prim_op
     info = noCafIdInfo
            `setSpecInfo`          mkSpecInfo (primOpRules prim_op name)
            `setArityInfo`         arity
-           `setAllStrictnessInfo` Just strict_sig
+           `setStrictnessInfo` Just strict_sig
 
 -- For each ccall we manufacture a separate CCallOpId, giving it
 -- a fresh unique, a type that is correct for this particular ccall,
@@ -789,7 +789,7 @@ mkFCallId uniq fcall ty
 
     info = noCafIdInfo
            `setArityInfo`         arity
-           `setAllStrictnessInfo` Just strict_sig
+           `setStrictnessInfo` Just strict_sig
 
     (_, tau)     = tcSplitForAllTys ty
     (arg_tys, _) = tcSplitFunTys tau
@@ -1158,7 +1158,7 @@ pc_bottoming_Id :: Name -> Type -> Id
 pc_bottoming_Id name ty
  = pcMiscPrelId name ty bottoming_info
  where
-    bottoming_info = vanillaIdInfo `setAllStrictnessInfo` Just strict_sig
+    bottoming_info = vanillaIdInfo `setStrictnessInfo` Just strict_sig
                                   `setArityInfo`         1
                        -- Make arity and strictness agree
 
diff --git a/compiler/basicTypes/NewDemand.lhs b/compiler/basicTypes/NewDemand.lhs
deleted file mode 100644 (file)
index e97a7db..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-%
-% (c) The University of Glasgow 2006
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-%
-\section[Demand]{@Demand@: the amount of demand on a value}
-
-\begin{code}
-module NewDemand(
-       Demand(..), 
-       topDmd, lazyDmd, seqDmd, evalDmd, errDmd, isStrictDmd, 
-       isTop, isAbsent, seqDemand,
-
-       DmdType(..), topDmdType, botDmdType, mkDmdType, mkTopDmdType, 
-               dmdTypeDepth, seqDmdType,
-       DmdEnv, emptyDmdEnv,
-       DmdResult(..), retCPR, isBotRes, returnsCPR, resTypeArgDmd,
-       
-       Demands(..), mapDmds, zipWithDmds, allTop, seqDemands,
-
-       StrictSig(..), mkStrictSig, topSig, botSig, cprSig,
-        isTopSig,
-       splitStrictSig, increaseStrictSigArity,
-       pprIfaceStrictSig, appIsBottom, isBottomingSig, seqStrictSig,
-     ) where
-
-#include "HsVersions.h"
-
-import StaticFlags
-import BasicTypes
-import VarEnv
-import UniqFM
-import Util
-import Outputable
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Demands}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-data Demand
-  = Top                        -- T; used for unlifted types too, so that
-                       --      A `lub` T = T
-  | Abs                        -- A
-
-  | Call Demand                -- C(d)
-
-  | Eval Demands       -- U(ds)
-
-  | Defer Demands      -- D(ds)
-
-  | Box Demand         -- B(d)
-
-  | Bot                        -- B
-  deriving( Eq )
-       -- Equality needed for fixpoints in DmdAnal
-
-data Demands = Poly Demand     -- Polymorphic case
-            | Prod [Demand]    -- Product case
-            deriving( Eq )
-
-allTop :: Demands -> Bool
-allTop (Poly d)  = isTop d
-allTop (Prod ds) = all isTop ds
-
-isTop :: Demand -> Bool
-isTop Top = True
-isTop _   = False 
-
-isAbsent :: Demand -> Bool
-isAbsent Abs = True
-isAbsent _   = False 
-
-mapDmds :: (Demand -> Demand) -> Demands -> Demands
-mapDmds f (Poly d)  = Poly (f d)
-mapDmds f (Prod ds) = Prod (map f ds)
-
-zipWithDmds :: (Demand -> Demand -> Demand)
-           -> Demands -> Demands -> Demands
-zipWithDmds f (Poly d1)  (Poly d2)  = Poly (d1 `f` d2)
-zipWithDmds f (Prod ds1) (Poly d2)  = Prod [d1 `f` d2 | d1 <- ds1]
-zipWithDmds f (Poly d1)  (Prod ds2) = Prod [d1 `f` d2 | d2 <- ds2]
-zipWithDmds f (Prod ds1) (Prod ds2) 
-  | length ds1 == length ds2 = Prod (zipWithEqual "zipWithDmds" f ds1 ds2)
-  | otherwise               = Poly topDmd
-       -- This really can happen with polymorphism
-       -- \f. case f x of (a,b) -> ...
-       --     case f y of (a,b,c) -> ...
-       -- Here the two demands on f are C(LL) and C(LLL)!
-
-topDmd, lazyDmd, seqDmd, evalDmd, errDmd :: Demand
-topDmd  = Top                  -- The most uninformative demand
-lazyDmd = Box Abs
-seqDmd  = Eval (Poly Abs)      -- Polymorphic seq demand
-evalDmd = Box seqDmd           -- Evaluate and return
-errDmd  = Box Bot              -- This used to be called X
-
-isStrictDmd :: Demand -> Bool
-isStrictDmd Bot      = True
-isStrictDmd (Eval _) = True
-isStrictDmd (Call _) = True
-isStrictDmd (Box d)  = isStrictDmd d
-isStrictDmd _        = False
-
-seqDemand :: Demand -> ()
-seqDemand (Call d)   = seqDemand d
-seqDemand (Eval ds)  = seqDemands ds
-seqDemand (Defer ds) = seqDemands ds
-seqDemand (Box d)    = seqDemand d
-seqDemand _          = ()
-
-seqDemands :: Demands -> ()
-seqDemands (Poly d)  = seqDemand d
-seqDemands (Prod ds) = seqDemandList ds
-
-seqDemandList :: [Demand] -> ()
-seqDemandList [] = ()
-seqDemandList (d:ds) = seqDemand d `seq` seqDemandList ds
-
-instance Outputable Demand where
-    ppr Top  = char 'T'
-    ppr Abs  = char 'A'
-    ppr Bot  = char 'B'
-
-    ppr (Defer ds)      = char 'D' <> ppr ds
-    ppr (Eval ds)       = char 'U' <> ppr ds
-                                     
-    ppr (Box (Eval ds)) = char 'S' <> ppr ds
-    ppr (Box Abs)      = char 'L'
-    ppr (Box Bot)      = char 'X'
-    ppr d@(Box _)      = pprPanic "ppr: Bad boxed demand" (ppr d)
-
-    ppr (Call d)       = char 'C' <> parens (ppr d)
-
-
-instance Outputable Demands where
-    ppr (Poly Abs) = empty
-    ppr (Poly d)   = parens (ppr d <> char '*')
-    ppr (Prod ds)  = parens (hcat (map ppr ds))
-       -- At one time I printed U(AAA) as U, but that
-       -- confuses (Poly Abs) with (Prod AAA), and the
-       -- worker/wrapper generation differs slightly for these two
-       -- [Reason: in the latter case we can avoid passing the arg;
-       --  see notes with WwLib.mkWWstr_one.]
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Demand types}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-data DmdType = DmdType 
-                   DmdEnv      -- Demand on explicitly-mentioned 
-                               --      free variables
-                   [Demand]    -- Demand on arguments
-                   DmdResult   -- Nature of result
-
-       --              IMPORTANT INVARIANT
-       -- The default demand on free variables not in the DmdEnv is:
-       -- DmdResult = BotRes        <=>  Bot
-       -- DmdResult = TopRes/ResCPR <=>  Abs
-
-       --              ANOTHER IMPORTANT INVARIANT
-       -- The Demands in the argument list are never
-       --      Bot, Defer d
-       -- Handwavey reason: these don't correspond to calling conventions
-       -- See DmdAnal.funArgDemand for details
-
-
--- This guy lets us switch off CPR analysis
--- by making sure that everything uses TopRes instead of RetCPR
--- Assuming, of course, that they don't mention RetCPR by name.
--- They should onlyu use retCPR
-retCPR :: DmdResult
-retCPR | opt_CprOff = TopRes
-       | otherwise  = RetCPR
-
-seqDmdType :: DmdType -> ()
-seqDmdType (DmdType _env ds res) = 
-  {- ??? env `seq` -} seqDemandList ds `seq` res `seq` ()
-
-type DmdEnv = VarEnv Demand
-
-data DmdResult = TopRes        -- Nothing known        
-              | RetCPR -- Returns a constructed product
-              | BotRes -- Diverges or errors
-              deriving( Eq, Show )
-       -- Equality for fixpoints
-       -- Show needed for Show in Lex.Token (sigh)
-
--- Equality needed for fixpoints in DmdAnal
-instance Eq DmdType where
-  (==) (DmdType fv1 ds1 res1)
-       (DmdType fv2 ds2 res2) =  ufmToList fv1 == ufmToList fv2
-                             && ds1 == ds2 && res1 == res2
-
-instance Outputable DmdType where
-  ppr (DmdType fv ds res) 
-    = hsep [text "DmdType",
-           hcat (map ppr ds) <> ppr res,
-           if null fv_elts then empty
-           else braces (fsep (map pp_elt fv_elts))]
-    where
-      pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
-      fv_elts = ufmToList fv
-
-instance Outputable DmdResult where
-  ppr TopRes = empty     -- Keep these distinct from Demand letters
-  ppr RetCPR = char 'm'          -- so that we can print strictness sigs as
-  ppr BotRes = char 'b'   --    dddr
-                         -- without ambiguity
-
-emptyDmdEnv :: VarEnv Demand
-emptyDmdEnv = emptyVarEnv
-
-topDmdType, botDmdType, cprDmdType :: DmdType
-topDmdType = DmdType emptyDmdEnv [] TopRes
-botDmdType = DmdType emptyDmdEnv [] BotRes
-cprDmdType = DmdType emptyVarEnv [] retCPR
-
-isTopDmdType :: DmdType -> Bool
--- Only used on top-level types, hence the assert
-isTopDmdType (DmdType env [] TopRes) = ASSERT( isEmptyVarEnv env) True 
-isTopDmdType _                       = False
-
-isBotRes :: DmdResult -> Bool
-isBotRes BotRes = True
-isBotRes _      = False
-
-resTypeArgDmd :: DmdResult -> Demand
--- TopRes and BotRes are polymorphic, so that
---     BotRes = Bot -> BotRes
---     TopRes = Top -> TopRes
--- This function makes that concrete
--- We can get a RetCPR, because of the way in which we are (now)
--- giving CPR info to strict arguments.  On the first pass, when
--- nothing has demand info, we optimistically give CPR info or RetCPR to all args
-resTypeArgDmd TopRes = Top
-resTypeArgDmd RetCPR = Top
-resTypeArgDmd BotRes = Bot
-
-returnsCPR :: DmdResult -> Bool
-returnsCPR RetCPR = True
-returnsCPR _      = False
-
-mkDmdType :: DmdEnv -> [Demand] -> DmdResult -> DmdType
-mkDmdType fv ds res = DmdType fv ds res
-
-mkTopDmdType :: [Demand] -> DmdResult -> DmdType
-mkTopDmdType ds res = DmdType emptyDmdEnv ds res
-
-dmdTypeDepth :: DmdType -> Arity
-dmdTypeDepth (DmdType _ ds _) = length ds
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Strictness signature
-%*                                                                     *
-%************************************************************************
-
-In a let-bound Id we record its strictness info.  
-In principle, this strictness info is a demand transformer, mapping
-a demand on the Id into a DmdType, which gives
-       a) the free vars of the Id's value
-       b) the Id's arguments
-       c) an indication of the result of applying 
-          the Id to its arguments
-
-However, in fact we store in the Id an extremely emascuated demand transfomer,
-namely 
-               a single DmdType
-(Nevertheless we dignify StrictSig as a distinct type.)
-
-This DmdType gives the demands unleashed by the Id when it is applied
-to as many arguments as are given in by the arg demands in the DmdType.
-
-For example, the demand transformer described by the DmdType
-               DmdType {x -> U(LL)} [V,A] Top
-says that when the function is applied to two arguments, it
-unleashes demand U(LL) on the free var x, V on the first arg,
-and A on the second.  
-
-If this same function is applied to one arg, all we can say is
-that it uses x with U*(LL), and its arg with demand L.
-
-\begin{code}
-newtype StrictSig = StrictSig DmdType
-                 deriving( Eq )
-
-instance Outputable StrictSig where
-   ppr (StrictSig ty) = ppr ty
-
-instance Show StrictSig where
-   show (StrictSig ty) = showSDoc (ppr ty)
-
-mkStrictSig :: DmdType -> StrictSig
-mkStrictSig dmd_ty = StrictSig dmd_ty
-
-splitStrictSig :: StrictSig -> ([Demand], DmdResult)
-splitStrictSig (StrictSig (DmdType _ dmds res)) = (dmds, res)
-
-increaseStrictSigArity :: Int -> StrictSig -> StrictSig
--- Add extra arguments to a strictness signature
-increaseStrictSigArity arity_increase (StrictSig (DmdType env dmds res))
-  = StrictSig (DmdType env (replicate arity_increase topDmd ++ dmds) res)
-
-isTopSig :: StrictSig -> Bool
-isTopSig (StrictSig ty) = isTopDmdType ty
-
-topSig, botSig, cprSig :: StrictSig
-topSig = StrictSig topDmdType
-botSig = StrictSig botDmdType
-cprSig = StrictSig cprDmdType
-       
-
--- appIsBottom returns true if an application to n args would diverge
-appIsBottom :: StrictSig -> Int -> Bool
-appIsBottom (StrictSig (DmdType _ ds BotRes)) n = listLengthCmp ds n /= GT
-appIsBottom _                                _ = False
-
-isBottomingSig :: StrictSig -> Bool
-isBottomingSig (StrictSig (DmdType _ _ BotRes)) = True
-isBottomingSig _                               = False
-
-seqStrictSig :: StrictSig -> ()
-seqStrictSig (StrictSig ty) = seqDmdType ty
-
-pprIfaceStrictSig :: StrictSig -> SDoc
--- Used for printing top-level strictness pragmas in interface files
-pprIfaceStrictSig (StrictSig (DmdType _ dmds res))
-  = hcat (map ppr dmds) <> ppr res
-\end{code}
-    
-
index 673d619..be34b07 100644 (file)
@@ -17,7 +17,7 @@ module CoreArity (
 import CoreSyn
 import CoreFVs
 import CoreUtils
-import NewDemand
+import Demand
 import TyCon   ( isRecursiveTyCon )
 import qualified CoreSubst
 import CoreSubst ( Subst, substBndr, substBndrs, substExpr
@@ -361,7 +361,7 @@ trimArity False  (AT _ ATop) = AT 0 ATop    -- Bale out
 ---------------------------
 arityType :: Bool -> CoreExpr -> ArityType
 arityType _ (Var v)
-  | Just strict_sig <- idNewStrictness_maybe v
+  | Just strict_sig <- idStrictness_maybe v
   , (ds, res) <- splitStrictSig strict_sig
   , isBotRes res
   = AT (length ds) ABot        -- Function diverges
index d6cdad8..4893885 100644 (file)
@@ -11,7 +11,7 @@ module CoreLint ( lintCoreBindings, lintUnfolding ) where
 
 #include "HsVersions.h"
 
-import NewDemand
+import Demand
 import CoreSyn
 import CoreFVs
 import CoreUtils
@@ -204,7 +204,7 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs)
        -- the unfolding is a SimplifiableCoreExpr. Give up for now.
    where
     binder_ty                  = idType binder
-    maybeDmdTy                 = idNewStrictness_maybe binder
+    maybeDmdTy                 = idStrictness_maybe binder
     bndr_vars                  = varSetElems (idFreeVars binder)
     lintBinder var | isId var  = lintIdBndr var $ \_ -> (return ())
                   | otherwise = return ()
@@ -1083,7 +1083,7 @@ mkStrictMsg :: Id -> Message
 mkStrictMsg binder
   = vcat [hsep [ptext (sLit "Recursive or top-level binder has strict demand info:"),
                     ppr binder],
-             hsep [ptext (sLit "Binder's demand info:"), ppr (idNewDemandInfo binder)]
+             hsep [ptext (sLit "Binder's demand info:"), ppr (idDemandInfo binder)]
             ]
 
 mkArityMsg :: Id -> Message
@@ -1097,7 +1097,7 @@ mkArityMsg binder
              hsep [ptext (sLit "Binder's strictness signature:"), ppr dmd_ty]
 
          ]
-           where (StrictSig dmd_ty) = idNewStrictness binder
+           where (StrictSig dmd_ty) = idStrictness binder
 
 mkUnboxedTupleMsg :: Id -> Message
 mkUnboxedTupleMsg binder
index 36b6f5c..738bf82 100644 (file)
@@ -20,7 +20,7 @@ import CoreSyn
 import Type
 import Coercion
 import TyCon
-import NewDemand
+import Demand
 import Var
 import VarSet
 import VarEnv
@@ -244,7 +244,7 @@ cpeBind :: TopLevelFlag
        -> UniqSM (CorePrepEnv, Floats)
 cpeBind top_lvl env (NonRec bndr rhs)
   = do { (_, bndr1) <- cloneBndr env bndr
-       ; let is_strict   = isStrictDmd (idNewDemandInfo bndr)
+       ; let is_strict   = isStrictDmd (idDemandInfo bndr)
              is_unlifted = isUnLiftedType (idType bndr)
        ; (floats, bndr2, rhs2) <- cpePair top_lvl NonRecursive 
                                                  (is_strict || is_unlifted) 
@@ -497,7 +497,7 @@ cpeApp env expr
            ; let v2 = lookupCorePrepEnv env v1
            ; return (Var v2, (Var v2, depth), idType v2, emptyFloats, stricts) }
        where
-         stricts = case idNewStrictness v of
+         stricts = case idStrictness v of
                        StrictSig (DmdType _ demands _)
                            | listLengthCmp demands depth /= GT -> demands
                                    -- length demands <= depth
index f634197..b77186e 100644 (file)
@@ -155,8 +155,8 @@ tidyLetBndr env (id,rhs)
     idinfo   = idInfo id
     new_info = idInfo new_id
                `setArityInfo`          exprArity rhs
-               `setAllStrictnessInfo`  newStrictnessInfo idinfo
-               `setNewDemandInfo`      newDemandInfo idinfo
+               `setStrictnessInfo`     strictnessInfo idinfo
+               `setDemandInfo` demandInfo idinfo
                `setInlinePragInfo`     inlinePragInfo idinfo
 
     -- Override the env we get back from tidyId with the new IdInfo
index df2978e..950e37b 100644 (file)
@@ -17,12 +17,7 @@ import CostCentre
 import Var
 import Id
 import IdInfo
-import NewDemand
-#ifdef OLD_STRICTNESS
-import Id
-import IdInfo
-#endif
-
+import Demand
 import DataCon
 import TyCon
 import Type
@@ -308,7 +303,7 @@ pprIdBndrInfo info
   where
     prag_info = inlinePragInfo info
     occ_info  = occInfo info
-    dmd_info  = newDemandInfo info
+    dmd_info  = demandInfo info
     lbv_info  = lbvarInfo info
 
     has_prag = not (isDefaultInlinePragma prag_info)
@@ -336,7 +331,7 @@ ppIdInfo id info
     [ (True, pp_scope <> ppr (idDetails id))
     , (has_arity,      ptext (sLit "Arity=") <> int arity)
     , (has_caf_info,   ptext (sLit "Caf=") <> ppr caf_info)
-    , (has_strictness, ptext (sLit "Str=") <> pprNewStrictness str_info)
+    , (has_strictness, ptext (sLit "Str=") <> pprStrictness str_info)
     , (has_unf,        ptext (sLit "Unf=") <> ppr unf_info)
     , (not (null rules), ptext (sLit "RULES:") <+> vcat (map pprRule rules))
     ]  -- Inline pragma, occ, demand, lbvar info
@@ -353,7 +348,7 @@ ppIdInfo id info
     caf_info = cafInfo info
     has_caf_info = not (mayHaveCafRefs caf_info)
 
-    str_info = newStrictnessInfo info
+    str_info = strictnessInfo info
     has_strictness = isJust str_info
 
     unf_info = unfoldingInfo info
diff --git a/compiler/cprAnalysis/CprAnalyse.lhs b/compiler/cprAnalysis/CprAnalyse.lhs
deleted file mode 100644 (file)
index 14c8017..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-% (c) The University of Glasgow 2006
-
-\section[CprAnalyse]{Identify functions that always return a
-constructed product result}
-
-\begin{code}
-#ifndef OLD_STRICTNESS
-module CprAnalyse ( ) where
-
-#else
-
-module CprAnalyse ( cprAnalyse ) where
-
-#include "HsVersions.h"
-
-import DynFlags
-import CoreMonad
-import CoreSyn
-import CoreUtils
-import Id
-import IdInfo
-import Demand
-import VarEnv
-import Util
-import Outputable
-
-import Maybe
-\end{code}
-
-This module performs an analysis of a set of Core Bindings for the
-Constructed Product Result (CPR) transformation.
-
-It detects functions that always explicitly (manifestly?) construct a
-result value with a product type.  A product type is a type which has
-only one constructor. For example, tuples and boxed primitive values
-have product type.
-
-We must also ensure that the function's body starts with sufficient
-manifest lambdas otherwise loss of sharing can occur.  See the comment
-in @StrictAnal.lhs@.
-
-The transformation of bindings to worker/wrapper pairs is done by the
-worker-wrapper pass.  The worker-wrapper pass splits bindings on the
-basis of both strictness and CPR info.  If an id has both then it can
-combine the transformations so that only one pair is produced.
-
-The analysis here detects nested CPR information.  For example, if a
-function returns a constructed pair, the first element of which is a
-constructed int, then the analysis will detect nested CPR information
-for the int as well.  Unfortunately, the current transformations can't
-take advantage of the nested CPR information.  They have (broken now,
-I think) code which will flatten out nested CPR components and rebuild
-them in the wrapper, but enabling this would lose laziness.  It is
-possible to make use of the nested info: if we knew that a caller was
-strict in that position then we could create a specialized version of
-the function which flattened/reconstructed that position.
-
-It is not known whether this optimisation would be worthwhile.
-
-So we generate and carry round nested CPR information, but before
-using this info to guide the creation of workers and wrappers we map
-all components of a CPRInfo to NoCprInfo.
-
-
-Data types
-~~~~~~~~~~
-
-Within this module Id's CPR information is represented by
-``AbsVal''. When adding this information to the Id's pragma info field
-we convert the ``Absval'' to a ``CprInfo'' value.
-
-Abstract domains consist of a `no information' value (Top), a function
-value (Fun) which when applied to an argument returns a new AbsVal
-(note the argument is not used in any way), , for product types, a
-corresponding length tuple (Tuple) of abstract values.  And finally,
-Bot.  Bot is not a proper abstract value but a generic bottom is
-useful for calculating fixpoints and representing divergent
-computations.  Note that we equate Bot and Fun^n Bot (n > 0), and
-likewise for Top.  This saves a lot of delving in types to keep
-everything exactly correct.
-
-Since functions abstract to constant functions we could just
-represent them by the abstract value of their result.  However,  it
-turns out (I know - I tried!) that this requires a lot of type
-manipulation and the code is more straightforward if we represent
-functions by an abstract constant function.
-
-\begin{code}
-data AbsVal = Top                -- Not a constructed product
-
-            | Fun AbsVal         -- A function that takes an argument
-                                 -- and gives AbsVal as result.
-
-            | Tuple              -- A constructed product of values
-
-            | Bot                -- Bot'tom included for convenience
-                                 -- we could use appropriate Tuple Vals
-     deriving (Eq,Show)
-
--- For pretty debugging
-instance Outputable AbsVal where
-  ppr Top       = ptext (sLit "Top")
-  ppr (Fun r)   = ptext (sLit "Fun->") <> (parens.ppr) r
-  ppr Tuple     = ptext (sLit "Tuple ")
-  ppr Bot       = ptext (sLit "Bot")
-
-
--- lub takes the lowest upper bound of two abstract values, standard.
-lub :: AbsVal -> AbsVal -> AbsVal
-lub Bot a = a
-lub a Bot = a
-lub Top a = Top
-lub a Top = Top
-lub Tuple Tuple         = Tuple
-lub (Fun l) (Fun r)     = Fun (lub l r)
-lub l r = panic "CPR Analysis tried to take the lub of a function and a tuple"
-
-
-\end{code}
-
-The environment maps Ids to their abstract CPR value.
-
-\begin{code}
-
-type CPREnv = VarEnv AbsVal
-
-initCPREnv = emptyVarEnv
-
-\end{code}
-
-Programs
-~~~~~~~~
-
-Take a list of core bindings and return a new list with CPR function
-ids decorated with their CprInfo pragmas.
-
-\begin{code}
-
-cprAnalyse :: DynFlags -> [CoreBind] -> IO [CoreBind]
-cprAnalyse dflags binds
-  = do {
-        showPass dflags "Constructed Product analysis" ;
-        let { binds_plus_cpr = do_prog binds } ;
-        endPass dflags "Constructed Product analysis"
-                Opt_D_dump_cpranal binds_plus_cpr []
-        return binds_plus_cpr
-    }
-  where
-    do_prog :: [CoreBind] -> [CoreBind]
-    do_prog binds = snd $ mapAccumL cprAnalBind initCPREnv binds
-\end{code}
-
-The cprAnal functions take binds/expressions and an environment which
-gives CPR info for visible ids and returns a new bind/expression
-with ids decorated with their CPR info.
-
-\begin{code}
--- Return environment extended with info from this binding
-cprAnalBind :: CPREnv -> CoreBind -> (CPREnv, CoreBind)
-cprAnalBind rho (NonRec b e)
-  | isImplicitId b      -- Don't touch the CPR info on constructors, selectors etc
-  = (rho, NonRec b e)
-  | otherwise
-  = (extendVarEnv rho b absval, NonRec b' e')
-  where
-    (e', absval) = cprAnalExpr rho e
-    b' = addIdCprInfo b e' absval
-
-cprAnalBind rho (Rec prs)
-  = (final_rho, Rec (map do_pr prs))
-  where
-    do_pr (b,e) = (b', e')
-                where
-                  b'           = addIdCprInfo b e' absval
-                  (e', absval) = cprAnalExpr final_rho e
-
-        -- When analyzing mutually recursive bindings the iterations to find
-        -- a fixpoint is bounded by the number of bindings in the group.
-        -- for simplicity we just iterate that number of times.
-    final_rho = nTimes (length prs) do_one_pass init_rho
-    init_rho  = rho `extendVarEnvList` [(b,Bot) | (b,e) <- prs]
-
-    do_one_pass :: CPREnv -> CPREnv
-    do_one_pass rho = foldl (\ rho (b,e) -> extendVarEnv rho b (snd (cprAnalExpr rho e)))
-                            rho prs
-
-
-cprAnalExpr :: CPREnv -> CoreExpr -> (CoreExpr, AbsVal)
-
--- If Id will always diverge when given sufficient arguments then
--- we can just set its abs val to Bot.  Any other CPR info
--- from other paths will then dominate,  which is what we want.
--- Check in rho,  if not there it must be imported, so check
--- the var's idinfo.
-cprAnalExpr rho e@(Var v)
-    | isBottomingId v = (e, Bot)
-    | otherwise       = (e, case lookupVarEnv rho v of
-                             Just a_val -> a_val
-                             Nothing    -> getCprAbsVal v)
-
--- Literals are unboxed
-cprAnalExpr rho (Lit l) = (Lit l, Top)
-
--- For apps we don't care about the argument's abs val.  This
--- app will return a constructed product if the function does. We strip
--- a Fun from the functions abs val, unless the argument is a type argument
--- or it is already Top or Bot.
-cprAnalExpr rho (App fun arg@(Type _))
-    = (App fun_cpr arg, fun_res)
-    where
-      (fun_cpr, fun_res)  = cprAnalExpr rho fun
-
-cprAnalExpr rho (App fun arg)
-    = (App fun_cpr arg_cpr, res_res)
-    where
-      (fun_cpr, fun_res)  = cprAnalExpr rho fun
-      (arg_cpr, _)        = cprAnalExpr rho arg
-      res_res             = case fun_res of
-                                Fun res_res -> res_res
-                                Top         -> Top
-                                Bot         -> Bot
-                                Tuple       -> WARN( True, ppr (App fun arg) ) Top
-                                                -- This really should not happen!
-
-
--- Map arguments to Top (we aren't constructing them)
--- Return the abstract value of the body, since functions
--- are represented by the CPR value of their result, and
--- add a Fun for this lambda..
-cprAnalExpr rho (Lam b body) | isTyVar b = (Lam b body_cpr, body_aval)
-                             | otherwise = (Lam b body_cpr, Fun body_aval)
-      where
-      (body_cpr, body_aval) = cprAnalExpr (extendVarEnv rho b Top) body
-
-cprAnalExpr rho (Let bind body)
-    = (Let bind' body', body_aval)
-    where
-      (rho', bind') = cprAnalBind rho bind
-      (body', body_aval) = cprAnalExpr rho' body
-
-cprAnalExpr rho (Case scrut bndr alts)
-    = (Case scrut_cpr bndr alts_cpr, alts_aval)
-      where
-      (scrut_cpr, scrut_aval) = cprAnalExpr rho scrut
-      (alts_cpr, alts_aval) = cprAnalCaseAlts (extendVarEnv rho bndr scrut_aval) alts
-
-cprAnalExpr rho (Note n exp)
-    = (Note n exp_cpr, expr_aval)
-      where
-      (exp_cpr, expr_aval) = cprAnalExpr rho exp
-
-cprAnalExpr rho (Type t)
-    = (Type t, Top)
-
-cprAnalCaseAlts :: CPREnv -> [CoreAlt] -> ([CoreAlt], AbsVal)
-cprAnalCaseAlts rho alts
-    = foldr anal_alt ([], Bot) alts
-      where
-      anal_alt :: CoreAlt -> ([CoreAlt], AbsVal) -> ([CoreAlt], AbsVal)
-      anal_alt (con, binds, exp)  (done, aval)
-          = ((con,binds,exp_cpr) : done, exp_aval `lub` aval)
-            where (exp_cpr, exp_aval) = cprAnalExpr rho' exp
-                  rho' = rho `extendVarEnvList` (zip binds (repeat Top))
-
-
-addIdCprInfo :: Id -> CoreExpr -> AbsVal -> Id
-addIdCprInfo bndr rhs absval
-  | useful_info && ok_to_add = setIdCprInfo bndr cpr_info
-  | otherwise                = bndr
-  where
-    cpr_info    = absToCprInfo absval
-    useful_info = case cpr_info of { ReturnsCPR -> True; NoCPRInfo -> False }
-
-    ok_to_add = case absval of
-                  Fun _ -> idArity bndr >= n_fun_tys absval
-                      -- Enough visible lambdas
-
-                  Tuple  -> exprIsHNF rhs || isStrict (idDemandInfo bndr)
-                        -- If the rhs is a value, and returns a constructed product,
-                        -- it will be inlined at usage sites, so we give it a Tuple absval
-                        -- If it isn't a value, we won't inline it (code/work dup worries), so
-                        -- we discard its absval.
-                        --
-                        -- Also, if the strictness analyser has figured out that it's strict,
-                        -- the let-to-case transformation will happen, so again it's good.
-                        -- (CPR analysis runs before the simplifier has had a chance to do
-                        --  the let-to-case transform.)
-                        -- This made a big difference to PrelBase.modInt, which had something like
-                        --      modInt = \ x -> let r = ... -> I# v in
-                        --                      ...body strict in r...
-                        -- r's RHS isn't a value yet; but modInt returns r in various branches, so
-                        -- if r doesn't have the CPR property then neither does modInt
-
-                  _ -> False
-
-    n_fun_tys :: AbsVal -> Int
-    n_fun_tys (Fun av) = 1 + n_fun_tys av
-    n_fun_tys other    = 0
-
-
-absToCprInfo :: AbsVal -> CprInfo
-absToCprInfo Tuple   = ReturnsCPR
-absToCprInfo (Fun r) = absToCprInfo r
-absToCprInfo _       = NoCPRInfo
-
-
--- Cpr Info doesn't store the number of arguments a function has,  so the caller
--- must take care to add the appropriate number of Funs.
-getCprAbsVal v = case idCprInfo v of
-                        NoCPRInfo -> Top
-                        ReturnsCPR -> nTimes arity Fun Tuple
-               where
-                 arity = idArity v
-        -- Imported (non-nullary) constructors will have the CPR property
-        -- in their IdInfo, so no need to look at their unfolding
-#endif /* OLD_STRICTNESS */
-\end{code}
index c51405c..582534a 100644 (file)
@@ -162,7 +162,6 @@ Library
         Name
         NameEnv
         NameSet
-        NewDemand
         OccName
         RdrName
         SrcLoc
@@ -266,7 +265,6 @@ Library
         MkExternalCore
         PprCore
         PprExternalCore
-        CprAnalyse
         Check
         Coverage
         Desugar
@@ -374,9 +372,6 @@ Library
         StgLint
         StgSyn
         DmdAnal
-        SaAbsInt
-        SaLib
-        StrictAnal
         WorkWrap
         WwLib
         FamInst
index ce023d7..beb39c0 100644 (file)
@@ -17,7 +17,7 @@ import TcRnMonad
 import IfaceEnv
 import HscTypes
 import BasicTypes
-import NewDemand
+import Demand
 import Annotations
 import IfaceSyn
 import Module
@@ -335,7 +335,7 @@ data BinDictionary = BinDictionary {
 {-! for StrictnessMark derive: Binary !-}
 {-! for Activation derive: Binary !-}
 
--- NewDemand
+-- Demand
 {-! for Demand derive: Binary !-}
 {-! for Demands derive: Binary !-}
 {-! for DmdResult derive: Binary !-}
index 4311e65..be68afe 100644 (file)
@@ -28,7 +28,7 @@ module IfaceSyn (
 
 import IfaceType
 
-import NewDemand
+import Demand
 import Annotations
 import Class
 import NameSet 
index 4da21d8..f271aa5 100644 (file)
@@ -54,7 +54,7 @@ import IfaceSyn
 import LoadIface
 import Id
 import IdInfo
-import NewDemand
+import Demand
 import Annotations
 import CoreSyn
 import CoreFVs
@@ -1466,7 +1466,7 @@ toIfaceIdInfo id_info
 
     ------------  Strictness  --------------
        -- No point in explicitly exporting TopSig
-    strict_hsinfo = case newStrictnessInfo id_info of
+    strict_hsinfo = case strictnessInfo id_info of
                        Just sig | not (isTopSig sig) -> Just (HsStrictness sig)
                        _other                        -> Nothing
 
index e1588a1..cecfc0b 100644 (file)
@@ -990,7 +990,7 @@ tcIdInfo ignore_prags name ty info
     tcPrag :: IdInfo -> IfaceInfoItem -> IfL IdInfo
     tcPrag info HsNoCafRefs        = return (info `setCafInfo`   NoCafRefs)
     tcPrag info (HsArity arity)    = return (info `setArityInfo` arity)
-    tcPrag info (HsStrictness str) = return (info `setAllStrictnessInfo` Just str)
+    tcPrag info (HsStrictness str) = return (info `setStrictnessInfo` Just str)
     tcPrag info (HsInline prag)    = return (info `setInlinePragInfo` prag)
 
        -- The next two are lazy, so they don't transitively suck stuff in
@@ -1034,7 +1034,7 @@ tcUnfolding name ty info (IfWrapper arity wkr)
 
        -- We are relying here on strictness info always appearing 
        -- before worker info,  fingers crossed ....
-    strict_sig = case newStrictnessInfo info of
+    strict_sig = case strictnessInfo info of
                   Just sig -> sig
                   Nothing  -> pprPanic "Worker info but no strictness for" (ppr wkr)
 
@@ -1219,7 +1219,7 @@ tcIfaceLetBndr (IfLetBndr fs ty info)
     tc_info [] = vanillaIdInfo
     tc_info (HsInline p     : i) = tc_info i `setInlinePragInfo` p 
     tc_info (HsArity a      : i) = tc_info i `setArityInfo` a 
-    tc_info (HsStrictness s : i) = tc_info i `setAllStrictnessInfo` Just s 
+    tc_info (HsStrictness s : i) = tc_info i `setStrictnessInfo` Just s 
     tc_info (other          : i) = pprTrace "tcIfaceLetBndr: discarding unexpected IdInfo" 
                                            (ppr other) (tc_info i)
 
index 10ab3d0..9e61b28 100644 (file)
@@ -1180,10 +1180,6 @@ getCoreToDo dflags
                 -- Don't stop now!
         simpl_phase 0 ["main"] (max max_iter 3),
 
-
-#ifdef OLD_STRICTNESS
-        CoreDoOldStrictness,
-#endif
         runWhen strictness (CoreDoPasses [
                 CoreDoStrictness,
                 CoreDoWorkerWrapper,
index ffe0eca..8f3a520 100644 (file)
@@ -26,7 +26,7 @@ import Var
 import Id
 import IdInfo
 import InstEnv
-import NewDemand
+import Demand
 import BasicTypes
 import Name hiding (varName)
 import NameSet
@@ -686,7 +686,7 @@ addExternal expose_all id = (new_needed_ids, show_unfold)
     idinfo        = idInfo id
     dont_inline           = isNeverActive (inlinePragmaActivation (inlinePragInfo idinfo))
     loop_breaker   = isNonRuleLoopBreaker (occInfo idinfo)
-    bottoming_fn   = isBottomingSig (newStrictnessInfo idinfo `orElse` topSig)
+    bottoming_fn   = isBottomingSig (strictnessInfo idinfo `orElse` topSig)
     spec_ids      = specInfoFreeVars (specInfo idinfo)
 
        -- Stuff to do with the Id's unfolding
@@ -983,7 +983,7 @@ tidyTopPair show_unfold rhs_tidy_env caf_info name' (bndr, rhs)
                         Nothing         -> True
                         Just (arity, _) -> appIsBottom str arity
         where
-          str = newStrictnessInfo idinfo `orElse` topSig
+          str = strictnessInfo idinfo `orElse` topSig
 
     bndr1   = mkGlobalId details name' ty' idinfo'
     details = idDetails bndr   -- Preserve the IdDetails
@@ -1043,14 +1043,14 @@ tidyTopIdInfo is_external idinfo unfold_info arity caf_info occ_info
         `setOccInfo`           robust_occ_info
        `setCafInfo`           caf_info
        `setArityInfo`         arity
-       `setAllStrictnessInfo` newStrictnessInfo idinfo
+       `setStrictnessInfo` strictnessInfo idinfo
 
   | otherwise          -- Externally-visible Ids get the whole lot
   = vanillaIdInfo
         `setOccInfo`           robust_occ_info
        `setCafInfo`           caf_info
        `setArityInfo`         arity
-       `setAllStrictnessInfo` newStrictnessInfo idinfo
+       `setStrictnessInfo` strictnessInfo idinfo
        `setInlinePragInfo`    inlinePragInfo idinfo
        `setUnfoldingInfo`     unfold_info
                -- NB: we throw away the Rules
index a9a8fa2..4ac1577 100644 (file)
@@ -31,7 +31,7 @@ module PrimOp (
 import TysPrim
 import TysWiredIn
 
-import NewDemand
+import Demand
 import Var             ( TyVar )
 import OccName         ( OccName, pprOccName, mkVarOccFS )
 import TyCon           ( TyCon, isPrimTyCon, tyConPrimRep, PrimRep(..) )
index c9b0601..c7ce066 100644 (file)
@@ -64,7 +64,7 @@ import CoreSubst      ( Subst, emptySubst, extendInScope, extendInScopeList,
 import Id              ( idType, mkSysLocal, isOneShotLambda,
                          zapDemandIdInfo, transferPolyIdInfo,
                          idSpecialisation, idUnfolding, setIdInfo, 
-                         setIdNewStrictness, setIdArity
+                         setIdStrictness, setIdArity
                        )
 import IdInfo
 import Var
@@ -398,7 +398,7 @@ lvlMFE strict_ctxt ctxt_lvl env ann_expr@(fvs, _)
                -- Note [Bottoming floats]
        let var_w_str = case exprBotStrictness_maybe expr of
                          Just (arity,str) -> var `setIdArity` arity
-                                                 `setIdNewStrictness` str
+                                                 `setIdStrictness` str
                          Nothing  -> var
        return (Let (NonRec (TB var_w_str dest_lvl) expr') 
                    (mkVarApps (Var var_w_str) abs_vars))
index df928f6..beb1ed0 100644 (file)
@@ -55,10 +55,6 @@ import Specialise    ( specProgram)
 import SpecConstr      ( specConstrProgram)
 import DmdAnal         ( dmdAnalPgm )
 import WorkWrap                ( wwTopBinds )
-#ifdef OLD_STRICTNESS
-import StrictAnal      ( saBinds )
-import CprAnalyse       ( cprAnalyse )
-#endif
 import Vectorise        ( vectorise )
 import FastString
 import Util
@@ -190,24 +186,8 @@ doCorePass CoreDoGlomBinds              = dontDescribePass $ doPassDM  glomBinds
 doCorePass CoreDoPrintCore              = dontDescribePass $ observe   printCore
 doCorePass (CoreDoRuleCheck phase pat)  = dontDescribePass $ ruleCheck phase pat
 
-#ifdef OLD_STRICTNESS
-doCorePass CoreDoOldStrictness          = {-# SCC "OldStrictness" #-} doOldStrictness
-#endif
-
 doCorePass CoreDoNothing                = return
 doCorePass (CoreDoPasses passes)        = doCorePasses passes
-
-#ifdef OLD_STRICTNESS
-doOldStrictness :: ModGuts -> CoreM ModGuts
-doOldStrictness guts
-  = do dfs <- getDynFlags
-       guts'  <- describePass "Strictness analysis" Opt_D_dump_stranal $ 
-                 doPassM (saBinds dfs) guts
-       guts'' <- describePass "Constructed Product analysis" Opt_D_dump_cpranal $ 
-                 doPass cprAnalyse guts'
-       return guts''
-#endif
-
 \end{code}
 
 %************************************************************************
@@ -844,7 +824,7 @@ transferIdInfo exported_id local_id
   = modifyIdInfo transfer exported_id
   where
     local_info = idInfo local_id
-    transfer exp_info = exp_info `setNewStrictnessInfo` newStrictnessInfo local_info
+    transfer exp_info = exp_info `setStrictnessInfo` strictnessInfo local_info
                                 `setUnfoldingInfo`     unfoldingInfo local_info
                                 `setInlinePragInfo`    inlinePragInfo local_info
                                 `setSpecInfo`          addSpecInfo (specInfo exp_info) new_info
index 972c0e5..87db9a8 100644 (file)
@@ -40,7 +40,7 @@ import CoreUnfold
 import Name
 import Id
 import Var     ( isCoVar )
-import NewDemand
+import Demand
 import SimplMonad
 import Type    hiding( substTy )
 import Coercion ( coercionKind )
@@ -342,7 +342,7 @@ mkArgInfo fun rules n_val_args call_cont
     vanilla_stricts  = repeat False
 
     arg_stricts
-      = case splitStrictSig (idNewStrictness fun) of
+      = case splitStrictSig (idStrictness fun) of
          (demands, result_info)
                | not (demands `lengthExceeds` n_val_args)
                ->      -- Enough args, use the strictness given.
index eb2884c..875061d 100644 (file)
@@ -23,7 +23,7 @@ import Coercion
 import FamInstEnv       ( topNormaliseType )
 import DataCon          ( DataCon, dataConWorkId, dataConRepStrictness )
 import CoreSyn
-import NewDemand        ( isStrictDmd, splitStrictSig )
+import Demand           ( isStrictDmd, splitStrictSig )
 import PprCore          ( pprParendExpr, pprCoreExpr )
 import CoreUnfold       ( mkUnfolding, mkCoreUnfolding, mkInlineRule, 
                           exprIsConApp_maybe, callSiteInline, CallCtxt(..) )
@@ -442,8 +442,8 @@ prepareRhs env id (Cast rhs co)    -- Note [Float coercions]
   = do  { (env', rhs') <- makeTrivialWithInfo env sanitised_info rhs
         ; return (env', Cast rhs' co) }
   where
-    sanitised_info = vanillaIdInfo `setNewStrictnessInfo` newStrictnessInfo info
-                                   `setNewDemandInfo`     newDemandInfo info
+    sanitised_info = vanillaIdInfo `setStrictnessInfo` strictnessInfo info
+                                   `setDemandInfo`     demandInfo info
     info = idInfo id
 
 prepareRhs env0 _ rhs0
@@ -644,7 +644,7 @@ addNonRecWithUnf env new_bndr new_rhs new_unfolding
               | otherwise                      = info2
 
         final_id = new_bndr `setIdInfo` info3
-       dmd_arity = length $ fst $ splitStrictSig $ idNewStrictness new_bndr
+       dmd_arity = length $ fst $ splitStrictSig $ idStrictness new_bndr
     in
     ASSERT( isId new_bndr )
     WARN( new_arity < old_arity || new_arity < dmd_arity, 
@@ -1468,7 +1468,7 @@ rebuildCase env scrut case_bndr [(_, bndrs, rhs)] cont
   where
         -- The case binder is going to be evaluated later,
         -- and the scrutinee is a simple variable
-    var_demanded_later (Var v) = isStrictDmd (idNewDemandInfo case_bndr)
+    var_demanded_later (Var v) = isStrictDmd (idDemandInfo case_bndr)
                                  && not (isTickBoxOp v)
                                     -- ugly hack; covering this case is what
                                     -- exprOkForSpeculation was intended for.
index c545fad..5606830 100644 (file)
@@ -41,7 +41,7 @@ import StaticFlags    ( opt_PprStyle_Debug )
 import StaticFlags     ( opt_SpecInlineJoinPoints )
 import BasicTypes      ( Activation(..) )
 import Maybes          ( orElse, catMaybes, isJust, isNothing )
-import NewDemand
+import Demand
 import DmdAnal         ( both )
 import Serialized       ( deserializeWithData )
 import Util
@@ -1162,7 +1162,7 @@ spec_one env fn arg_bndrs body (call_pat@(qvars, pats), rule_number)
              spec_rhs  = mkLams spec_lam_args spec_body
              spec_str  = calcSpecStrictness fn spec_lam_args pats
              spec_id   = mkUserLocal spec_occ spec_uniq (mkPiTypes spec_lam_args body_ty) fn_loc
-                           `setIdNewStrictness` spec_str       -- See Note [Transfer strictness]
+                           `setIdStrictness` spec_str          -- See Note [Transfer strictness]
                            `setIdArity` count isId spec_lam_args
              body_ty   = exprType spec_body
              rule_rhs  = mkVarApps (Var spec_id) spec_call_args
@@ -1177,7 +1177,7 @@ calcSpecStrictness fn qvars pats
   = StrictSig (mkTopDmdType spec_dmds TopRes)
   where
     spec_dmds = [ lookupVarEnv dmd_env qv `orElse` lazyDmd | qv <- qvars, isId qv ]
-    StrictSig (DmdType _ dmds _) = idNewStrictness fn
+    StrictSig (DmdType _ dmds _) = idStrictness fn
 
     dmd_env = go emptyVarEnv dmds pats
 
index 789e77a..2414aea 100644 (file)
@@ -22,7 +22,7 @@ module DmdAnal ( dmdAnalPgm, dmdAnalTopRhs,
 
 import DynFlags                ( DynFlags, DynFlag(..) )
 import StaticFlags     ( opt_MaxWorkerArgs )
-import NewDemand       -- All of it
+import Demand  -- All of it
 import CoreSyn
 import PprCore 
 import CoreUtils       ( exprIsHNF, exprIsTrivial )
@@ -31,17 +31,11 @@ import DataCon              ( dataConTyCon )
 import TyCon           ( isProductTyCon, isRecursiveTyCon )
 import Id              ( Id, idType, idInlineActivation,
                          isDataConWorkId, isGlobalId, idArity,
-#ifdef OLD_STRICTNESS
-                         idDemandInfo,  idStrictness, idCprInfo, idName,
-#endif
-                         idNewStrictness, idNewStrictness_maybe,
-                         setIdNewStrictness, idNewDemandInfo,
-                         idNewDemandInfo_maybe,
-                         setIdNewDemandInfo
+                         idStrictness, idStrictness_maybe,
+                         setIdStrictness, idDemandInfo,
+                         idDemandInfo_maybe,
+                         setIdDemandInfo
                        )
-#ifdef OLD_STRICTNESS
-import IdInfo          ( newStrictnessFromOld, newDemand )
-#endif
 import Var             ( Var )
 import VarEnv
 import TysWiredIn      ( unboxedPairDataCon )
@@ -79,12 +73,6 @@ dmdAnalPgm :: DynFlags -> [CoreBind] -> IO [CoreBind]
 dmdAnalPgm dflags binds
   = do {
        let { binds_plus_dmds = do_prog binds } ;
-#ifdef OLD_STRICTNESS
-       -- Only if OLD_STRICTNESS is on, because only then is the old
-       -- strictness analyser run
-       let { dmd_changes = get_changes binds_plus_dmds } ;
-       printDump (text "Changes in demands" $$ dmd_changes) ;
-#endif
        return binds_plus_dmds
     }
   where
@@ -257,7 +245,7 @@ dmdAnal sigs dmd (Case scrut case_bndr ty [alt@(DataAlt dc,bndrs,rhs)])
        --      x = (a, absent-error)
        -- and that'll crash.
        -- So at one stage I had:
-       --      dead_case_bndr           = isAbsentDmd (idNewDemandInfo case_bndr')
+       --      dead_case_bndr           = isAbsentDmd (idDemandInfo case_bndr')
        --      keepity | dead_case_bndr = Drop
        --              | otherwise      = Keep         
        --
@@ -268,9 +256,9 @@ dmdAnal sigs dmd (Case scrut case_bndr ty [alt@(DataAlt dc,bndrs,rhs)])
        -- The insight is, of course, that a demand on y is a demand on the
        -- scrutinee, so we need to `both` it with the scrut demand
 
-       alt_dmd            = Eval (Prod [idNewDemandInfo b | b <- bndrs', isId b])
+       alt_dmd            = Eval (Prod [idDemandInfo b | b <- bndrs', isId b])
         scrut_dmd         = alt_dmd `both`
-                            idNewDemandInfo case_bndr'
+                            idDemandInfo case_bndr'
 
        (scrut_ty, scrut') = dmdAnal sigs scrut_dmd scrut
     in
@@ -425,7 +413,7 @@ dmdFix top_lvl sigs orig_pairs
        -- of the fixpoint algorithm.  (Cunning plan.)
        -- Note that the cunning plan extends to the DmdEnv too,
        -- since it is part of the strictness signature
-initialSig id = idNewStrictness_maybe id `orElse` botSig
+initialSig id = idStrictness_maybe id `orElse` botSig
 
 dmdAnalRhs :: TopLevelFlag -> RecFlag
        -> SigEnv -> (Id, CoreExpr)
@@ -443,7 +431,7 @@ dmdAnalRhs top_lvl rec_flag sigs (id, rhs)
                                -- The RHS can be eta-reduced to just a variable, 
                                -- in which case we should not complain. 
                       mkSigTy top_lvl rec_flag id rhs rhs_dmd_ty
-  id'               = id `setIdNewStrictness` sig_ty
+  id'               = id `setIdStrictness` sig_ty
   sigs'                     = extendSigEnv top_lvl sigs id sig_ty
 \end{code}
 
@@ -464,7 +452,7 @@ mkSigTy top_lvl rec_flag id rhs dmd_ty
   = mk_sig_ty never_inline thunk_cpr_ok rhs dmd_ty
   where
     never_inline = isNeverActive (idInlineActivation id)
-    maybe_id_dmd = idNewDemandInfo_maybe id
+    maybe_id_dmd = idDemandInfo_maybe id
        -- Is Nothing the first time round
 
     thunk_cpr_ok
@@ -734,7 +722,7 @@ annotateBndr :: DmdType -> Var -> (DmdType, Var)
 -- No effect on the argument demands
 annotateBndr dmd_ty@(DmdType fv ds res) var
   | isTyVar var = (dmd_ty, var)
-  | otherwise   = (DmdType fv' ds res, setIdNewDemandInfo var dmd)
+  | otherwise   = (DmdType fv' ds res, setIdDemandInfo var dmd)
   where
     (fv', dmd) = removeFV fv var res
 
@@ -749,7 +737,7 @@ annotateLamIdBndr dmd_ty@(DmdType fv ds res) id
 -- For lambdas we add the demand to the argument demands
 -- Only called for Ids
   = ASSERT( isId id )
-    (DmdType fv' (hacked_dmd:ds) res, setIdNewDemandInfo id hacked_dmd)
+    (DmdType fv' (hacked_dmd:ds) res, setIdDemandInfo id hacked_dmd)
   where
     (fv', dmd) = removeFV fv id res
     hacked_dmd = argDemand dmd
@@ -815,7 +803,7 @@ extendSigsWithLam :: SigEnv -> Id -> SigEnv
 -- CPR results (e.g. from \x -> x!).
 
 extendSigsWithLam sigs id
-  = case idNewDemandInfo_maybe id of
+  = case idDemandInfo_maybe id of
        Nothing               -> extendVarEnv sigs id (cprSig, NotTopLevel)
                -- Optimistic in the Nothing case;
                -- See notes [CPR-AND-STRICTNESS]
@@ -835,7 +823,7 @@ dmdTransform sigs var dmd
 ------         DATA CONSTRUCTOR
   | isDataConWorkId var                -- Data constructor
   = let 
-       StrictSig dmd_ty    = idNewStrictness var       -- It must have a strictness sig
+       StrictSig dmd_ty    = idStrictness var  -- It must have a strictness sig
        DmdType _ _ con_res = dmd_ty
        arity               = idArity var
     in
@@ -866,7 +854,7 @@ dmdTransform sigs var dmd
 
 ------         IMPORTED FUNCTION
   | isGlobalId var,            -- Imported function
-    let StrictSig dmd_ty = idNewStrictness var
+    let StrictSig dmd_ty = idStrictness var
   = if dmdTypeDepth dmd_ty <= call_depth then  -- Saturated, so unleash the demand
        dmd_ty
     else
@@ -1146,88 +1134,3 @@ both d1@(Defer ds1) d2        = d2 `both` d1
  
 boths ds1 ds2 = zipWithDmds both ds1 ds2
 \end{code}
-
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Miscellaneous
-%*                                                                     *
-%************************************************************************
-
-
-\begin{code}
-#ifdef OLD_STRICTNESS
-get_changes binds = vcat (map get_changes_bind binds)
-
-get_changes_bind (Rec pairs) = vcat (map get_changes_pr pairs)
-get_changes_bind (NonRec id rhs) = get_changes_pr (id,rhs)
-
-get_changes_pr (id,rhs) 
-  = get_changes_var id $$ get_changes_expr rhs
-
-get_changes_var var
-  | isId var  = get_changes_str var $$ get_changes_dmd var
-  | otherwise = empty
-
-get_changes_expr (Type t)     = empty
-get_changes_expr (Var v)      = empty
-get_changes_expr (Lit l)      = empty
-get_changes_expr (Note n e)   = get_changes_expr e
-get_changes_expr (App e1 e2)  = get_changes_expr e1 $$ get_changes_expr e2
-get_changes_expr (Lam b e)    = {- get_changes_var b $$ -} get_changes_expr e
-get_changes_expr (Let b e)    = get_changes_bind b $$ get_changes_expr e
-get_changes_expr (Case e b a) = get_changes_expr e $$ {- get_changes_var b $$ -} vcat (map get_changes_alt a)
-
-get_changes_alt (con,bs,rhs) = {- vcat (map get_changes_var bs) $$ -} get_changes_expr rhs
-
-get_changes_str id
-  | new_better && old_better = empty
-  | new_better              = message "BETTER"
-  | old_better              = message "WORSE"
-  | otherwise               = message "INCOMPARABLE" 
-  where
-    message word = text word <+> text "strictness for" <+> ppr id <+> info
-    info = (text "Old" <+> ppr old) $$ (text "New" <+> ppr new)
-    new = squashSig (idNewStrictness id)       -- Don't report spurious diffs that the old
-                                               -- strictness analyser can't track
-    old = newStrictnessFromOld (idName id) (idArity id) (idStrictness id) (idCprInfo id)
-    old_better = old `betterStrictness` new
-    new_better = new `betterStrictness` old
-
-get_changes_dmd id
-  | isUnLiftedType (idType id) = empty -- Not useful
-  | new_better && old_better = empty
-  | new_better              = message "BETTER"
-  | old_better              = message "WORSE"
-  | otherwise               = message "INCOMPARABLE" 
-  where
-    message word = text word <+> text "demand for" <+> ppr id <+> info
-    info = (text "Old" <+> ppr old) $$ (text "New" <+> ppr new)
-    new = squashDmd (argDemand (idNewDemandInfo id))   -- To avoid spurious improvements
-                                                       -- A bit of a hack
-    old = newDemand (idDemandInfo id)
-    new_better = new `betterDemand` old 
-    old_better = old `betterDemand` new
-
-betterStrictness :: StrictSig -> StrictSig -> Bool
-betterStrictness (StrictSig t1) (StrictSig t2) = betterDmdType t1 t2
-
-betterDmdType t1 t2 = (t1 `lubType` t2) == t2
-
-betterDemand :: Demand -> Demand -> Bool
--- If d1 `better` d2, and d2 `better` d2, then d1==d2
-betterDemand d1 d2 = (d1 `lub` d2) == d2
-
-squashSig (StrictSig (DmdType fv ds res))
-  = StrictSig (DmdType emptyDmdEnv (map squashDmd ds) res)
-  where
-       -- squash just gets rid of call demands
-       -- which the old analyser doesn't track
-squashDmd (Call d)   = evalDmd
-squashDmd (Box d)    = Box (squashDmd d)
-squashDmd (Eval ds)  = Eval (mapDmds squashDmd ds)
-squashDmd (Defer ds) = Defer (mapDmds squashDmd ds)
-squashDmd d          = d
-#endif
-\end{code}
diff --git a/compiler/stranal/SaAbsInt.lhs b/compiler/stranal/SaAbsInt.lhs
deleted file mode 100644 (file)
index 1fd3bb1..0000000
+++ /dev/null
@@ -1,932 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
-%
-\section[SaAbsInt]{Abstract interpreter for strictness analysis}
-
-\begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
---     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
--- for details
-
-#ifndef OLD_STRICTNESS
--- If OLD_STRICTNESS is off, omit all exports 
-module SaAbsInt () where
-
-#else
-module SaAbsInt (
-       findStrictness,
-       findDemand, findDemandAlts,
-       absEval,
-       widen,
-       fixpoint,
-       isBot
-    ) where
-
-#include "HsVersions.h"
-
-import StaticFlags     ( opt_AllStrict, opt_NumbersStrict )
-import CoreSyn
-import CoreUnfold      ( maybeUnfoldingTemplate )
-import Id              ( Id, idType, idUnfolding, isDataConWorkId_maybe,
-                         idStrictness,
-                       )
-import DataCon         ( dataConTyCon, splitProductType_maybe, dataConRepArgTys )
-import IdInfo          ( StrictnessInfo(..) )
-import Demand          ( Demand(..), wwPrim, wwStrict, wwUnpack, wwLazy,
-                         mkStrictnessInfo, isLazy
-                       )
-import SaLib
-import TyCon           ( isProductTyCon, isRecursiveTyCon )
-import Type            ( splitTyConApp_maybe, 
-                         isUnLiftedType, Type )
-import TyCon           ( tyConUnique )
-import PrelInfo                ( numericTyKeys )
-import Util            ( isIn, nOfThem, zipWithEqual, equalLength )
-import Outputable      
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[AbsVal-ops]{Operations on @AbsVals@}
-%*                                                                     *
-%************************************************************************
-
-Least upper bound, greatest lower bound.
-
-\begin{code}
-lub, glb :: AbsVal -> AbsVal -> AbsVal
-
-lub AbsBot val2   = val2       
-lub val1   AbsBot = val1       
-
-lub (AbsProd xs) (AbsProd ys) = AbsProd (zipWithEqual "lub" lub xs ys)
-
-lub _            _           = AbsTop  -- Crude, but conservative
-                                       -- The crudity only shows up if there
-                                       -- are functions involved
-
--- Slightly funny glb; for absence analysis only;
--- AbsBot is the safe answer.
---
--- Using anyBot rather than just testing for AbsBot is important.
--- Consider:
---
---   f = \a b -> ...
---
---   g = \x y z -> case x of
---                  []     -> f x
---                  (p:ps) -> f p
---
--- Now, the abstract value of the branches of the case will be an
--- AbsFun, but when testing for z's absence we want to spot that it's
--- an AbsFun which can't possibly return AbsBot.  So when glb'ing we
--- mustn't be too keen to bale out and return AbsBot; the anyBot test
--- spots that (f x) can't possibly return AbsBot.
-
--- We have also tripped over the following interesting case:
---     case x of
---       []     -> \y -> 1
---        (p:ps) -> f
---
--- Now, suppose f is bound to AbsTop.  Does this expression mention z?
--- Obviously not.  But the case will take the glb of AbsTop (for f) and
--- an AbsFun (for \y->1). We should not bale out and give AbsBot, because
--- that would say that it *does* mention z (or anything else for that matter).
--- Nor can we always return AbsTop, because the AbsFun might be something
--- like (\y->z), which obviously does mention z. The point is that we're
--- glbing two functions, and AbsTop is not actually the top of the function
--- lattice.  It is more like (\xyz -> x|y|z); that is, AbsTop returns
--- poison iff any of its arguments do.
-
--- Deal with functions specially, because AbsTop isn't the
--- top of their domain.
-
-glb v1 v2
-  | is_fun v1 || is_fun v2
-  = if not (anyBot v1) && not (anyBot v2)
-    then
-       AbsTop
-    else
-       AbsBot
-  where
-    is_fun (AbsFun _ _)       = True
-    is_fun (AbsApproxFun _ _) = True   -- Not used, but the glb works ok
-    is_fun other              = False
-
--- The non-functional cases are quite straightforward
-
-glb (AbsProd xs) (AbsProd ys) = AbsProd (zipWithEqual "glb" glb xs ys)
-
-glb AbsTop      v2           = v2
-glb v1           AbsTop              = v1
-
-glb _            _            = AbsBot                 -- Be pessimistic
-\end{code}
-
-@isBot@ returns True if its argument is (a representation of) bottom.  The
-``representation'' part is because we need to detect the bottom {\em function}
-too.  To detect the bottom function, bind its args to top, and see if it
-returns bottom.
-
-Used only in strictness analysis:
-\begin{code}
-isBot :: AbsVal -> Bool
-
-isBot AbsBot = True
-isBot other  = False   -- Functions aren't bottom any more
-\end{code}
-
-Used only in absence analysis:
-
-\begin{code}
-anyBot :: AbsVal -> Bool
-
-anyBot AbsBot                 = True   -- poisoned!
-anyBot AbsTop                 = False
-anyBot (AbsProd vals)         = any anyBot vals
-anyBot (AbsFun bndr_ty abs_fn) = anyBot (abs_fn AbsTop)
-anyBot (AbsApproxFun _ val)    = anyBot val
-\end{code}
-
-@widen@ takes an @AbsVal@, $val$, and returns and @AbsVal@ which is
-approximated by $val$.  Furthermore, the result has no @AbsFun@s in
-it, so it can be compared for equality by @sameVal@.
-
-\begin{code}
-widen :: AnalysisKind -> AbsVal -> AbsVal
-
--- Widening is complicated by the fact that funtions are lifted
-widen StrAnal the_fn@(AbsFun bndr_ty _)
-  = case widened_body of
-       AbsApproxFun ds val -> AbsApproxFun (d : ds) val
-                           where
-                              d = findRecDemand str_fn abs_fn bndr_ty
-                              str_fn val = isBot (foldl (absApply StrAnal) the_fn 
-                                                        (val : [AbsTop | d <- ds]))
-
-       other               -> AbsApproxFun [d] widened_body
-                           where
-                              d = findRecDemand str_fn abs_fn bndr_ty
-                              str_fn val = isBot (absApply StrAnal the_fn val)
-  where
-    widened_body = widen StrAnal (absApply StrAnal the_fn AbsTop)
-    abs_fn val   = False       -- Always says poison; so it looks as if
-                               -- nothing is absent; safe
-
-{-     OLD comment... 
-       This stuff is now instead handled neatly by the fact that AbsApproxFun 
-       contains an AbsVal inside it.   SLPJ Jan 97
-
-  | isBot abs_body = AbsBot
-    -- It's worth checking for a function which is unconditionally
-    -- bottom.  Consider
-    --
-    -- f x y = let g y = case x of ...
-    --         in (g ..) + (g ..)
-    --
-    -- Here, when we are considering strictness of f in x, we'll
-    -- evaluate the body of f with x bound to bottom.  The current
-    -- strategy is to bind g to its *widened* value; without the isBot
-    -- (...) test above, we'd bind g to an AbsApproxFun, and deliver
-    -- Top, not Bot as the value of f's rhs.  The test spots the
-    -- unconditional bottom-ness of g when x is bottom.  (Another
-    -- alternative here would be to bind g to its exact abstract
-    -- value, but that entails lots of potential re-computation, at
-    -- every application of g.)
--}
-
-widen StrAnal (AbsProd vals) = AbsProd (map (widen StrAnal) vals)
-widen StrAnal other_val             = other_val
-
-
-widen AbsAnal the_fn@(AbsFun bndr_ty _)
-  | anyBot widened_body = AbsBot
-       -- In the absence-analysis case it's *essential* to check
-       -- that the function has no poison in its body.  If it does,
-       -- anywhere, then the whole function is poisonous.
-
-  | otherwise
-  = case widened_body of
-       AbsApproxFun ds val -> AbsApproxFun (d : ds) val
-                           where
-                              d = findRecDemand str_fn abs_fn bndr_ty
-                              abs_fn val = not (anyBot (foldl (absApply AbsAnal) the_fn 
-                                                               (val : [AbsTop | d <- ds])))
-
-       other               -> AbsApproxFun [d] widened_body
-                           where
-                              d = findRecDemand str_fn abs_fn bndr_ty
-                              abs_fn val = not (anyBot (absApply AbsAnal the_fn val))
-  where
-    widened_body = widen AbsAnal (absApply AbsAnal the_fn AbsTop)
-    str_fn val   = True                -- Always says non-termination;
-                               -- that'll make findRecDemand peer into the
-                               -- structure of the value.
-
-widen AbsAnal (AbsProd vals) = AbsProd (map (widen AbsAnal) vals)
-
-       -- It's desirable to do a good job of widening for product
-       -- values.  Consider
-       --
-       --      let p = (x,y)
-       --      in ...(case p of (x,y) -> x)...
-       --
-       -- Now, is y absent in this expression?  Currently the
-       -- analyser widens p before looking at p's scope, to avoid
-       -- lots of recomputation in the case where p is a function.
-       -- So if widening doesn't have a case for products, we'll
-       -- widen p to AbsBot (since when searching for absence in y we
-       -- bind y to poison ie AbsBot), and now we are lost.
-
-widen AbsAnal other_val = other_val
-
--- WAS:          if anyBot val then AbsBot else AbsTop
--- Nowadays widen is doing a better job on functions for absence analysis.
-\end{code}
-
-@crudeAbsWiden@ is used just for absence analysis, and always
-returns AbsTop or AbsBot, so it widens to a two-point domain
-
-\begin{code}
-crudeAbsWiden :: AbsVal -> AbsVal
-crudeAbsWiden val = if anyBot val then AbsBot else AbsTop
-\end{code}
-
-@sameVal@ compares two abstract values for equality.  It can't deal with
-@AbsFun@, but that should have been removed earlier in the day by @widen@.
-
-\begin{code}
-sameVal :: AbsVal -> AbsVal -> Bool    -- Can't handle AbsFun!
-
-#ifdef DEBUG
-sameVal (AbsFun _ _) _ = panic "sameVal: AbsFun: arg1"
-sameVal _ (AbsFun _ _) = panic "sameVal: AbsFun: arg2"
-#endif
-
-sameVal AbsBot AbsBot = True
-sameVal AbsBot other  = False  -- widen has reduced AbsFun bots to AbsBot
-
-sameVal AbsTop AbsTop = True
-sameVal AbsTop other  = False          -- Right?
-
-sameVal (AbsProd vals1) (AbsProd vals2) = and (zipWithEqual "sameVal" sameVal vals1 vals2)
-sameVal (AbsProd _)    AbsTop          = False
-sameVal (AbsProd _)    AbsBot          = False
-
-sameVal (AbsApproxFun str1 v1) (AbsApproxFun str2 v2) = str1 == str2 && sameVal v1 v2
-sameVal (AbsApproxFun _ _)     AbsTop                = False
-sameVal (AbsApproxFun _ _)     AbsBot                = False
-
-sameVal val1 val2 = panic "sameVal: type mismatch or AbsFun encountered"
-\end{code}
-
-
-@evalStrictness@ compares a @Demand@ with an abstract value, returning
-@True@ iff the abstract value is {\em less defined} than the demand.
-(@True@ is the exciting answer; @False@ is always safe.)
-
-\begin{code}
-evalStrictness :: Demand
-              -> AbsVal
-              -> Bool          -- True iff the value is sure
-                               -- to be less defined than the Demand
-
-evalStrictness (WwLazy _) _   = False
-evalStrictness WwStrict   val = isBot val
-evalStrictness WwEnum    val = isBot val
-
-evalStrictness (WwUnpack _ demand_info) val
-  = case val of
-      AbsTop      -> False
-      AbsBot      -> True
-      AbsProd vals
-          | not (equalLength vals demand_info) -> pprTrace "TELL SIMON: evalStrictness" (ppr demand_info $$ ppr val)
-                                                 False
-          | otherwise -> or (zipWithEqual "evalStrictness" evalStrictness demand_info vals)
-
-      _                       -> pprTrace "evalStrictness?" empty False
-
-evalStrictness WwPrim val
-  = case val of
-      AbsTop -> False
-      AbsBot -> True   -- Can happen: consider f (g x), where g is a 
-                       -- recursive function returning an Int# that diverges
-
-      other  -> pprPanic "evalStrictness: WwPrim:" (ppr other)
-\end{code}
-
-For absence analysis, we're interested in whether "poison" in the
-argument (ie a bottom therein) can propagate to the result of the
-function call; that is, whether the specified demand can {\em
-possibly} hit poison.
-
-\begin{code}
-evalAbsence (WwLazy True) _ = False    -- Can't possibly hit poison
-                                       -- with Absent demand
-
-evalAbsence (WwUnpack _ demand_info) val
-  = case val of
-       AbsTop       -> False           -- No poison in here
-       AbsBot       -> True            -- Pure poison
-       AbsProd vals 
-          | not (equalLength vals demand_info) -> pprTrace "TELL SIMON: evalAbsence" (ppr demand_info $$ ppr val)
-                                                 True
-          | otherwise -> or (zipWithEqual "evalAbsence" evalAbsence demand_info vals)
-       _              -> pprTrace "TELL SIMON: evalAbsence" 
-                               (ppr demand_info $$ ppr val)
-                         True
-
-evalAbsence other val = anyBot val
-  -- The demand is conservative; even "Lazy" *might* evaluate the
-  -- argument arbitrarily so we have to look everywhere for poison
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[absEval]{Evaluate an expression in the abstract domain}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
--- The isBottomingId stuf is now dealt with via the Id's strictness info
--- absId anal var env | isBottomingId var
---   = case anal of
---     StrAnal -> AbsBot       -- See discussion below
---     AbsAnal -> AbsTop       -- Just want to see if there's any poison in
-                               -- error's arg
-
-absId anal var env
-  = case (lookupAbsValEnv env var, 
-         isDataConWorkId_maybe var, 
-         idStrictness var, 
-         maybeUnfoldingTemplate (idUnfolding var)) of
-
-       (Just abs_val, _, _, _) ->
-                       abs_val -- Bound in the environment
-
-       (_, Just data_con, _, _) | isProductTyCon tycon &&
-                                  not (isRecursiveTyCon tycon)
-               ->      -- A product.  We get infinite loops if we don't
-                       -- check for recursive products!
-                       -- The strictness info on the constructor 
-                       -- isn't expressive enough to contain its abstract value
-                  productAbsVal (dataConRepArgTys data_con) []
-               where
-                  tycon = dataConTyCon data_con
-
-       (_, _, NoStrictnessInfo, Just unfolding) ->
-                       -- We have an unfolding for the expr
-                       -- Assume the unfolding has no free variables since it
-                       -- came from inside the Id
-                       absEval anal unfolding env
-               -- Notice here that we only look in the unfolding if we don't
-               -- have strictness info (an unusual situation).
-               -- We could have chosen to look in the unfolding if it exists,
-               -- and only try the strictness info if it doesn't, and that would
-               -- give more accurate results, at the cost of re-abstract-interpreting
-               -- the unfolding every time.
-               -- We found only one place where the look-at-unfolding-first
-               -- method gave better results, which is in the definition of
-               -- showInt in the Prelude.  In its defintion, fromIntegral is
-               -- not inlined (it's big) but ab-interp-ing its unfolding gave
-               -- a better result than looking at its strictness only.
-               --  showInt :: Integral a => a -> [Char] -> [Char]
-               -- !       {-# GHC_PRAGMA _A_ 1 _U_ 122 _S_
-               --         "U(U(U(U(SA)AAAAAAAAL)AA)AAAAASAAASA)" {...} _N_ _N_ #-}
-               -- --- 42,44 ----
-               --   showInt :: Integral a => a -> [Char] -> [Char]
-               -- !       {-# GHC_PRAGMA _A_ 1 _U_ 122 _S_
-               --        "U(U(U(U(SL)LLLLLLLLL)LL)LLLLLSLLLLL)" _N_ _N_ #-}
-
-
-       (_, _, strictness_info, _) ->
-                       -- Includes NoUnfolding
-                       -- Try the strictness info
-                       absValFromStrictness anal strictness_info
-
-productAbsVal []                 rev_abs_args = AbsProd (reverse rev_abs_args)
-productAbsVal (arg_ty : arg_tys) rev_abs_args = AbsFun arg_ty (\ abs_arg -> productAbsVal arg_tys (abs_arg : rev_abs_args))
-\end{code}
-
-\begin{code}
-absEval :: AnalysisKind -> CoreExpr -> AbsValEnv -> AbsVal
-
-absEval anal (Type ty) env = AbsTop
-absEval anal (Var var) env = absId anal var env
-\end{code}
-
-Discussion about error (following/quoting Lennart): Any expression
-'error e' is regarded as bottom (with HBC, with the -ffail-strict
-flag, on with -O).
-
-Regarding it as bottom gives much better strictness properties for
-some functions.         E.g.
-
-       f [x] y = x+y
-       f (x:xs) y = f xs (x+y)
-i.e.
-       f [] _ = error "no match"
-       f [x] y = x+y
-       f (x:xs) y = f xs (x+y)
-
-is strict in y, which you really want.  But, it may lead to
-transformations that turn a call to \tr{error} into non-termination.
-(The odds of this happening aren't good.)
-
-Things are a little different for absence analysis, because we want
-to make sure that any poison (?????)
-
-\begin{code}
-absEval anal (Lit _) env = AbsTop
-       -- Literals terminate (strictness) and are not poison (absence)
-\end{code}
-
-\begin{code}
-absEval anal (Lam bndr body) env
-  | isTyVar bndr = absEval anal body env       -- Type lambda
-  | otherwise    = AbsFun (idType bndr) abs_fn -- Value lambda
-  where
-    abs_fn arg = absEval anal body (addOneToAbsValEnv env bndr arg)
-
-absEval anal (App expr (Type ty)) env
-  = absEval anal expr env                      -- Type appplication
-absEval anal (App f val_arg) env
-  = absApply anal (absEval anal f env)                 -- Value applicationn
-                 (absEval anal val_arg env)
-\end{code}
-
-\begin{code}
-absEval anal expr@(Case scrut case_bndr alts) env
-  = let
-       scrut_val  = absEval anal scrut env
-       alts_env   = addOneToAbsValEnv env case_bndr scrut_val
-    in
-    case (scrut_val, alts) of
-       (AbsBot, _) -> AbsBot
-
-       (AbsProd arg_vals, [(con, bndrs, rhs)])
-               | con /= DEFAULT ->
-               -- The scrutinee is a product value, so it must be of a single-constr
-               -- type; so the constructor in this alternative must be the right one
-               -- so we can go ahead and bind the constructor args to the components
-               -- of the product value.
-           ASSERT(equalLength arg_vals val_bndrs)
-           absEval anal rhs rhs_env
-         where
-           val_bndrs = filter isId bndrs
-           rhs_env   = growAbsValEnvList alts_env (val_bndrs `zip` arg_vals)
-
-       other -> absEvalAlts anal alts alts_env
-\end{code}
-
-For @Lets@ we widen the value we get.  This is nothing to
-do with fixpointing.  The reason is so that we don't get an explosion
-in the amount of computation.  For example, consider:
-\begin{verbatim}
-      let
-       g a = case a of
-               q1 -> ...
-               q2 -> ...
-       f x = case x of
-               p1 -> ...g r...
-               p2 -> ...g s...
-      in
-       f e
-\end{verbatim}
-If we bind @f@ and @g@ to their exact abstract value, then we'll
-``execute'' one call to @f@ and {\em two} calls to @g@.  This can blow
-up exponentially.  Widening cuts it off by making a fixed
-approximation to @f@ and @g@, so that the bodies of @f@ and @g@ are
-not evaluated again at all when they are called.
-
-Of course, this can lose useful joint strictness, which is sad.  An
-alternative approach would be to try with a certain amount of ``fuel''
-and be prepared to bale out.
-
-\begin{code}
-absEval anal (Let (NonRec binder e1) e2) env
-  = let
-       new_env = addOneToAbsValEnv env binder (widen anal (absEval anal e1 env))
-    in
-       -- The binder of a NonRec should *not* be of unboxed type,
-       -- hence no need to strictly evaluate the Rhs.
-    absEval anal e2 new_env
-
-absEval anal (Let (Rec pairs) body) env
-  = let
-       (binders,rhss) = unzip pairs
-       rhs_vals = cheapFixpoint anal binders rhss env  -- Returns widened values
-       new_env  = growAbsValEnvList env (binders `zip` rhs_vals)
-    in
-    absEval anal body new_env
-
-absEval anal (Note (Coerce _ _) expr) env = AbsTop
-       -- Don't look inside coerces, becuase they
-       -- are usually recursive newtypes
-       -- (Could improve, for the error case, but we're about
-       -- to kill this analyser anyway.)
-absEval anal (Note note expr) env = absEval anal expr env
-\end{code}
-
-\begin{code}
-absEvalAlts :: AnalysisKind -> [CoreAlt] -> AbsValEnv -> AbsVal
-absEvalAlts anal alts env
-  = combine anal (map go alts)
-  where
-    combine StrAnal = foldr1 lub       -- Diverge only if all diverge
-    combine AbsAnal = foldr1 glb       -- Find any poison
-
-    go (con, bndrs, rhs)
-      = absEval anal rhs rhs_env
-      where
-       rhs_env = growAbsValEnvList env (filter isId bndrs `zip` repeat AbsTop)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[absApply]{Apply an abstract function to an abstract argument}
-%*                                                                     *
-%************************************************************************
-
-Easy ones first:
-
-\begin{code}
-absApply :: AnalysisKind -> AbsVal -> AbsVal -> AbsVal
-
-absApply anal AbsBot arg = AbsBot
-  -- AbsBot represents the abstract bottom *function* too
-
-absApply StrAnal AbsTop        arg = AbsTop
-absApply AbsAnal AbsTop        arg = if anyBot arg
-                             then AbsBot
-                             else AbsTop
-       -- To be conservative, we have to assume that a function about
-       -- which we know nothing (AbsTop) might look at some part of
-       -- its argument
-\end{code}
-
-An @AbsFun@ with only one more argument needed---bind it and eval the
-result.         A @Lam@ with two or more args: return another @AbsFun@ with
-an augmented environment.
-
-\begin{code}
-absApply anal (AbsFun bndr_ty abs_fn) arg = abs_fn arg
-\end{code}
-
-\begin{code}
-absApply StrAnal (AbsApproxFun (d:ds) val) arg
-  = case ds of 
-       []    -> val'
-       other -> AbsApproxFun ds val'   -- Result is non-bot if there are still args
-  where
-    val' | evalStrictness d arg = AbsBot
-        | otherwise            = val
-
-absApply AbsAnal (AbsApproxFun (d:ds) val) arg
-  = if evalAbsence d arg
-    then AbsBot                -- Poison in arg means poison in the application
-    else case ds of
-               []    -> val
-               other -> AbsApproxFun ds val
-
-#ifdef DEBUG
-absApply anal f@(AbsProd _) arg 
-  = pprPanic ("absApply: Duff function: AbsProd." ++ show anal) ((ppr f) <+> (ppr arg))
-#endif
-\end{code}
-
-
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[findStrictness]{Determine some binders' strictness}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-findStrictness :: Id
-              -> AbsVal                -- Abstract strictness value of function
-              -> AbsVal                -- Abstract absence value of function
-              -> StrictnessInfo        -- Resulting strictness annotation
-
-findStrictness id (AbsApproxFun str_ds str_res) (AbsApproxFun abs_ds _)
-       -- You might think there's really no point in describing detailed
-       -- strictness for a divergent function; 
-       -- If it's fully applied we get bottom regardless of the
-       -- argument.  If it's not fully applied we don't get bottom.
-       -- Finally, we don't want to regard the args of a divergent function
-       -- as 'interesting' for inlining purposes (see Simplify.prepareArgs)
-       --
-       -- HOWEVER, if we make diverging functions appear lazy, they
-       -- don't get wrappers, and then we get dreadful reboxing.
-       -- See notes with WwLib.worthSplitting
-  = find_strictness id str_ds str_res abs_ds
-
-findStrictness id str_val abs_val 
-  | isBot str_val = mkStrictnessInfo ([], True)
-  | otherwise     = NoStrictnessInfo
-
--- The list of absence demands passed to combineDemands 
--- can be shorter than the list of absence demands
---
---     lookup = \ dEq -> letrec {
---                          lookup = \ key ds -> ...lookup...
---                       }
---                       in lookup
--- Here the strictness value takes three args, but the absence value
--- takes only one, for reasons I don't quite understand (see cheapFixpoint)
-
-find_strictness id orig_str_ds orig_str_res orig_abs_ds
-  = mkStrictnessInfo (go orig_str_ds orig_abs_ds, res_bot)
-  where
-    res_bot = isBot orig_str_res
-
-    go str_ds abs_ds = zipWith mk_dmd str_ds (abs_ds ++ repeat wwLazy)
-
-    mk_dmd str_dmd (WwLazy True)
-        = WARN( not (res_bot || isLazy str_dmd),
-                ppr id <+> ppr orig_str_ds <+> ppr orig_abs_ds )
-               -- If the arg isn't used we jolly well don't expect the function
-               -- to be strict in it.  Unless the function diverges.
-          WwLazy True  -- Best of all
-
-    mk_dmd (WwUnpack u str_ds) 
-          (WwUnpack _ abs_ds) = WwUnpack u (go str_ds abs_ds)
-
-    mk_dmd str_dmd abs_dmd = str_dmd
-\end{code}
-
-
-\begin{code}
-findDemand dmd str_env abs_env expr binder
-  = findRecDemand str_fn abs_fn (idType binder)
-  where
-    str_fn val = evalStrictness   dmd (absEval StrAnal expr (addOneToAbsValEnv str_env binder val))
-    abs_fn val = not (evalAbsence dmd (absEval AbsAnal expr (addOneToAbsValEnv abs_env binder val)))
-
-findDemandAlts dmd str_env abs_env alts binder
-  = findRecDemand str_fn abs_fn (idType binder)
-  where
-    str_fn val = evalStrictness   dmd (absEvalAlts StrAnal alts (addOneToAbsValEnv str_env binder val))
-    abs_fn val = not (evalAbsence dmd (absEvalAlts AbsAnal alts (addOneToAbsValEnv abs_env binder val)))
-\end{code}
-
-@findRecDemand@ is where we finally convert strictness/absence info
-into ``Demands'' which we can pin on Ids (etc.).
-
-NOTE: What do we do if something is {\em both} strict and absent?
-Should \tr{f x y z = error "foo"} says that \tr{f}'s arguments are all
-strict (because of bottoming effect of \tr{error}) or all absent
-(because they're not used)?
-
-Well, for practical reasons, we prefer absence over strictness.  In
-particular, it makes the ``default defaults'' for class methods (the
-ones that say \tr{defm.foo dict = error "I don't exist"}) come out
-nicely [saying ``the dict isn't used''], rather than saying it is
-strict in every component of the dictionary [massive gratuitious
-casing to take the dict apart].
-
-But you could have examples where going for strictness would be better
-than absence.  Consider:
-\begin{verbatim}
-       let x = something big
-       in
-       f x y z + g x
-\end{verbatim}
-
-If \tr{x} is marked absent in \tr{f}, but not strict, and \tr{g} is
-lazy, then the thunk for \tr{x} will be built.  If \tr{f} was strict,
-then we'd let-to-case it:
-\begin{verbatim}
-       case something big of
-         x -> f x y z + g x
-\end{verbatim}
-Ho hum.
-
-\begin{code}
-findRecDemand :: (AbsVal -> Bool)      -- True => function applied to this value yields Bot
-             -> (AbsVal -> Bool)       -- True => function applied to this value yields no poison
-             -> Type       -- The type of the argument
-             -> Demand
-
-findRecDemand str_fn abs_fn ty
-  = if isUnLiftedType ty then -- It's a primitive type!
-       wwPrim
-
-    else if abs_fn AbsBot then -- It's absent
-       -- We prefer absence over strictness: see NOTE above.
-       WwLazy True
-
-    else if not (opt_AllStrict ||
-                (opt_NumbersStrict && is_numeric_type ty) ||
-                str_fn AbsBot) then
-       WwLazy False -- It's not strict and we're not pretending
-
-    else -- It's strict (or we're pretending it is)!
-
-       case splitProductType_maybe ty of
-
-        Nothing -> wwStrict    -- Could have a test for wwEnum, but
-                               -- we don't exploit it yet, so don't bother
-
-        Just (tycon,_,data_con,cmpnt_tys)      -- Single constructor case
-          | isRecursiveTyCon tycon             -- Recursive data type; don't unpack
-          ->   wwStrict                        --      (this applies to newtypes too:
-                                               --      e.g.  data Void = MkVoid Void)
-
-          |  null compt_strict_infos           -- A nullary data type
-          ->   wwStrict
-
-          | otherwise                          -- Some other data type
-          ->   wwUnpack compt_strict_infos
-
-          where
-             prod_len = length cmpnt_tys
-             compt_strict_infos
-               = [ findRecDemand
-                        (\ cmpnt_val ->
-                              str_fn (mkMainlyTopProd prod_len i cmpnt_val)
-                        )
-                        (\ cmpnt_val ->
-                              abs_fn (mkMainlyTopProd prod_len i cmpnt_val)
-                        )
-                    cmpnt_ty
-                 | (cmpnt_ty, i) <- cmpnt_tys `zip` [1..] ]
-
-  where
-    is_numeric_type ty
-      = case (splitTyConApp_maybe ty) of -- NB: duplicates stuff done above
-         Nothing         -> False
-         Just (tycon, _) -> tyConUnique tycon `is_elem` numericTyKeys
-      where
-       is_elem = isIn "is_numeric_type"
-
-    -- mkMainlyTopProd: make an AbsProd that is all AbsTops ("n"-1 of
-    -- them) except for a given value in the "i"th position.
-
-    mkMainlyTopProd :: Int -> Int -> AbsVal -> AbsVal
-
-    mkMainlyTopProd n i val
-      = let
-           befores = nOfThem (i-1) AbsTop
-           afters  = nOfThem (n-i) AbsTop
-       in
-       AbsProd (befores ++ (val : afters))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[fixpoint]{Fixpointer for the strictness analyser}
-%*                                                                     *
-%************************************************************************
-
-The @fixpoint@ functions take a list of \tr{(binder, expr)} pairs, an
-environment, and returns the abstract value of each binder.
-
-The @cheapFixpoint@ function makes a conservative approximation,
-by binding each of the variables to Top in their own right hand sides.
-That allows us to make rapid progress, at the cost of a less-than-wonderful
-approximation.
-
-\begin{code}
-cheapFixpoint :: AnalysisKind -> [Id] -> [CoreExpr] -> AbsValEnv -> [AbsVal]
-
-cheapFixpoint AbsAnal [id] [rhs] env
-  = [crudeAbsWiden (absEval AbsAnal rhs new_env)]
-  where
-    new_env = addOneToAbsValEnv env id AbsTop  -- Unsafe starting point!
-                   -- In the just-one-binding case, we guarantee to
-                   -- find a fixed point in just one iteration,
-                   -- because we are using only a two-point domain.
-                   -- This improves matters in cases like:
-                   --
-                   --  f x y = letrec g = ...g...
-                   --          in g x
-                   --
-                   -- Here, y isn't used at all, but if g is bound to
-                   -- AbsBot we simply get AbsBot as the next
-                   -- iteration too.
-
-cheapFixpoint anal ids rhss env
-  = [widen anal (absEval anal rhs new_env) | rhs <- rhss]
-               -- We do just one iteration, starting from a safe
-               -- approximation.  This won't do a good job in situations
-               -- like:
-               --      \x -> letrec f = ...g...
-               --                   g = ...f...x...
-               --            in
-               --            ...f...
-               -- Here, f will end up bound to Top after one iteration,
-               -- and hence we won't spot the strictness in x.
-               -- (A second iteration would solve this.  ToDo: try the effect of
-               --  really searching for a fixed point.)
-  where
-    new_env = growAbsValEnvList env [(id,safe_val) | id <- ids]
-
-    safe_val
-      = case anal of   -- The safe starting point
-         StrAnal -> AbsTop
-         AbsAnal -> AbsBot
-\end{code}
-
-\begin{code}
-fixpoint :: AnalysisKind -> [Id] -> [CoreExpr] -> AbsValEnv -> [AbsVal]
-
-fixpoint anal [] _ env = []
-
-fixpoint anal ids rhss env
-  = fix_loop initial_vals
-  where
-    initial_val id
-      = case anal of   -- The (unsafe) starting point
-         AbsAnal -> AbsTop
-         StrAnal -> AbsBot
-               -- At one stage for StrAnal we said:
-               --   if (returnsRealWorld (idType id))
-               --   then AbsTop -- this is a massively horrible hack (SLPJ 95/05)
-               -- but no one has the foggiest idea what this hack did,
-               -- and returnsRealWorld was a stub that always returned False
-               -- So this comment is all that is left of the hack!
-
-    initial_vals = [ initial_val id | id <- ids ]
-
-    fix_loop :: [AbsVal] -> [AbsVal]
-
-    fix_loop current_widened_vals
-      = let
-           new_env  = growAbsValEnvList env (ids `zip` current_widened_vals)
-           new_vals = [ absEval anal rhs new_env | rhs <- rhss ]
-           new_widened_vals = map (widen anal) new_vals
-       in
-       if (and (zipWith sameVal current_widened_vals new_widened_vals)) then
-           current_widened_vals
-
-           -- NB: I was too chicken to make that a zipWithEqual,
-           -- lest I jump into a black hole.  WDP 96/02
-
-           -- Return the widened values.  We might get a slightly
-           -- better value by returning new_vals (which we used to
-           -- do, see below), but alas that means that whenever the
-           -- function is called we have to re-execute it, which is
-           -- expensive.
-
-           -- OLD VERSION
-           -- new_vals
-           -- Return the un-widened values which may be a bit better
-           -- than the widened ones, and are guaranteed safe, since
-           -- they are one iteration beyond current_widened_vals,
-           -- which itself is a fixed point.
-       else
-           fix_loop new_widened_vals
-\end{code}
-
-For absence analysis, we make do with a very very simple approach:
-look for convergence in a two-point domain.
-
-We used to use just one iteration, starting with the variables bound
-to @AbsBot@, which is safe.
-
-Prior to that, we used one iteration starting from @AbsTop@ (which
-isn't safe).  Why isn't @AbsTop@ safe?  Consider:
-\begin{verbatim}
-       letrec
-         x = ...p..d...
-         d = (x,y)
-       in
-       ...
-\end{verbatim}
-Here, if p is @AbsBot@, then we'd better {\em not} end up with a ``fixed
-point'' of @d@ being @(AbsTop, AbsTop)@!  An @AbsBot@ initial value is
-safe because it gives poison more often than really necessary, and
-thus may miss some absence, but will never claim absence when it ain't
-so.
-
-Anyway, one iteration starting with everything bound to @AbsBot@ give
-bad results for
-
-       f = \ x -> ...f...
-
-Here, f would always end up bound to @AbsBot@, which ain't very
-clever, because then it would introduce poison whenever it was
-applied.  Much better to start with f bound to @AbsTop@, and widen it
-to @AbsBot@ if any poison shows up. In effect we look for convergence
-in the two-point @AbsTop@/@AbsBot@ domain.
-
-What we miss (compared with the cleverer strictness analysis) is
-spotting that in this case
-
-       f = \ x y -> ...y...(f x y')...
-
-\tr{x} is actually absent, since it is only passed round the loop, never
-used.  But who cares about missing that?
-
-NB: despite only having a two-point domain, we may still have many
-iterations, because there are several variables involved at once.
-
-\begin{code}
-#endif /* OLD_STRICTNESS */
-\end{code}
diff --git a/compiler/stranal/SaLib.lhs b/compiler/stranal/SaLib.lhs
deleted file mode 100644 (file)
index 2561d97..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
-%
-\section[SaLib]{Basic datatypes, functions for the strictness analyser}
-
-See also: the ``library'' for the ``back end'' (@SaBackLib@).
-
-\begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
---     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
--- for details
-
-#ifndef OLD_STRICTNESS
-module SaLib () where
-#else
-
-module SaLib (
-       AbsVal(..),
-       AnalysisKind(..),
-       AbsValEnv{-abstract-}, StrictEnv, AbsenceEnv,
-       mkAbsApproxFun,
-       nullAbsValEnv, addOneToAbsValEnv, growAbsValEnvList,
-       lookupAbsValEnv,
-       absValFromStrictness
-    ) where
-
-#include "HsVersions.h"
-
-import Type            ( Type )
-import VarEnv
-import IdInfo          ( StrictnessInfo(..) )
-import Demand          ( Demand )
-import Outputable
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[AbsVal-datatype]{@AbsVal@: abstract values (and @AbsValEnv@)}
-%*                                                                     *
-%************************************************************************
-
-@AnalysisKind@ tells what kind of analysis is being done.
-
-\begin{code}
-data AnalysisKind
-  = StrAnal    -- We're doing strictness analysis
-  | AbsAnal    -- We're doing absence analysis
-  deriving Show
-\end{code}
-
-@AbsVal@ is the data type of HNF abstract values.
-
-\begin{code}
-data AbsVal
-  = AbsTop                 -- AbsTop is the completely uninformative
-                           -- value
-
-  | AbsBot                 -- An expression whose abstract value is
-                           -- AbsBot is sure to fail to terminate.
-                           -- AbsBot represents the abstract
-                           --  *function* bottom too.
-
-  | AbsProd [AbsVal]       -- (Lifted) product of abstract values
-                           -- "Lifted" means that AbsBot is *different* from
-                           --    AbsProd [AbsBot, ..., AbsBot]
-
-  | AbsFun                 -- An abstract function, with the given:
-           Type                 -- Type of the *argument* to the function
-           (AbsVal -> AbsVal)  -- The function
-
-  | AbsApproxFun           -- This is used to represent a coarse
-           [Demand]        -- approximation to a function value.  It's an
-           AbsVal          -- abstract function which is strict in its
-                           -- arguments if the  Demand so indicates.
-       -- INVARIANT: the [Demand] is non-empty
-
-       -- AbsApproxFun has to take a *list* of demands, no just one,
-       -- because function spaces are now lifted.  Hence, (f bot top)
-       -- might be bot, but the partial application (f bot) is a *function*,
-       -- not bot.
-
-mkAbsApproxFun :: Demand -> AbsVal -> AbsVal
-mkAbsApproxFun d (AbsApproxFun ds val) = AbsApproxFun (d:ds) val
-mkAbsApproxFun d val                  = AbsApproxFun [d]    val
-
-instance Outputable AbsVal where
-    ppr AbsTop = ptext (sLit "AbsTop")
-    ppr AbsBot = ptext (sLit "AbsBot")
-    ppr (AbsProd prod) = hsep [ptext (sLit "AbsProd"), ppr prod]
-    ppr (AbsFun bndr_ty body) = ptext (sLit "AbsFun")
-    ppr (AbsApproxFun demands val)
-      = ptext (sLit "AbsApprox") <+> brackets (interpp'SP demands) <+> ppr val
-\end{code}
-
-%-----------
-
-An @AbsValEnv@ maps @Ids@ to @AbsVals@.  Any unbound @Ids@ are
-implicitly bound to @AbsTop@, the completely uninformative,
-pessimistic value---see @absEval@ of a @Var@.
-
-\begin{code}
-newtype AbsValEnv = AbsValEnv (IdEnv AbsVal)
-
-type StrictEnv  = AbsValEnv    -- Environment for strictness analysis
-type AbsenceEnv = AbsValEnv    -- Environment for absence analysis
-
-nullAbsValEnv -- this is the one and only way to create AbsValEnvs
-  = AbsValEnv emptyVarEnv
-
-addOneToAbsValEnv (AbsValEnv idenv) y z = AbsValEnv (extendVarEnv idenv y z)
-growAbsValEnvList (AbsValEnv idenv) ys  = AbsValEnv (extendVarEnvList idenv ys)
-
-lookupAbsValEnv (AbsValEnv idenv) y
-  = lookupVarEnv idenv y
-\end{code}
-
-\begin{code}
-absValFromStrictness :: AnalysisKind -> StrictnessInfo -> AbsVal
-
-absValFromStrictness anal NoStrictnessInfo = AbsTop
-absValFromStrictness anal (StrictnessInfo args_info bot_result)
-  = case args_info of  -- Check the invariant that the arg list on 
-       [] -> res       -- AbsApproxFun is non-empty
-       _  -> AbsApproxFun args_info res
-  where
-    res | not bot_result = AbsTop
-       | otherwise      = case anal of
-                               StrAnal -> AbsBot
-                               AbsAnal -> AbsTop
-\end{code}
-
-\begin{code}
-#endif /* OLD_STRICTNESS */
-\end{code}
diff --git a/compiler/stranal/StrictAnal.lhs b/compiler/stranal/StrictAnal.lhs
deleted file mode 100644 (file)
index 920f841..0000000
+++ /dev/null
@@ -1,464 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
-%
-\section[StrictAnal]{``Simple'' Mycroft-style strictness analyser}
-
-The original version(s) of all strictness-analyser code (except the
-Semantique analyser) was written by Andy Gill.
-
-\begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
---     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
--- for details
-
-#ifndef OLD_STRICTNESS
-module StrictAnal ( ) where
-
-#else
-
-module StrictAnal ( saBinds ) where
-
-#include "HsVersions.h"
-
-import DynFlags        ( DynFlags, DynFlag(..) )
-import CoreSyn
-import Id              ( setIdStrictness, setInlinePragma, 
-                         idDemandInfo, setIdDemandInfo, isBottomingId,
-                         Id
-                       )
-import ErrUtils                ( dumpIfSet_dyn )
-import SaAbsInt
-import SaLib
-import Demand          ( Demand, wwStrict, isStrict, isLazy )
-import Util            ( zipWith3Equal, stretchZipWith, compareLength )
-import BasicTypes      ( Activation( NeverActive ) )
-import Outputable
-import FastTypes
-import State
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[Thoughts]{Random thoughts}
-%*                                                                     *
-%************************************************************************
-
-A note about worker-wrappering.  If we have
-
-       f :: Int -> Int
-       f = let v = <expensive>
-           in \x -> <body>
-
-and we deduce that f is strict, it is nevertheless NOT safe to worker-wapper to
-
-       f = \x -> case x of Int x# -> fw x#
-       fw = \x# -> let x = Int x#
-                   in
-                   let v = <expensive>
-                   in <body>
-
-because this obviously loses laziness, since now <expensive>
-is done each time.  Alas.
-
-WATCH OUT!  This can mean that something is unboxed only to be
-boxed again. For example
-
-       g x y = f x
-
-Here g is strict, and *will* split into worker-wrapper.  A call to
-g, with the wrapper inlined will then be
-
-       case arg of Int a# -> gw a#
-
-Now g calls f, which has no wrapper, so it has to box it.
-
-       gw = \a# -> f (Int a#)
-
-Alas and alack.
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[iface-StrictAnal]{Interface to the outside world}
-%*                                                                     *
-%************************************************************************
-
-@saBinds@ decorates bindings with strictness info.  A later 
-worker-wrapper pass can use this info to create wrappers and
-strict workers.
-
-\begin{code}
-saBinds :: DynFlags -> [CoreBind] -> IO [CoreBind]
-saBinds dflags binds
-  = do {
-       -- Mark each binder with its strictness
-#ifndef OMIT_STRANAL_STATS
-       let { (binds_w_strictness, sa_stats) = runState $ (saTopBinds binds) nullSaStats };
-       dumpIfSet_dyn dflags Opt_D_dump_simpl_stats "Strictness analysis statistics"
-                 (pp_stats sa_stats);
-#else
-       let { binds_w_strictness = unSaM $ saTopBindsBinds binds };
-#endif
-
-       return binds_w_strictness
-    }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[saBinds]{Strictness analysis of bindings}
-%*                                                                     *
-%************************************************************************
-
-[Some of the documentation about types, etc., in \tr{SaLib} may be
-helpful for understanding this module.]
-
-@saTopBinds@ tags each binder in the program with its @Demand@.
-That tells how each binder is {\em used}; if @Strict@, then the binder
-is sure to be evaluated to HNF; if @NonStrict@ it may or may not be;
-if @Absent@, then it certainly is not used. [DATED; ToDo: update]
-
-(The above info is actually recorded for posterity in each binder's
-IdInfo, notably its @DemandInfo@.)
-
-We proceed by analysing the bindings top-to-bottom, building up an
-environment which maps @Id@s to their abstract values (i.e., an
-@AbsValEnv@ maps an @Id@ to its @AbsVal@).
-
-\begin{code}
-saTopBinds :: [CoreBind] -> SaM [CoreBind] -- not exported
-
-saTopBinds binds
-  = let
-       starting_abs_env = nullAbsValEnv
-    in
-    do_it starting_abs_env starting_abs_env binds
-  where
-    do_it _    _    [] = return []
-    do_it senv aenv (b:bs) = do
-        (senv2, aenv2, new_b) <- saTopBind senv  aenv  b
-        new_bs                <- do_it     senv2 aenv2 bs
-        return (new_b : new_bs)
-\end{code}
-
-@saTopBind@ is only used for the top level.  We don't add any demand
-info to these ids because we can't work it out.  In any case, it
-doesn't do us any good to know whether top-level binders are sure to
-be used; we can't turn top-level @let@s into @case@s.
-
-\begin{code}
-saTopBind :: StrictEnv -> AbsenceEnv
-         -> CoreBind
-         -> SaM (StrictEnv, AbsenceEnv, CoreBind)
-
-saTopBind str_env abs_env (NonRec binder rhs) = do
-    new_rhs <- saExpr minDemand str_env abs_env rhs
-    let
-       str_rhs = absEval StrAnal rhs str_env
-       abs_rhs = absEval AbsAnal rhs abs_env
-
-       widened_str_rhs = widen StrAnal str_rhs
-       widened_abs_rhs = widen AbsAnal abs_rhs
-               -- The widening above is done for efficiency reasons.
-               -- See notes on Let case in SaAbsInt.lhs
-
-       new_binder
-         = addStrictnessInfoToTopId
-               widened_str_rhs widened_abs_rhs
-               binder
-
-         -- Augment environments with a mapping of the
-         -- binder to its abstract values, computed by absEval
-       new_str_env = addOneToAbsValEnv str_env binder widened_str_rhs
-       new_abs_env = addOneToAbsValEnv abs_env binder widened_abs_rhs
-    
-    return (new_str_env, new_abs_env, NonRec new_binder new_rhs)
-
-saTopBind str_env abs_env (Rec pairs)
-  = let
-       (binders,rhss) = unzip pairs
-       str_rhss    = fixpoint StrAnal binders rhss str_env
-       abs_rhss    = fixpoint AbsAnal binders rhss abs_env
-                     -- fixpoint returns widened values
-       new_str_env = growAbsValEnvList str_env (binders `zip` str_rhss)
-       new_abs_env = growAbsValEnvList abs_env (binders `zip` abs_rhss)
-       new_binders = zipWith3Equal "saTopBind" addStrictnessInfoToTopId
-                                   str_rhss abs_rhss binders
-    
-    new_rhss <- mapM (saExpr minDemand new_str_env new_abs_env) rhss
-    let
-       new_pairs   = new_binders `zip` new_rhss
-    
-    return (new_str_env, new_abs_env, Rec new_pairs)
-
--- Hack alert!
--- Top level divergent bindings are marked NOINLINE
--- This avoids fruitless inlining of top level error functions
-addStrictnessInfoToTopId str_val abs_val bndr
-  = if isBottomingId new_id then
-       new_id `setInlinePragma` NeverActive
-    else
-       new_id
-  where
-    new_id = addStrictnessInfoToId str_val abs_val bndr
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[saExpr]{Strictness analysis of an expression}
-%*                                                                     *
-%************************************************************************
-
-@saExpr@ computes the strictness of an expression within a given
-environment.
-
-\begin{code}
-saExpr :: Demand -> StrictEnv -> AbsenceEnv -> CoreExpr -> SaM CoreExpr
-       -- The demand is the least demand we expect on the
-       -- expression.  WwStrict is the least, because we're only
-       -- interested in the expression at all if it's being evaluated,
-       -- but the demand may be more.  E.g.
-       --      f E
-       -- where f has strictness u(LL), will evaluate E with demand u(LL)
-
-minDemand = wwStrict 
-minDemands = repeat minDemand
-
--- When we find an application, do the arguments
--- with demands gotten from the function
-saApp str_env abs_env (fun, args) = do
-    args' <- sequence sa_args
-    fun' <- saExpr minDemand str_env abs_env fun
-    return (mkApps fun' args')
-  where
-    arg_dmds = case fun of
-                Var var -> case lookupAbsValEnv str_env var of
-                               Just (AbsApproxFun ds _) 
-                                  | compareLength ds args /= LT 
-                                             -- 'ds' is at least as long as 'args'.
-                                       -> ds ++ minDemands
-                               other   -> minDemands
-                other -> minDemands
-
-    sa_args = stretchZipWith isTypeArg (error "saApp:dmd") 
-                            sa_arg args arg_dmds 
-       -- The arg_dmds are for value args only, we need to skip
-       -- over the type args when pairing up with the demands
-       -- Hence the stretchZipWith
-
-    sa_arg arg dmd = saExpr dmd' str_env abs_env arg
-                  where
-                       -- Bring arg demand up to minDemand
-                       dmd' | isLazy dmd = minDemand
-                            | otherwise  = dmd
-
-saExpr _ _ _ e@(Var _) = return e
-saExpr _ _ _ e@(Lit _) = return e
-saExpr _ _ _ e@(Type _)        = return e
-
-saExpr dmd str_env abs_env (Lam bndr body)
-  = do -- Don't bother to set the demand-info on a lambda binder
-       -- We do that only for let(rec)-bound functions
-    new_body <- saExpr minDemand str_env abs_env body
-    return (Lam bndr new_body)
-
-saExpr dmd str_env abs_env e@(App fun arg)
-  = saApp str_env abs_env (collectArgs e)
-
-saExpr dmd str_env abs_env (Note note expr) = do
-    new_expr <- saExpr dmd str_env abs_env expr
-    return (Note note new_expr)
-
-saExpr dmd str_env abs_env (Case expr case_bndr alts) = do
-    new_expr <- saExpr minDemand str_env abs_env expr
-    new_alts <- mapM sa_alt alts
-    let
-       new_case_bndr = addDemandInfoToCaseBndr dmd str_env abs_env alts case_bndr
-    return (Case new_expr new_case_bndr new_alts)
-  where
-    sa_alt (con, binders, rhs) = do
-        new_rhs <- saExpr dmd str_env abs_env rhs
-       let
-           new_binders = map add_demand_info binders
-           add_demand_info bndr | isTyVar bndr = bndr
-                                | otherwise    = addDemandInfoToId dmd str_env abs_env rhs bndr
-       
-       tickCases new_binders -- stats
-       return (con, new_binders, new_rhs)
-
-saExpr dmd str_env abs_env (Let (NonRec binder rhs) body) = do
-       -- Analyse the RHS in the environment at hand
-    let
-       -- Find the demand on the RHS
-       rhs_dmd = findDemand dmd str_env abs_env body binder
-
-       -- Bind this binder to the abstract value of the RHS; analyse
-       -- the body of the `let' in the extended environment.
-       str_rhs_val     = absEval StrAnal rhs str_env
-       abs_rhs_val     = absEval AbsAnal rhs abs_env
-
-       widened_str_rhs = widen StrAnal str_rhs_val
-       widened_abs_rhs = widen AbsAnal abs_rhs_val
-               -- The widening above is done for efficiency reasons.
-               -- See notes on Let case in SaAbsInt.lhs
-
-       new_str_env     = addOneToAbsValEnv str_env binder widened_str_rhs
-       new_abs_env     = addOneToAbsValEnv abs_env binder widened_abs_rhs
-
-       -- Now determine the strictness of this binder; use that info
-       -- to record DemandInfo/StrictnessInfo in the binder.
-       new_binder = addStrictnessInfoToId
-                       widened_str_rhs widened_abs_rhs
-                       (binder `setIdDemandInfo` rhs_dmd)
-    
-    tickLet new_binder          -- stats
-    new_rhs <- saExpr rhs_dmd str_env abs_env rhs
-    new_body <- saExpr dmd new_str_env new_abs_env body
-    return (Let (NonRec new_binder new_rhs) new_body)
-
-saExpr dmd str_env abs_env (Let (Rec pairs) body) = do
-    let
-       (binders,rhss) = unzip pairs
-       str_vals       = fixpoint StrAnal binders rhss str_env
-       abs_vals       = fixpoint AbsAnal binders rhss abs_env
-                        -- fixpoint returns widened values
-       new_str_env    = growAbsValEnvList str_env (binders `zip` str_vals)
-       new_abs_env    = growAbsValEnvList abs_env (binders `zip` abs_vals)
-    
-    new_body <- saExpr dmd new_str_env new_abs_env body
-    new_rhss <- mapM (saExpr minDemand new_str_env new_abs_env) rhss
-    let
---             DON'T add demand info in a Rec!
---             a) it's useless: we can't do let-to-case
---             b) it's incorrect.  Consider
---                     letrec x = ...y...
---                            y = ...x...
---                     in ...x...
---                When we ask whether y is demanded we'll bind y to bottom and
---                evaluate the body of the letrec.  But that will result in our
---                deciding that y is absent, which is plain wrong!
---             It's much easier simply not to do this.
-
-       improved_binders = zipWith3Equal "saExpr" addStrictnessInfoToId
-                                        str_vals abs_vals binders
-
-       new_pairs   = improved_binders `zip` new_rhss
-    
-    return (Let (Rec new_pairs) new_body)
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[computeInfos]{Add computed info to binders}
-%*                                                                     *
-%************************************************************************
-
-Important note (Sept 93).  @addStrictnessInfoToId@ is used only for
-let(rec) bound variables, and is use to attach the strictness (not
-demand) info to the binder.  We are careful to restrict this
-strictness info to the lambda-bound arguments which are actually
-visible, at the top level, lest we accidentally lose laziness by
-eagerly looking for an "extra" argument.  So we "dig for lambdas" in a
-rather syntactic way.
-
-A better idea might be to have some kind of arity analysis to
-tell how many args could safely be grabbed.
-
-\begin{code}
-addStrictnessInfoToId
-       :: AbsVal               -- Abstract strictness value
-       -> AbsVal               -- Ditto absence
-       -> Id                   -- The id
-       -> Id                   -- Augmented with strictness
-
-addStrictnessInfoToId str_val abs_val binder
-  = binder `setIdStrictness` findStrictness binder str_val abs_val
-\end{code}
-
-\begin{code}
-addDemandInfoToId :: Demand -> StrictEnv -> AbsenceEnv
-                 -> CoreExpr   -- The scope of the id
-                 -> Id
-                 -> Id                 -- Id augmented with Demand info
-
-addDemandInfoToId dmd str_env abs_env expr binder
-  = binder `setIdDemandInfo` (findDemand dmd str_env abs_env expr binder)
-
-addDemandInfoToCaseBndr dmd str_env abs_env alts binder
-  = binder `setIdDemandInfo` (findDemandAlts dmd str_env abs_env alts binder)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Monad used herein for stats}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-data SaStats
-  = SaStats FastInt FastInt    -- total/marked-demanded lambda-bound
-           FastInt FastInt     -- total/marked-demanded case-bound
-           FastInt FastInt     -- total/marked-demanded let-bound
-                               -- (excl. top-level; excl. letrecs)
-
-nullSaStats = SaStats
-   (_ILIT(0)) (_ILIT(0))
-   (_ILIT(0)) (_ILIT(0))
-   (_ILIT(0)) (_ILIT(0))
-
-tickLambda :: Id   -> SaM ()
-tickCases  :: [CoreBndr] -> SaM ()
-tickLet    :: Id   -> SaM ()
-
-#ifndef OMIT_STRANAL_STATS
-type SaM a = State SaStats a
-
-tickLambda var = modify $ \(SaStats tlam dlam tc dc tlet dlet)
-  -> case (tick_demanded var (0,0)) of { (totB, demandedB) ->
-     let tot = iUnbox totB ; demanded = iUnbox demandedB 
-     in SaStats (tlam +# tot) (dlam +# demanded) tc dc tlet dlet)
-
-tickCases vars = modify $ \(SaStats tlam dlam tc dc tlet dlet)
-  = case (foldr tick_demanded (0,0) vars) of { (totB, demandedB) ->
-    let tot = iUnbox totB ; demanded = iUnbox demandedB 
-    in  SaStats tlam dlam (tc +# tot) (dc +# demanded) tlet dlet)
-
-tickLet var = modify $ \(SaStats tlam dlam tc dc tlet dlet)
-  = case (tick_demanded var (0,0))        of { (totB, demandedB) ->
-    let tot = iUnbox totB ; demanded = iUnbox demandedB 
-    in SaStats tlam dlam tc dc (tlet +# tot) (dlet +# demanded))
-
-tick_demanded var (tot, demanded)
-  | isTyVar var = (tot, demanded)
-  | otherwise
-  = (tot + 1,
-     if (isStrict (idDemandInfo var))
-     then demanded + 1
-     else demanded)
-
-pp_stats (SaStats tlam dlam tc dc tlet dlet)
-      = hcat [ptext (sLit "Lambda vars: "), int (iBox dlam), char '/', int (iBox tlam),
-             ptext (sLit "; Case vars: "), int (iBox dc),   char '/', int (iBox tc),
-             ptext (sLit "; Let vars: "),  int (iBox dlet), char '/', int (iBox tlet)
-       ]
-
-#else /* OMIT_STRANAL_STATS */
--- identity monad
-newtype SaM a = SaM { unSaM :: a }
-
-instance Monad SaM where
-    return x    = SaM x
-    SaM x >>= f = f x
-
-tickLambda var  = panic "OMIT_STRANAL_STATS: tickLambda"
-tickCases  vars = panic "OMIT_STRANAL_STATS: tickCases"
-tickLet    var  = panic "OMIT_STRANAL_STATS: tickLet"
-
-#endif /* OMIT_STRANAL_STATS */
-
-#endif /* OLD_STRICTNESS */
-\end{code}
index d23e83e..4e7a494 100644 (file)
@@ -12,12 +12,12 @@ import CoreUtils    ( exprType, exprIsHNF )
 import CoreArity       ( exprArity )
 import Var
 import Id              ( idType, isOneShotLambda, idUnfolding,
-                         setIdNewStrictness, mkWorkerId,
+                         setIdStrictness, mkWorkerId,
                          setInlineActivation, setIdUnfolding,
                          setIdArity )
 import Type            ( Type )
 import IdInfo
-import NewDemand        ( Demand(..), StrictSig(..), DmdType(..), DmdResult(..), 
+import Demand           ( Demand(..), StrictSig(..), DmdType(..), DmdResult(..), 
                          Demands(..), mkTopDmdType, isBotRes, returnsCPR, topSig, isAbsent
                        )
 import UniqSupply
@@ -225,12 +225,12 @@ tryWW is_rec fn_id rhs
 
   where
     fn_info     = idInfo fn_id
-    maybe_fn_dmd = newDemandInfo fn_info
+    maybe_fn_dmd = demandInfo fn_info
     inline_act   = inlinePragmaActivation (inlinePragInfo fn_info)
 
        -- In practice it always will have a strictness 
        -- signature, even if it's a uninformative one
-    strict_sig  = newStrictnessInfo fn_info `orElse` topSig
+    strict_sig  = strictnessInfo fn_info `orElse` topSig
     StrictSig (DmdType env wrap_dmds res_info) = strict_sig
 
        -- new_fn_id has the DmdEnv zapped.  
@@ -239,7 +239,7 @@ tryWW is_rec fn_id rhs
        --      (c) it becomes incorrect as things are cloned, because
        --          we don't push the substitution into it
     new_fn_id | isEmptyVarEnv env = fn_id
-             | otherwise         = fn_id `setIdNewStrictness` 
+             | otherwise         = fn_id `setIdStrictness` 
                                     StrictSig (mkTopDmdType wrap_dmds res_info)
 
     is_fun    = notNull wrap_dmds
@@ -283,7 +283,7 @@ splitFun fn_id fn_info wrap_dmds res_info inline_act rhs
                                -- can't think of a compelling reason. (In ptic, INLINE things are 
                                -- not w/wd). However, the RuleMatchInfo is not transferred since
                                 -- it does not make sense for workers to be constructorlike.
-                       `setIdNewStrictness` StrictSig (mkTopDmdType work_demands work_res_info)
+                       `setIdStrictness` StrictSig (mkTopDmdType work_demands work_res_info)
                                -- Even though we may not be at top level, 
                                -- it's ok to give it an empty DmdEnv
                         `setIdArity` (exprArity work_rhs)
index 2c3581c..611c4d4 100644 (file)
@@ -10,13 +10,13 @@ module WwLib ( mkWwBodies, mkWWstr, mkWorkerArgs ) where
 
 import CoreSyn
 import CoreUtils       ( exprType )
-import Id              ( Id, idType, mkSysLocal, idNewDemandInfo, setIdNewDemandInfo,
+import Id              ( Id, idType, mkSysLocal, idDemandInfo, setIdDemandInfo,
                          isOneShotLambda, setOneShotLambda, setIdUnfolding,
                           setIdInfo
                        )
 import IdInfo          ( vanillaIdInfo )
 import DataCon
-import NewDemand       ( Demand(..), DmdResult(..), Demands(..) ) 
+import Demand          ( Demand(..), DmdResult(..), Demands(..) ) 
 import MkId            ( realWorldPrimId, voidArgId, mkRuntimeErrorApp, rUNTIME_ERROR_ID,
                           mkUnpackCase, mkProductBox )
 import TysWiredIn      ( tupleCon )
@@ -133,7 +133,7 @@ mkWwBodies fun_ty demands res_info one_shots
                     return (id, id, res_ty)
 
        ; let (work_lam_args, work_call_args) = mkWorkerArgs work_args res_ty
-       ; return ([idNewDemandInfo v | v <- work_call_args, isId v],
+       ; return ([idDemandInfo v | v <- work_call_args, isId v],
                   wrap_fn_args . wrap_fn_cpr . wrap_fn_str . applyToVars work_call_args . Var,
                   mkLams work_lam_args. work_fn_str . work_fn_cpr . work_fn_args) }
         -- We use an INLINE unconditionally, even if the wrapper turns out to be
@@ -278,9 +278,9 @@ mkWWargs subst fun_ty arg_info
 applyToVars :: [Var] -> CoreExpr -> CoreExpr
 applyToVars vars fn = mkVarApps fn vars
 
-mk_wrap_arg :: Unique -> Type -> NewDemand.Demand -> Bool -> Id
+mk_wrap_arg :: Unique -> Type -> Demand -> Bool -> Id
 mk_wrap_arg uniq ty dmd one_shot 
-  = set_one_shot one_shot (setIdNewDemandInfo (mkSysLocal (fsLit "w") uniq ty) dmd)
+  = set_one_shot one_shot (setIdDemandInfo (mkSysLocal (fsLit "w") uniq ty) dmd)
   where
     set_one_shot True  id = setOneShotLambda id
     set_one_shot False id = id
@@ -340,7 +340,7 @@ mkWWstr_one arg
   = return ([arg],  nop_fn, nop_fn)
 
   | otherwise
-  = case idNewDemandInfo arg of
+  = case idDemandInfo arg of
 
        -- Absent case.  We don't deal with absence for unlifted types,
        -- though, because it's not so easy to manufacture a placeholder
@@ -392,7 +392,7 @@ mkWWstr_one arg
        -- If the wrapper argument is a one-shot lambda, then
        -- so should (all) the corresponding worker arguments be
        -- This bites when we do w/w on a case join point
-    set_worker_arg_info worker_arg demand = set_one_shot (setIdNewDemandInfo worker_arg demand)
+    set_worker_arg_info worker_arg demand = set_one_shot (setIdDemandInfo worker_arg demand)
 
     set_one_shot | isOneShotLambda arg = setOneShotLambda
                 | otherwise           = \x -> x