PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/simplCore/CSE.lhs

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