PageRenderTime 23ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/ghc-7.0.4/compiler/basicTypes/Demand.lhs

http://picorec.googlecode.com/
Haskell | 342 lines | 227 code | 75 blank | 40 comment | 8 complexity | 3ff74bff5860dfcff23e3995f77c0a12 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. %
  2. % (c) The University of Glasgow 2006
  3. % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
  4. %
  5. \section[Demand]{@Demand@: the amount of demand on a value}
  6. \begin{code}
  7. module Demand(
  8. Demand(..),
  9. topDmd, lazyDmd, seqDmd, evalDmd, errDmd, isStrictDmd,
  10. isTop, isAbsent, seqDemand,
  11. DmdType(..), topDmdType, botDmdType, mkDmdType, mkTopDmdType,
  12. dmdTypeDepth, seqDmdType,
  13. DmdEnv, emptyDmdEnv,
  14. DmdResult(..), retCPR, isBotRes, returnsCPR, resTypeArgDmd,
  15. Demands(..), mapDmds, zipWithDmds, allTop, seqDemands,
  16. StrictSig(..), mkStrictSig, topSig, botSig, cprSig,
  17. isTopSig,
  18. splitStrictSig, increaseStrictSigArity,
  19. pprIfaceStrictSig, appIsBottom, isBottomingSig, seqStrictSig,
  20. ) where
  21. #include "HsVersions.h"
  22. import StaticFlags
  23. import BasicTypes
  24. import VarEnv
  25. import UniqFM
  26. import Util
  27. import Outputable
  28. \end{code}
  29. %************************************************************************
  30. %* *
  31. \subsection{Demands}
  32. %* *
  33. %************************************************************************
  34. \begin{code}
  35. data Demand
  36. = Top -- T; used for unlifted types too, so that
  37. -- A `lub` T = T
  38. | Abs -- A
  39. | Call Demand -- C(d)
  40. | Eval Demands -- U(ds)
  41. | Defer Demands -- D(ds)
  42. | Box Demand -- B(d)
  43. | Bot -- B
  44. deriving( Eq )
  45. -- Equality needed for fixpoints in DmdAnal
  46. data Demands = Poly Demand -- Polymorphic case
  47. | Prod [Demand] -- Product case
  48. deriving( Eq )
  49. allTop :: Demands -> Bool
  50. allTop (Poly d) = isTop d
  51. allTop (Prod ds) = all isTop ds
  52. isTop :: Demand -> Bool
  53. isTop Top = True
  54. isTop _ = False
  55. isAbsent :: Demand -> Bool
  56. isAbsent Abs = True
  57. isAbsent _ = False
  58. mapDmds :: (Demand -> Demand) -> Demands -> Demands
  59. mapDmds f (Poly d) = Poly (f d)
  60. mapDmds f (Prod ds) = Prod (map f ds)
  61. zipWithDmds :: (Demand -> Demand -> Demand)
  62. -> Demands -> Demands -> Demands
  63. zipWithDmds f (Poly d1) (Poly d2) = Poly (d1 `f` d2)
  64. zipWithDmds f (Prod ds1) (Poly d2) = Prod [d1 `f` d2 | d1 <- ds1]
  65. zipWithDmds f (Poly d1) (Prod ds2) = Prod [d1 `f` d2 | d2 <- ds2]
  66. zipWithDmds f (Prod ds1) (Prod ds2)
  67. | length ds1 == length ds2 = Prod (zipWithEqual "zipWithDmds" f ds1 ds2)
  68. | otherwise = Poly topDmd
  69. -- This really can happen with polymorphism
  70. -- \f. case f x of (a,b) -> ...
  71. -- case f y of (a,b,c) -> ...
  72. -- Here the two demands on f are C(LL) and C(LLL)!
  73. topDmd, lazyDmd, seqDmd, evalDmd, errDmd :: Demand
  74. topDmd = Top -- The most uninformative demand
  75. lazyDmd = Box Abs
  76. seqDmd = Eval (Poly Abs) -- Polymorphic seq demand
  77. evalDmd = Box seqDmd -- Evaluate and return
  78. errDmd = Box Bot -- This used to be called X
  79. isStrictDmd :: Demand -> Bool
  80. isStrictDmd Bot = True
  81. isStrictDmd (Eval _) = True
  82. isStrictDmd (Call _) = True
  83. isStrictDmd (Box d) = isStrictDmd d
  84. isStrictDmd _ = False
  85. seqDemand :: Demand -> ()
  86. seqDemand (Call d) = seqDemand d
  87. seqDemand (Eval ds) = seqDemands ds
  88. seqDemand (Defer ds) = seqDemands ds
  89. seqDemand (Box d) = seqDemand d
  90. seqDemand _ = ()
  91. seqDemands :: Demands -> ()
  92. seqDemands (Poly d) = seqDemand d
  93. seqDemands (Prod ds) = seqDemandList ds
  94. seqDemandList :: [Demand] -> ()
  95. seqDemandList [] = ()
  96. seqDemandList (d:ds) = seqDemand d `seq` seqDemandList ds
  97. instance Outputable Demand where
  98. ppr Top = char 'T'
  99. ppr Abs = char 'A'
  100. ppr Bot = char 'B'
  101. ppr (Defer ds) = char 'D' <> ppr ds
  102. ppr (Eval ds) = char 'U' <> ppr ds
  103. ppr (Box (Eval ds)) = char 'S' <> ppr ds
  104. ppr (Box Abs) = char 'L'
  105. ppr (Box Bot) = char 'X'
  106. ppr d@(Box _) = pprPanic "ppr: Bad boxed demand" (ppr d)
  107. ppr (Call d) = char 'C' <> parens (ppr d)
  108. instance Outputable Demands where
  109. ppr (Poly Abs) = empty
  110. ppr (Poly d) = parens (ppr d <> char '*')
  111. ppr (Prod ds) = parens (hcat (map ppr ds))
  112. -- At one time I printed U(AAA) as U, but that
  113. -- confuses (Poly Abs) with (Prod AAA), and the
  114. -- worker/wrapper generation differs slightly for these two
  115. -- [Reason: in the latter case we can avoid passing the arg;
  116. -- see notes with WwLib.mkWWstr_one.]
  117. \end{code}
  118. %************************************************************************
  119. %* *
  120. \subsection{Demand types}
  121. %* *
  122. %************************************************************************
  123. \begin{code}
  124. data DmdType = DmdType
  125. DmdEnv -- Demand on explicitly-mentioned
  126. -- free variables
  127. [Demand] -- Demand on arguments
  128. DmdResult -- Nature of result
  129. -- IMPORTANT INVARIANT
  130. -- The default demand on free variables not in the DmdEnv is:
  131. -- DmdResult = BotRes <=> Bot
  132. -- DmdResult = TopRes/ResCPR <=> Abs
  133. -- ANOTHER IMPORTANT INVARIANT
  134. -- The Demands in the argument list are never
  135. -- Bot, Defer d
  136. -- Handwavey reason: these don't correspond to calling conventions
  137. -- See DmdAnal.funArgDemand for details
  138. -- This guy lets us switch off CPR analysis
  139. -- by making sure that everything uses TopRes instead of RetCPR
  140. -- Assuming, of course, that they don't mention RetCPR by name.
  141. -- They should onlyu use retCPR
  142. retCPR :: DmdResult
  143. retCPR | opt_CprOff = TopRes
  144. | otherwise = RetCPR
  145. seqDmdType :: DmdType -> ()
  146. seqDmdType (DmdType _env ds res) =
  147. {- ??? env `seq` -} seqDemandList ds `seq` res `seq` ()
  148. type DmdEnv = VarEnv Demand
  149. data DmdResult = TopRes -- Nothing known
  150. | RetCPR -- Returns a constructed product
  151. | BotRes -- Diverges or errors
  152. deriving( Eq, Show )
  153. -- Equality for fixpoints
  154. -- Show needed for Show in Lex.Token (sigh)
  155. -- Equality needed for fixpoints in DmdAnal
  156. instance Eq DmdType where
  157. (==) (DmdType fv1 ds1 res1)
  158. (DmdType fv2 ds2 res2) = ufmToList fv1 == ufmToList fv2
  159. && ds1 == ds2 && res1 == res2
  160. instance Outputable DmdType where
  161. ppr (DmdType fv ds res)
  162. = hsep [text "DmdType",
  163. hcat (map ppr ds) <> ppr res,
  164. if null fv_elts then empty
  165. else braces (fsep (map pp_elt fv_elts))]
  166. where
  167. pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
  168. fv_elts = ufmToList fv
  169. instance Outputable DmdResult where
  170. ppr TopRes = empty -- Keep these distinct from Demand letters
  171. ppr RetCPR = char 'm' -- so that we can print strictness sigs as
  172. ppr BotRes = char 'b' -- dddr
  173. -- without ambiguity
  174. emptyDmdEnv :: VarEnv Demand
  175. emptyDmdEnv = emptyVarEnv
  176. topDmdType, botDmdType, cprDmdType :: DmdType
  177. topDmdType = DmdType emptyDmdEnv [] TopRes
  178. botDmdType = DmdType emptyDmdEnv [] BotRes
  179. cprDmdType = DmdType emptyVarEnv [] retCPR
  180. isTopDmdType :: DmdType -> Bool
  181. -- Only used on top-level types, hence the assert
  182. isTopDmdType (DmdType env [] TopRes) = ASSERT( isEmptyVarEnv env) True
  183. isTopDmdType _ = False
  184. isBotRes :: DmdResult -> Bool
  185. isBotRes BotRes = True
  186. isBotRes _ = False
  187. resTypeArgDmd :: DmdResult -> Demand
  188. -- TopRes and BotRes are polymorphic, so that
  189. -- BotRes = Bot -> BotRes
  190. -- TopRes = Top -> TopRes
  191. -- This function makes that concrete
  192. -- We can get a RetCPR, because of the way in which we are (now)
  193. -- giving CPR info to strict arguments. On the first pass, when
  194. -- nothing has demand info, we optimistically give CPR info or RetCPR to all args
  195. resTypeArgDmd TopRes = Top
  196. resTypeArgDmd RetCPR = Top
  197. resTypeArgDmd BotRes = Bot
  198. returnsCPR :: DmdResult -> Bool
  199. returnsCPR RetCPR = True
  200. returnsCPR _ = False
  201. mkDmdType :: DmdEnv -> [Demand] -> DmdResult -> DmdType
  202. mkDmdType fv ds res = DmdType fv ds res
  203. mkTopDmdType :: [Demand] -> DmdResult -> DmdType
  204. mkTopDmdType ds res = DmdType emptyDmdEnv ds res
  205. dmdTypeDepth :: DmdType -> Arity
  206. dmdTypeDepth (DmdType _ ds _) = length ds
  207. \end{code}
  208. %************************************************************************
  209. %* *
  210. \subsection{Strictness signature
  211. %* *
  212. %************************************************************************
  213. In a let-bound Id we record its strictness info.
  214. In principle, this strictness info is a demand transformer, mapping
  215. a demand on the Id into a DmdType, which gives
  216. a) the free vars of the Id's value
  217. b) the Id's arguments
  218. c) an indication of the result of applying
  219. the Id to its arguments
  220. However, in fact we store in the Id an extremely emascuated demand transfomer,
  221. namely
  222. a single DmdType
  223. (Nevertheless we dignify StrictSig as a distinct type.)
  224. This DmdType gives the demands unleashed by the Id when it is applied
  225. to as many arguments as are given in by the arg demands in the DmdType.
  226. For example, the demand transformer described by the DmdType
  227. DmdType {x -> U(LL)} [V,A] Top
  228. says that when the function is applied to two arguments, it
  229. unleashes demand U(LL) on the free var x, V on the first arg,
  230. and A on the second.
  231. If this same function is applied to one arg, all we can say is
  232. that it uses x with U*(LL), and its arg with demand L.
  233. \begin{code}
  234. newtype StrictSig = StrictSig DmdType
  235. deriving( Eq )
  236. instance Outputable StrictSig where
  237. ppr (StrictSig ty) = ppr ty
  238. instance Show StrictSig where
  239. show (StrictSig ty) = showSDoc (ppr ty)
  240. mkStrictSig :: DmdType -> StrictSig
  241. mkStrictSig dmd_ty = StrictSig dmd_ty
  242. splitStrictSig :: StrictSig -> ([Demand], DmdResult)
  243. splitStrictSig (StrictSig (DmdType _ dmds res)) = (dmds, res)
  244. increaseStrictSigArity :: Int -> StrictSig -> StrictSig
  245. -- Add extra arguments to a strictness signature
  246. increaseStrictSigArity arity_increase (StrictSig (DmdType env dmds res))
  247. = StrictSig (DmdType env (replicate arity_increase topDmd ++ dmds) res)
  248. isTopSig :: StrictSig -> Bool
  249. isTopSig (StrictSig ty) = isTopDmdType ty
  250. topSig, botSig, cprSig :: StrictSig
  251. topSig = StrictSig topDmdType
  252. botSig = StrictSig botDmdType
  253. cprSig = StrictSig cprDmdType
  254. -- appIsBottom returns true if an application to n args would diverge
  255. appIsBottom :: StrictSig -> Int -> Bool
  256. appIsBottom (StrictSig (DmdType _ ds BotRes)) n = listLengthCmp ds n /= GT
  257. appIsBottom _ _ = False
  258. isBottomingSig :: StrictSig -> Bool
  259. isBottomingSig (StrictSig (DmdType _ _ BotRes)) = True
  260. isBottomingSig _ = False
  261. seqStrictSig :: StrictSig -> ()
  262. seqStrictSig (StrictSig ty) = seqDmdType ty
  263. pprIfaceStrictSig :: StrictSig -> SDoc
  264. -- Used for printing top-level strictness pragmas in interface files
  265. pprIfaceStrictSig (StrictSig (DmdType _ dmds res))
  266. = hcat (map ppr dmds) <> ppr res
  267. \end{code}