PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/ghc-7.0.4/compiler/simplCore/CSE.lhs

http://picorec.googlecode.com/
Haskell | 359 lines | 260 code | 65 blank | 34 comment | 9 complexity | 2e0bd6885332de36acc2684a9ebc2f47 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. %
  2. % (c) The AQUA Project, Glasgow University, 1993-1998
  3. %
  4. \section{Common subexpression}
  5. \begin{code}
  6. module CSE (
  7. cseProgram
  8. ) where
  9. #include "HsVersions.h"
  10. import Id ( Id, idType, idInlineActivation, zapIdOccInfo )
  11. import CoreUtils ( hashExpr, eqExpr, exprIsBig, mkAltExpr, exprIsCheap )
  12. import DataCon ( isUnboxedTupleCon )
  13. import Type ( tyConAppArgs )
  14. import CoreSyn
  15. import VarEnv
  16. import Outputable
  17. import StaticFlags ( opt_PprStyle_Debug )
  18. import BasicTypes ( isAlwaysActive )
  19. import Util ( lengthExceeds )
  20. import UniqFM
  21. import FastString
  22. import Data.List
  23. \end{code}
  24. Simple common sub-expression
  25. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  26. When we see
  27. x1 = C a b
  28. x2 = C x1 b
  29. we build up a reverse mapping: C a b -> x1
  30. C x1 b -> x2
  31. and apply that to the rest of the program.
  32. When we then see
  33. y1 = C a b
  34. y2 = C y1 b
  35. we replace the C a b with x1. But then we *dont* want to
  36. add x1 -> y1 to the mapping. Rather, we want the reverse, y1 -> x1
  37. so that a subsequent binding
  38. y2 = C y1 b
  39. will get transformed to C x1 b, and then to x2.
  40. So we carry an extra var->var substitution which we apply *before* looking up in the
  41. reverse mapping.
  42. Note [Shadowing]
  43. ~~~~~~~~~~~~~~~~
  44. We have to be careful about shadowing.
  45. For example, consider
  46. f = \x -> let y = x+x in
  47. h = \x -> x+x
  48. in ...
  49. Here we must *not* do CSE on the inner x+x! The simplifier used to guarantee no
  50. shadowing, but it doesn't any more (it proved too hard), so we clone as we go.
  51. We can simply add clones to the substitution already described.
  52. However, we do NOT clone type variables. It's just too hard, because then we need
  53. to run the substitution over types and IdInfo. No no no. Instead, we just throw
  54. (In fact, I think the simplifier does guarantee no-shadowing for type variables.)
  55. Note [Case binders 1]
  56. ~~~~~~~~~~~~~~~~~~~~~~
  57. Consider
  58. f = \x -> case x of wild {
  59. (a:as) -> case a of wild1 {
  60. (p,q) -> ...(wild1:as)...
  61. Here, (wild1:as) is morally the same as (a:as) and hence equal to wild.
  62. But that's not quite obvious. In general we want to keep it as (wild1:as),
  63. but for CSE purpose that's a bad idea.
  64. So we add the binding (wild1 -> a) to the extra var->var mapping.
  65. Notice this is exactly backwards to what the simplifier does, which is
  66. to try to replaces uses of 'a' with uses of 'wild1'
  67. Note [Case binders 2]
  68. ~~~~~~~~~~~~~~~~~~~~~~
  69. Consider
  70. case (h x) of y -> ...(h x)...
  71. We'd like to replace (h x) in the alternative, by y. But because of
  72. the preceding [Note: case binders 1], we only want to add the mapping
  73. scrutinee -> case binder
  74. to the reverse CSE mapping if the scrutinee is a non-trivial expression.
  75. (If the scrutinee is a simple variable we want to add the mapping
  76. case binder -> scrutinee
  77. to the substitution
  78. Note [Unboxed tuple case binders]
  79. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  80. Consider
  81. case f x of t { (# a,b #) ->
  82. case ... of
  83. True -> f x
  84. False -> 0 }
  85. We must not replace (f x) by t, because t is an unboxed-tuple binder.
  86. Instead, we shoudl replace (f x) by (# a,b #). That is, the "reverse mapping" is
  87. f x --> (# a,b #)
  88. That is why the CSEMap has pairs of expressions.
  89. Note [CSE for INLINE and NOINLINE]
  90. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  91. We are careful to do no CSE inside functions that the user has marked as
  92. INLINE or NOINLINE. In terms of Core, that means
  93. a) we do not do CSE inside an InlineRule
  94. b) we do not do CSE on the RHS of a binding b=e
  95. unless b's InlinePragma is AlwaysActive
  96. Here's why (examples from Roman Leshchinskiy). Consider
  97. yes :: Int
  98. {-# NOINLINE yes #-}
  99. yes = undefined
  100. no :: Int
  101. {-# NOINLINE no #-}
  102. no = undefined
  103. foo :: Int -> Int -> Int
  104. {-# NOINLINE foo #-}
  105. foo m n = n
  106. {-# RULES "foo/no" foo no = id #-}
  107. bar :: Int -> Int
  108. bar = foo yes
  109. We do not expect the rule to fire. But if we do CSE, then we get
  110. yes=no, and the rule does fire. Worse, whether we get yes=no or
  111. no=yes depends on the order of the definitions.
  112. In general, CSE should probably never touch things with INLINE pragmas
  113. as this could lead to surprising results. Consider
  114. {-# INLINE foo #-}
  115. foo = <rhs>
  116. {-# NOINLINE bar #-}
  117. bar = <rhs> -- Same rhs as foo
  118. If CSE produces
  119. foo = bar
  120. then foo will never be inlined (when it should be); but if it produces
  121. bar = foo
  122. bar will be inlined (when it should not be). Even if we remove INLINE foo,
  123. we'd still like foo to be inlined if rhs is small. This won't happen
  124. with foo = bar.
  125. Not CSE-ing inside INLINE also solves an annoying bug in CSE. Consider
  126. a worker/wrapper, in which the worker has turned into a single variable:
  127. $wf = h
  128. f = \x -> ...$wf...
  129. Now CSE may transform to
  130. f = \x -> ...h...
  131. But the WorkerInfo for f still says $wf, which is now dead! This won't
  132. happen now that we don't look inside INLINEs (which wrappers are).
  133. %************************************************************************
  134. %* *
  135. \section{Common subexpression}
  136. %* *
  137. %************************************************************************
  138. \begin{code}
  139. cseProgram :: [CoreBind] -> [CoreBind]
  140. cseProgram binds = cseBinds emptyCSEnv binds
  141. cseBinds :: CSEnv -> [CoreBind] -> [CoreBind]
  142. cseBinds _ [] = []
  143. cseBinds env (b:bs) = (b':bs')
  144. where
  145. (env1, b') = cseBind env b
  146. bs' = cseBinds env1 bs
  147. cseBind :: CSEnv -> CoreBind -> (CSEnv, CoreBind)
  148. cseBind env (NonRec b e) = let (env', (b',e')) = do_one env (b, e)
  149. in (env', NonRec b' e')
  150. cseBind env (Rec pairs) = let (env', pairs') = mapAccumL do_one env pairs
  151. in (env', Rec pairs')
  152. do_one :: CSEnv -> (Id, CoreExpr) -> (CSEnv, (Id, CoreExpr))
  153. do_one env (id, rhs)
  154. = case lookupCSEnv env rhs' of
  155. Just (Var other_id) -> (extendSubst env' id other_id, (id', Var other_id))
  156. Just other_expr -> (env', (id', other_expr))
  157. Nothing -> (addCSEnvItem env' rhs' (Var id'), (id', rhs'))
  158. where
  159. (env', id') = addBinder env id
  160. rhs' | isAlwaysActive (idInlineActivation id) = cseExpr env' rhs
  161. | otherwise = rhs
  162. -- See Note [CSE for INLINE and NOINLINE]
  163. tryForCSE :: CSEnv -> CoreExpr -> CoreExpr
  164. tryForCSE _ (Type t) = Type t
  165. tryForCSE env expr = case lookupCSEnv env expr' of
  166. Just smaller_expr -> smaller_expr
  167. Nothing -> expr'
  168. where
  169. expr' = cseExpr env expr
  170. cseExpr :: CSEnv -> CoreExpr -> CoreExpr
  171. cseExpr _ (Type t) = Type t
  172. cseExpr _ (Lit lit) = Lit lit
  173. cseExpr env (Var v) = Var (lookupSubst env v)
  174. cseExpr env (App f a) = App (cseExpr env f) (tryForCSE env a)
  175. cseExpr env (Note n e) = Note n (cseExpr env e)
  176. cseExpr env (Cast e co) = Cast (cseExpr env e) co
  177. cseExpr env (Lam b e) = let (env', b') = addBinder env b
  178. in Lam b' (cseExpr env' e)
  179. cseExpr env (Let bind e) = let (env', bind') = cseBind env bind
  180. in Let bind' (cseExpr env' e)
  181. cseExpr env (Case scrut bndr ty alts) = Case scrut' bndr'' ty (cseAlts env' scrut' bndr bndr'' alts)
  182. where
  183. scrut' = tryForCSE env scrut
  184. (env', bndr') = addBinder env bndr
  185. bndr'' = zapIdOccInfo bndr'
  186. -- The swizzling from Note [Case binders 2] may
  187. -- cause a dead case binder to be alive, so we
  188. -- play safe here and bring them all to life
  189. cseAlts :: CSEnv -> CoreExpr -> CoreBndr -> CoreBndr -> [CoreAlt] -> [CoreAlt]
  190. cseAlts env scrut' bndr _bndr' [(DataAlt con, args, rhs)]
  191. | isUnboxedTupleCon con
  192. -- Unboxed tuples are special because the case binder isn't
  193. -- a real value. See Note [Unboxed tuple case binders]
  194. = [(DataAlt con, args'', tryForCSE new_env rhs)]
  195. where
  196. (env', args') = addBinders env args
  197. args'' = map zapIdOccInfo args' -- They should all be ids
  198. -- Same motivation for zapping as [Case binders 2] only this time
  199. -- it's Note [Unboxed tuple case binders]
  200. new_env | exprIsCheap scrut' = env'
  201. | otherwise = extendCSEnv env' scrut' tup_value
  202. tup_value = mkAltExpr (DataAlt con) args'' (tyConAppArgs (idType bndr))
  203. cseAlts env scrut' bndr bndr' alts
  204. = map cse_alt alts
  205. where
  206. (con_target, alt_env)
  207. = case scrut' of
  208. Var v' -> (v', extendSubst env bndr v') -- See Note [Case binders 1]
  209. -- map: bndr -> v'
  210. _ -> (bndr', extendCSEnv env scrut' (Var bndr')) -- See Note [Case binders 2]
  211. -- map: scrut' -> bndr'
  212. arg_tys = tyConAppArgs (idType bndr)
  213. cse_alt (DataAlt con, args, rhs)
  214. | not (null args)
  215. -- Don't try CSE if there are no args; it just increases the number
  216. -- of live vars. E.g.
  217. -- case x of { True -> ....True.... }
  218. -- Don't replace True by x!
  219. -- Hence the 'null args', which also deal with literals and DEFAULT
  220. = (DataAlt con, args', tryForCSE new_env rhs)
  221. where
  222. (env', args') = addBinders alt_env args
  223. new_env = extendCSEnv env' (mkAltExpr (DataAlt con) args' arg_tys)
  224. (Var con_target)
  225. cse_alt (con, args, rhs)
  226. = (con, args', tryForCSE env' rhs)
  227. where
  228. (env', args') = addBinders alt_env args
  229. \end{code}
  230. %************************************************************************
  231. %* *
  232. \section{The CSE envt}
  233. %* *
  234. %************************************************************************
  235. \begin{code}
  236. data CSEnv = CS CSEMap InScopeSet (IdEnv Id)
  237. -- Simple substitution
  238. type CSEMap = UniqFM [(CoreExpr, CoreExpr)] -- This is the reverse mapping
  239. -- It maps the hash-code of an expression e to list of (e,e') pairs
  240. -- This means that it's good to replace e by e'
  241. -- INVARIANT: The expr in the range has already been CSE'd
  242. emptyCSEnv :: CSEnv
  243. emptyCSEnv = CS emptyUFM emptyInScopeSet emptyVarEnv
  244. lookupCSEnv :: CSEnv -> CoreExpr -> Maybe CoreExpr
  245. lookupCSEnv (CS cs in_scope _) expr
  246. = case lookupUFM cs (hashExpr expr) of
  247. Nothing -> Nothing
  248. Just pairs -> lookup_list pairs
  249. where
  250. -- In this lookup we use full expression equality
  251. -- Reason: when expressions differ we generally find out quickly
  252. -- but I found that cheapEqExpr was saying (\x.x) /= (\y.y),
  253. -- and this kind of thing happened in real programs
  254. lookup_list :: [(CoreExpr,CoreExpr)] -> Maybe CoreExpr
  255. lookup_list [] = Nothing
  256. lookup_list ((e,e'):es) | eqExpr in_scope e expr = Just e'
  257. | otherwise = lookup_list es
  258. addCSEnvItem :: CSEnv -> CoreExpr -> CoreExpr -> CSEnv
  259. addCSEnvItem env expr expr' | exprIsBig expr = env
  260. | otherwise = extendCSEnv env expr expr'
  261. -- We don't try to CSE big expressions, because they are expensive to compare
  262. -- (and are unlikely to be the same anyway)
  263. extendCSEnv :: CSEnv -> CoreExpr -> CoreExpr -> CSEnv
  264. extendCSEnv (CS cs in_scope sub) expr expr'
  265. = CS (addToUFM_C combine cs hash [(expr, expr')]) in_scope sub
  266. where
  267. hash = hashExpr expr
  268. combine old new
  269. = WARN( result `lengthExceeds` 4, short_msg $$ nest 2 long_msg ) result
  270. where
  271. result = new ++ old
  272. short_msg = ptext (sLit "extendCSEnv: long list, length") <+> int (length result)
  273. long_msg | opt_PprStyle_Debug = (text "hash code" <+> text (show hash)) $$ ppr result
  274. | otherwise = empty
  275. lookupSubst :: CSEnv -> Id -> Id
  276. lookupSubst (CS _ _ sub) x = case lookupVarEnv sub x of
  277. Just y -> y
  278. Nothing -> x
  279. extendSubst :: CSEnv -> Id -> Id -> CSEnv
  280. extendSubst (CS cs in_scope sub) x y = CS cs in_scope (extendVarEnv sub x y)
  281. addBinder :: CSEnv -> Id -> (CSEnv, Id)
  282. addBinder (CS cs in_scope sub) v
  283. | not (v `elemInScopeSet` in_scope) = (CS cs (extendInScopeSet in_scope v) sub, v)
  284. | isId v = (CS cs (extendInScopeSet in_scope v') (extendVarEnv sub v v'), v')
  285. | otherwise = WARN( True, ppr v )
  286. (CS emptyUFM in_scope sub, v)
  287. -- This last case is the unusual situation where we have shadowing of
  288. -- a type variable; we have to discard the CSE mapping
  289. -- See Note [Shadowing]
  290. where
  291. v' = uniqAway in_scope v
  292. addBinders :: CSEnv -> [Id] -> (CSEnv, [Id])
  293. addBinders env vs = mapAccumL addBinder env vs
  294. \end{code}