PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/simplCore/CSE.lhs

https://github.com/luite/ghc
Haskell | 403 lines | 284 code | 72 blank | 47 comment | 10 complexity | 6bb9ff0d927defc91044f181ccee88db MD5 | raw file
  1. %
  2. % (c) The AQUA Project, Glasgow University, 1993-1998
  3. %
  4. \section{Common subexpression}
  5. \begin{code}
  6. {-# OPTIONS -fno-warn-tabs #-}
  7. -- The above warning supression flag is a temporary kludge.
  8. -- While working on this module you are encouraged to remove it and
  9. -- detab the module (please do the detabbing in a separate patch). See
  10. -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
  11. -- for details
  12. module CSE (
  13. cseProgram
  14. ) where
  15. #include "HsVersions.h"
  16. -- Note [Keep old CSEnv rep]
  17. -- ~~~~~~~~~~~~~~~~~~~~~~~~~
  18. -- Temporarily retain code for the old representation for CSEnv
  19. -- Keeping it only so that we can switch back if a bug shows up
  20. -- or we want to do some performance comparisions
  21. --
  22. -- NB: when you remove this, also delete hashExpr from CoreUtils
  23. #ifdef OLD_CSENV_REP
  24. import CoreUtils ( exprIsBig, hashExpr, eqExpr )
  25. import StaticFlags ( opt_PprStyle_Debug )
  26. import Util ( lengthExceeds )
  27. import UniqFM
  28. import FastString
  29. #else
  30. import TrieMap
  31. #endif
  32. import CoreSubst
  33. import Var ( Var )
  34. import Id ( Id, idType, idInlineActivation, zapIdOccInfo )
  35. import CoreUtils ( mkAltExpr
  36. , exprIsTrivial)
  37. import Type ( tyConAppArgs )
  38. import CoreSyn
  39. import Outputable
  40. import BasicTypes ( isAlwaysActive )
  41. import Data.List
  42. \end{code}
  43. Simple common sub-expression
  44. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  45. When we see
  46. x1 = C a b
  47. x2 = C x1 b
  48. we build up a reverse mapping: C a b -> x1
  49. C x1 b -> x2
  50. and apply that to the rest of the program.
  51. When we then see
  52. y1 = C a b
  53. y2 = C y1 b
  54. we replace the C a b with x1. But then we *dont* want to
  55. add x1 -> y1 to the mapping. Rather, we want the reverse, y1 -> x1
  56. so that a subsequent binding
  57. y2 = C y1 b
  58. will get transformed to C x1 b, and then to x2.
  59. So we carry an extra var->var substitution which we apply *before* looking up in the
  60. reverse mapping.
  61. Note [Shadowing]
  62. ~~~~~~~~~~~~~~~~
  63. We have to be careful about shadowing.
  64. For example, consider
  65. f = \x -> let y = x+x in
  66. h = \x -> x+x
  67. in ...
  68. Here we must *not* do CSE on the inner x+x! The simplifier used to guarantee no
  69. shadowing, but it doesn't any more (it proved too hard), so we clone as we go.
  70. We can simply add clones to the substitution already described.
  71. Note [Case binders 1]
  72. ~~~~~~~~~~~~~~~~~~~~~~
  73. Consider
  74. f = \x -> case x of wild {
  75. (a:as) -> case a of wild1 {
  76. (p,q) -> ...(wild1:as)...
  77. Here, (wild1:as) is morally the same as (a:as) and hence equal to wild.
  78. But that's not quite obvious. In general we want to keep it as (wild1:as),
  79. but for CSE purpose that's a bad idea.
  80. So we add the binding (wild1 -> a) to the extra var->var mapping.
  81. Notice this is exactly backwards to what the simplifier does, which is
  82. to try to replaces uses of 'a' with uses of 'wild1'
  83. Note [Case binders 2]
  84. ~~~~~~~~~~~~~~~~~~~~~~
  85. Consider
  86. case (h x) of y -> ...(h x)...
  87. We'd like to replace (h x) in the alternative, by y. But because of
  88. the preceding [Note: case binders 1], we only want to add the mapping
  89. scrutinee -> case binder
  90. to the reverse CSE mapping if the scrutinee is a non-trivial expression.
  91. (If the scrutinee is a simple variable we want to add the mapping
  92. case binder -> scrutinee
  93. to the substitution
  94. Note [CSE for INLINE and NOINLINE]
  95. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  96. We are careful to do no CSE inside functions that the user has marked as
  97. INLINE or NOINLINE. In terms of Core, that means
  98. a) we do not do CSE inside an InlineRule
  99. b) we do not do CSE on the RHS of a binding b=e
  100. unless b's InlinePragma is AlwaysActive
  101. Here's why (examples from Roman Leshchinskiy). Consider
  102. yes :: Int
  103. {-# NOINLINE yes #-}
  104. yes = undefined
  105. no :: Int
  106. {-# NOINLINE no #-}
  107. no = undefined
  108. foo :: Int -> Int -> Int
  109. {-# NOINLINE foo #-}
  110. foo m n = n
  111. {-# RULES "foo/no" foo no = id #-}
  112. bar :: Int -> Int
  113. bar = foo yes
  114. We do not expect the rule to fire. But if we do CSE, then we get
  115. yes=no, and the rule does fire. Worse, whether we get yes=no or
  116. no=yes depends on the order of the definitions.
  117. In general, CSE should probably never touch things with INLINE pragmas
  118. as this could lead to surprising results. Consider
  119. {-# INLINE foo #-}
  120. foo = <rhs>
  121. {-# NOINLINE bar #-}
  122. bar = <rhs> -- Same rhs as foo
  123. If CSE produces
  124. foo = bar
  125. then foo will never be inlined (when it should be); but if it produces
  126. bar = foo
  127. bar will be inlined (when it should not be). Even if we remove INLINE foo,
  128. we'd still like foo to be inlined if rhs is small. This won't happen
  129. with foo = bar.
  130. Not CSE-ing inside INLINE also solves an annoying bug in CSE. Consider
  131. a worker/wrapper, in which the worker has turned into a single variable:
  132. $wf = h
  133. f = \x -> ...$wf...
  134. Now CSE may transform to
  135. f = \x -> ...h...
  136. But the WorkerInfo for f still says $wf, which is now dead! This won't
  137. happen now that we don't look inside INLINEs (which wrappers are).
  138. Note [CSE for case expressions]
  139. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  140. Consider
  141. case f x of y { pat -> ...let y = f x in ... }
  142. Then we can CSE the inner (f x) to y. In fact 'case' is like a strict
  143. let-binding, and we can use cseRhs for dealing with the scrutinee.
  144. %************************************************************************
  145. %* *
  146. \section{Common subexpression}
  147. %* *
  148. %************************************************************************
  149. \begin{code}
  150. cseProgram :: CoreProgram -> CoreProgram
  151. cseProgram binds = cseBinds emptyCSEnv binds
  152. cseBinds :: CSEnv -> [CoreBind] -> [CoreBind]
  153. cseBinds _ [] = []
  154. cseBinds env (b:bs) = (b':bs')
  155. where
  156. (env1, b') = cseBind env b
  157. bs' = cseBinds env1 bs
  158. cseBind :: CSEnv -> CoreBind -> (CSEnv, CoreBind)
  159. cseBind env (NonRec b e)
  160. = (env2, NonRec b' e')
  161. where
  162. (env1, b') = addBinder env b
  163. (env2, e') = cseRhs env1 (b',e)
  164. cseBind env (Rec pairs)
  165. = (env2, Rec (bs' `zip` es'))
  166. where
  167. (bs,es) = unzip pairs
  168. (env1, bs') = addRecBinders env bs
  169. (env2, es') = mapAccumL cseRhs env1 (bs' `zip` es)
  170. cseRhs :: CSEnv -> (OutBndr, InExpr) -> (CSEnv, OutExpr)
  171. cseRhs env (id',rhs)
  172. = case lookupCSEnv env rhs' of
  173. Just other_expr -> (env, other_expr)
  174. Nothing -> (addCSEnvItem env rhs' (Var id'), rhs')
  175. where
  176. rhs' | isAlwaysActive (idInlineActivation id') = cseExpr env rhs
  177. | otherwise = rhs
  178. -- See Note [CSE for INLINE and NOINLINE]
  179. tryForCSE :: CSEnv -> InExpr -> OutExpr
  180. tryForCSE env expr
  181. | exprIsTrivial expr' = expr' -- No point
  182. | Just smaller <- lookupCSEnv env expr' = smaller
  183. | otherwise = expr'
  184. where
  185. expr' = cseExpr env expr
  186. cseExpr :: CSEnv -> InExpr -> OutExpr
  187. cseExpr env (Type t) = Type (substTy (csEnvSubst env) t)
  188. cseExpr env (Coercion c) = Coercion (substCo (csEnvSubst env) c)
  189. cseExpr _ (Lit lit) = Lit lit
  190. cseExpr env (Var v) = lookupSubst env v
  191. cseExpr env (App f a) = App (cseExpr env f) (tryForCSE env a)
  192. cseExpr env (Tick t e) = Tick t (cseExpr env e)
  193. cseExpr env (Cast e co) = Cast (cseExpr env e) (substCo (csEnvSubst env) co)
  194. cseExpr env (Lam b e) = let (env', b') = addBinder env b
  195. in Lam b' (cseExpr env' e)
  196. cseExpr env (Let bind e) = let (env', bind') = cseBind env bind
  197. in Let bind' (cseExpr env' e)
  198. cseExpr env (Case scrut bndr ty alts) = Case scrut' bndr'' ty alts'
  199. where
  200. alts' = cseAlts env2 scrut' bndr bndr'' alts
  201. (env1, bndr') = addBinder env bndr
  202. bndr'' = zapIdOccInfo bndr'
  203. -- The swizzling from Note [Case binders 2] may
  204. -- cause a dead case binder to be alive, so we
  205. -- play safe here and bring them all to life
  206. (env2, scrut') = cseRhs env1 (bndr'', scrut)
  207. -- Note [CSE for case expressions]
  208. cseAlts :: CSEnv -> OutExpr -> InBndr -> InBndr -> [InAlt] -> [OutAlt]
  209. cseAlts env scrut' bndr bndr' alts
  210. = map cse_alt alts
  211. where
  212. (con_target, alt_env)
  213. = case scrut' of
  214. Var v' -> (v', extendCSSubst env bndr v') -- See Note [Case binders 1]
  215. -- map: bndr -> v'
  216. _ -> (bndr', extendCSEnv env scrut' (Var bndr')) -- See Note [Case binders 2]
  217. -- map: scrut' -> bndr'
  218. arg_tys = tyConAppArgs (idType bndr)
  219. cse_alt (DataAlt con, args, rhs)
  220. | not (null args)
  221. -- Don't try CSE if there are no args; it just increases the number
  222. -- of live vars. E.g.
  223. -- case x of { True -> ....True.... }
  224. -- Don't replace True by x!
  225. -- Hence the 'null args', which also deal with literals and DEFAULT
  226. = (DataAlt con, args', tryForCSE new_env rhs)
  227. where
  228. (env', args') = addBinders alt_env args
  229. new_env = extendCSEnv env' (mkAltExpr (DataAlt con) args' arg_tys)
  230. (Var con_target)
  231. cse_alt (con, args, rhs)
  232. = (con, args', tryForCSE env' rhs)
  233. where
  234. (env', args') = addBinders alt_env args
  235. \end{code}
  236. %************************************************************************
  237. %* *
  238. \section{The CSE envt}
  239. %* *
  240. %************************************************************************
  241. \begin{code}
  242. type InExpr = CoreExpr -- Pre-cloning
  243. type InBndr = CoreBndr
  244. type InAlt = CoreAlt
  245. type OutExpr = CoreExpr -- Post-cloning
  246. type OutBndr = CoreBndr
  247. type OutAlt = CoreAlt
  248. -- See Note [Keep old CsEnv rep]
  249. #ifdef OLD_CSENV_REP
  250. data CSEnv = CS { cs_map :: CSEMap
  251. , cs_subst :: Subst }
  252. type CSEMap = UniqFM [(OutExpr, OutExpr)] -- This is the reverse mapping
  253. -- It maps the hash-code of an expression e to list of (e,e') pairs
  254. -- This means that it's good to replace e by e'
  255. -- INVARIANT: The expr in the range has already been CSE'd
  256. emptyCSEnv :: CSEnv
  257. emptyCSEnv = CS { cs_map = emptyUFM, cs_subst = emptySubst }
  258. lookupCSEnv :: CSEnv -> OutExpr -> Maybe OutExpr
  259. lookupCSEnv (CS { cs_map = oldmap, cs_subst = sub}) expr
  260. = case lookupUFM oldmap (hashExpr expr) of
  261. Nothing -> Nothing
  262. Just pairs -> lookup_list pairs
  263. where
  264. in_scope = substInScope sub
  265. -- In this lookup we use full expression equality
  266. -- Reason: when expressions differ we generally find out quickly
  267. -- but I found that cheapEqExpr was saying (\x.x) /= (\y.y),
  268. -- and this kind of thing happened in real programs
  269. lookup_list :: [(OutExpr,OutExpr)] -> Maybe OutExpr
  270. lookup_list ((e,e'):es)
  271. | eqExpr in_scope e expr = Just e'
  272. | otherwise = lookup_list es
  273. lookup_list [] = Nothing
  274. addCSEnvItem :: CSEnv -> OutExpr -> OutExpr -> CSEnv
  275. addCSEnvItem env expr expr' | exprIsBig expr = env
  276. | otherwise = extendCSEnv env expr expr'
  277. -- We don't try to CSE big expressions, because they are expensive to compare
  278. -- (and are unlikely to be the same anyway)
  279. extendCSEnv :: CSEnv -> OutExpr -> OutExpr -> CSEnv
  280. extendCSEnv cse@(CS { cs_map = oldmap }) expr expr'
  281. = cse { cs_map = addToUFM_C combine oldmap hash [(expr, expr')] }
  282. where
  283. hash = hashExpr expr
  284. combine old new
  285. = WARN( result `lengthExceeds` 4, short_msg $$ nest 2 long_msg ) result
  286. where
  287. result = new ++ old
  288. short_msg = ptext (sLit "extendCSEnv: long list, length") <+> int (length result)
  289. long_msg | opt_PprStyle_Debug = (text "hash code" <+> text (show hash)) $$ ppr result
  290. | otherwise = empty
  291. #else
  292. ------------ NEW ----------------
  293. data CSEnv = CS { cs_map :: CoreMap (OutExpr, OutExpr) -- Key, value
  294. , cs_subst :: Subst }
  295. emptyCSEnv :: CSEnv
  296. emptyCSEnv = CS { cs_map = emptyCoreMap, cs_subst = emptySubst }
  297. lookupCSEnv :: CSEnv -> OutExpr -> Maybe OutExpr
  298. lookupCSEnv (CS { cs_map = csmap }) expr
  299. = case lookupCoreMap csmap expr of
  300. Just (_,e) -> Just e
  301. Nothing -> Nothing
  302. addCSEnvItem :: CSEnv -> OutExpr -> OutExpr -> CSEnv
  303. addCSEnvItem = extendCSEnv
  304. -- We used to avoid trying to CSE big expressions, on the grounds
  305. -- that they are expensive to compare. But now we have CoreMaps
  306. -- we can happily insert them and laziness will mean that the
  307. -- insertions only get fully done if we look up in that part
  308. -- of the trie. No need for a size test.
  309. extendCSEnv :: CSEnv -> OutExpr -> OutExpr -> CSEnv
  310. extendCSEnv cse expr expr'
  311. = cse { cs_map = extendCoreMap (cs_map cse) expr (expr,expr') }
  312. #endif
  313. csEnvSubst :: CSEnv -> Subst
  314. csEnvSubst = cs_subst
  315. lookupSubst :: CSEnv -> Id -> OutExpr
  316. lookupSubst (CS { cs_subst = sub}) x = lookupIdSubst (text "CSE.lookupSubst") sub x
  317. extendCSSubst :: CSEnv -> Id -> Id -> CSEnv
  318. extendCSSubst cse x y = cse { cs_subst = extendIdSubst (cs_subst cse) x (Var y) }
  319. addBinder :: CSEnv -> Var -> (CSEnv, Var)
  320. addBinder cse v = (cse { cs_subst = sub' }, v')
  321. where
  322. (sub', v') = substBndr (cs_subst cse) v
  323. addBinders :: CSEnv -> [Var] -> (CSEnv, [Var])
  324. addBinders cse vs = (cse { cs_subst = sub' }, vs')
  325. where
  326. (sub', vs') = substBndrs (cs_subst cse) vs
  327. addRecBinders :: CSEnv -> [Id] -> (CSEnv, [Id])
  328. addRecBinders cse vs = (cse { cs_subst = sub' }, vs')
  329. where
  330. (sub', vs') = substRecBndrs (cs_subst cse) vs
  331. \end{code}