PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://picorec.googlecode.com/
Haskell | 480 lines | 340 code | 95 blank | 45 comment | 21 complexity | 81ae57c6b1548a7afb32323a3abd988b MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. %
  2. % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
  3. %
  4. %************************************************************************
  5. %* *
  6. \section[FloatIn]{Floating Inwards pass}
  7. %* *
  8. %************************************************************************
  9. The main purpose of @floatInwards@ is floating into branches of a
  10. case, so that we don't allocate things, save them on the stack, and
  11. then discover that they aren't needed in the chosen branch.
  12. \begin{code}
  13. module FloatIn ( floatInwards ) where
  14. #include "HsVersions.h"
  15. import CoreSyn
  16. import CoreUtils ( exprIsHNF, exprIsDupable )
  17. import CoreFVs ( CoreExprWithFVs, freeVars, freeVarsOf, idRuleAndUnfoldingVars )
  18. import Id ( isOneShotBndr, idType )
  19. import Var
  20. import Type ( isUnLiftedType )
  21. import VarSet
  22. import Util ( zipEqual, zipWithEqual, count )
  23. import UniqFM
  24. import Outputable
  25. \end{code}
  26. Top-level interface function, @floatInwards@. Note that we do not
  27. actually float any bindings downwards from the top-level.
  28. \begin{code}
  29. floatInwards :: [CoreBind] -> [CoreBind]
  30. floatInwards = map fi_top_bind
  31. where
  32. fi_top_bind (NonRec binder rhs)
  33. = NonRec binder (fiExpr [] (freeVars rhs))
  34. fi_top_bind (Rec pairs)
  35. = Rec [ (b, fiExpr [] (freeVars rhs)) | (b, rhs) <- pairs ]
  36. \end{code}
  37. %************************************************************************
  38. %* *
  39. \subsection{Mail from Andr\'e [edited]}
  40. %* *
  41. %************************************************************************
  42. {\em Will wrote: What??? I thought the idea was to float as far
  43. inwards as possible, no matter what. This is dropping all bindings
  44. every time it sees a lambda of any kind. Help! }
  45. You are assuming we DO DO full laziness AFTER floating inwards! We
  46. have to [not float inside lambdas] if we don't.
  47. If we indeed do full laziness after the floating inwards (we could
  48. check the compilation flags for that) then I agree we could be more
  49. aggressive and do float inwards past lambdas.
  50. Actually we are not doing a proper full laziness (see below), which
  51. was another reason for not floating inwards past a lambda.
  52. This can easily be fixed. The problem is that we float lets outwards,
  53. but there are a few expressions which are not let bound, like case
  54. scrutinees and case alternatives. After floating inwards the
  55. simplifier could decide to inline the let and the laziness would be
  56. lost, e.g.
  57. \begin{verbatim}
  58. let a = expensive ==> \b -> case expensive of ...
  59. in \ b -> case a of ...
  60. \end{verbatim}
  61. The fix is
  62. \begin{enumerate}
  63. \item
  64. to let bind the algebraic case scrutinees (done, I think) and
  65. the case alternatives (except the ones with an
  66. unboxed type)(not done, I think). This is best done in the
  67. SetLevels.lhs module, which tags things with their level numbers.
  68. \item
  69. do the full laziness pass (floating lets outwards).
  70. \item
  71. simplify. The simplifier inlines the (trivial) lets that were
  72. created but were not floated outwards.
  73. \end{enumerate}
  74. With the fix I think Will's suggestion that we can gain even more from
  75. strictness by floating inwards past lambdas makes sense.
  76. We still gain even without going past lambdas, as things may be
  77. strict in the (new) context of a branch (where it was floated to) or
  78. of a let rhs, e.g.
  79. \begin{verbatim}
  80. let a = something case x of
  81. in case x of alt1 -> case something of a -> a + a
  82. alt1 -> a + a ==> alt2 -> b
  83. alt2 -> b
  84. let a = something let b = case something of a -> a + a
  85. in let b = a + a ==> in (b,b)
  86. in (b,b)
  87. \end{verbatim}
  88. Also, even if a is not found to be strict in the new context and is
  89. still left as a let, if the branch is not taken (or b is not entered)
  90. the closure for a is not built.
  91. %************************************************************************
  92. %* *
  93. \subsection{Main floating-inwards code}
  94. %* *
  95. %************************************************************************
  96. \begin{code}
  97. type FreeVarsSet = IdSet
  98. type FloatingBinds = [(CoreBind, FreeVarsSet)]
  99. -- In reverse dependency order (innermost binder first)
  100. -- The FreeVarsSet is the free variables of the binding. In the case
  101. -- of recursive bindings, the set doesn't include the bound
  102. -- variables.
  103. fiExpr :: FloatingBinds -- Binds we're trying to drop
  104. -- as far "inwards" as possible
  105. -> CoreExprWithFVs -- Input expr
  106. -> CoreExpr -- Result
  107. fiExpr to_drop (_, AnnVar v) = mkCoLets' to_drop (Var v)
  108. fiExpr to_drop (_, AnnType ty) = ASSERT( null to_drop )
  109. Type ty
  110. fiExpr to_drop (_, AnnCast expr co)
  111. = Cast (fiExpr to_drop expr) co -- Just float in past coercion
  112. fiExpr _ (_, AnnLit lit) = Lit lit
  113. \end{code}
  114. Applications: we do float inside applications, mainly because we
  115. need to get at all the arguments. The next simplifier run will
  116. pull out any silly ones.
  117. \begin{code}
  118. fiExpr to_drop (_,AnnApp fun arg)
  119. = mkCoLets' drop_here (App (fiExpr fun_drop fun) (fiExpr arg_drop arg))
  120. where
  121. [drop_here, fun_drop, arg_drop] = sepBindsByDropPoint False [freeVarsOf fun, freeVarsOf arg] to_drop
  122. \end{code}
  123. Note [Floating in past a lambda group]
  124. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  125. * We must be careful about floating inside inside a value lambda.
  126. That risks losing laziness.
  127. The float-out pass might rescue us, but then again it might not.
  128. * We must be careful about type lambdas too. At one time we did, and
  129. there is no risk of duplicating work thereby, but we do need to be
  130. careful. In particular, here is a bad case (it happened in the
  131. cichelli benchmark:
  132. let v = ...
  133. in let f = /\t -> \a -> ...
  134. ==>
  135. let f = /\t -> let v = ... in \a -> ...
  136. This is bad as now f is an updatable closure (update PAP)
  137. and has arity 0.
  138. * Hack alert! We only float in through one-shot lambdas,
  139. not (as you might guess) through lone big lambdas.
  140. Reason: we float *out* past big lambdas (see the test in the Lam
  141. case of FloatOut.floatExpr) and we don't want to float straight
  142. back in again.
  143. It *is* important to float into one-shot lambdas, however;
  144. see the remarks with noFloatIntoRhs.
  145. So we treat lambda in groups, using the following rule:
  146. Float in if (a) there is at least one Id,
  147. and (b) there are no non-one-shot Ids
  148. Otherwise drop all the bindings outside the group.
  149. This is what the 'go' function in the AnnLam case is doing.
  150. Urk! if all are tyvars, and we don't float in, we may miss an
  151. opportunity to float inside a nested case branch
  152. \begin{code}
  153. fiExpr to_drop lam@(_, AnnLam _ _)
  154. | go False bndrs -- Float in
  155. = mkLams bndrs (fiExpr to_drop body)
  156. | otherwise -- Dump it all here
  157. = mkCoLets' to_drop (mkLams bndrs (fiExpr [] body))
  158. where
  159. (bndrs, body) = collectAnnBndrs lam
  160. go seen_one_shot_id [] = seen_one_shot_id
  161. go seen_one_shot_id (b:bs)
  162. | isTyCoVar b = go seen_one_shot_id bs
  163. | isOneShotBndr b = go True bs
  164. | otherwise = False -- Give up at a non-one-shot Id
  165. \end{code}
  166. We don't float lets inwards past an SCC.
  167. ToDo: keep info on current cc, and when passing
  168. one, if it is not the same, annotate all lets in binds with current
  169. cc, change current cc to the new one and float binds into expr.
  170. \begin{code}
  171. fiExpr to_drop (_, AnnNote note@(SCC _) expr)
  172. = -- Wimp out for now
  173. mkCoLets' to_drop (Note note (fiExpr [] expr))
  174. fiExpr to_drop (_, AnnNote note@(CoreNote _) expr)
  175. = Note note (fiExpr to_drop expr)
  176. \end{code}
  177. For @Lets@, the possible ``drop points'' for the \tr{to_drop}
  178. bindings are: (a)~in the body, (b1)~in the RHS of a NonRec binding,
  179. or~(b2), in each of the RHSs of the pairs of a @Rec@.
  180. Note that we do {\em weird things} with this let's binding. Consider:
  181. \begin{verbatim}
  182. let
  183. w = ...
  184. in {
  185. let v = ... w ...
  186. in ... v .. w ...
  187. }
  188. \end{verbatim}
  189. Look at the inner \tr{let}. As \tr{w} is used in both the bind and
  190. body of the inner let, we could panic and leave \tr{w}'s binding where
  191. it is. But \tr{v} is floatable further into the body of the inner let, and
  192. {\em then} \tr{w} will also be only in the body of that inner let.
  193. So: rather than drop \tr{w}'s binding here, we add it onto the list of
  194. things to drop in the outer let's body, and let nature take its
  195. course.
  196. Note [extra_fvs (1): avoid floating into RHS]
  197. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  198. Consdider let x=\y....t... in body. We do not necessarily want to float
  199. a binding for t into the RHS, because it'll immediately be floated out
  200. again. (It won't go inside the lambda else we risk losing work.)
  201. In letrec, we need to be more careful still. We don't want to transform
  202. let x# = y# +# 1#
  203. in
  204. letrec f = \z. ...x#...f...
  205. in ...
  206. into
  207. letrec f = let x# = y# +# 1# in \z. ...x#...f... in ...
  208. because now we can't float the let out again, because a letrec
  209. can't have unboxed bindings.
  210. So we make "extra_fvs" which is the rhs_fvs of such bindings, and
  211. arrange to dump bindings that bind extra_fvs before the entire let.
  212. Note [extra_fvs (s): free variables of rules]
  213. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  214. Consider
  215. let x{rule mentioning y} = rhs in body
  216. Here y is not free in rhs or body; but we still want to dump bindings
  217. that bind y outside the let. So we augment extra_fvs with the
  218. idRuleAndUnfoldingVars of x. No need for type variables, hence not using
  219. idFreeVars.
  220. \begin{code}
  221. fiExpr to_drop (_,AnnLet (AnnNonRec id rhs@(rhs_fvs, ann_rhs)) body)
  222. = fiExpr new_to_drop body
  223. where
  224. body_fvs = freeVarsOf body
  225. rule_fvs = idRuleAndUnfoldingVars id -- See Note [extra_fvs (2): free variables of rules]
  226. extra_fvs | noFloatIntoRhs ann_rhs
  227. || isUnLiftedType (idType id) = rule_fvs `unionVarSet` rhs_fvs
  228. | otherwise = rule_fvs
  229. -- See Note [extra_fvs (2): avoid floating into RHS]
  230. -- No point in floating in only to float straight out again
  231. -- Ditto ok-for-speculation unlifted RHSs
  232. [shared_binds, extra_binds, rhs_binds, body_binds]
  233. = sepBindsByDropPoint False [extra_fvs, rhs_fvs, body_fvs] to_drop
  234. new_to_drop = body_binds ++ -- the bindings used only in the body
  235. [(NonRec id rhs', rhs_fvs')] ++ -- the new binding itself
  236. extra_binds ++ -- bindings from extra_fvs
  237. shared_binds -- the bindings used both in rhs and body
  238. -- Push rhs_binds into the right hand side of the binding
  239. rhs' = fiExpr rhs_binds rhs
  240. rhs_fvs' = rhs_fvs `unionVarSet` floatedBindsFVs rhs_binds `unionVarSet` rule_fvs
  241. -- Don't forget the rule_fvs; the binding mentions them!
  242. fiExpr to_drop (_,AnnLet (AnnRec bindings) body)
  243. = fiExpr new_to_drop body
  244. where
  245. (ids, rhss) = unzip bindings
  246. rhss_fvs = map freeVarsOf rhss
  247. body_fvs = freeVarsOf body
  248. -- See Note [extra_fvs (1,2)]
  249. rule_fvs = foldr (unionVarSet . idRuleAndUnfoldingVars) emptyVarSet ids
  250. extra_fvs = rule_fvs `unionVarSet`
  251. unionVarSets [ fvs | (fvs, rhs) <- rhss
  252. , noFloatIntoRhs rhs ]
  253. (shared_binds:extra_binds:body_binds:rhss_binds)
  254. = sepBindsByDropPoint False (extra_fvs:body_fvs:rhss_fvs) to_drop
  255. new_to_drop = body_binds ++ -- the bindings used only in the body
  256. [(Rec (fi_bind rhss_binds bindings), rhs_fvs')] ++
  257. -- The new binding itself
  258. extra_binds ++ -- Note [extra_fvs (1,2)]
  259. shared_binds -- Used in more than one place
  260. rhs_fvs' = unionVarSets rhss_fvs `unionVarSet`
  261. unionVarSets (map floatedBindsFVs rhss_binds) `unionVarSet`
  262. rule_fvs -- Don't forget the rule variables!
  263. -- Push rhs_binds into the right hand side of the binding
  264. fi_bind :: [FloatingBinds] -- one per "drop pt" conjured w/ fvs_of_rhss
  265. -> [(Id, CoreExprWithFVs)]
  266. -> [(Id, CoreExpr)]
  267. fi_bind to_drops pairs
  268. = [ (binder, fiExpr to_drop rhs)
  269. | ((binder, rhs), to_drop) <- zipEqual "fi_bind" pairs to_drops ]
  270. \end{code}
  271. For @Case@, the possible ``drop points'' for the \tr{to_drop}
  272. bindings are: (a)~inside the scrutinee, (b)~inside one of the
  273. alternatives/default [default FVs always {\em first}!].
  274. \begin{code}
  275. fiExpr to_drop (_, AnnCase scrut case_bndr ty alts)
  276. = mkCoLets' drop_here1 $
  277. mkCoLets' drop_here2 $
  278. Case (fiExpr scrut_drops scrut) case_bndr ty
  279. (zipWith fi_alt alts_drops_s alts)
  280. where
  281. -- Float into the scrut and alts-considered-together just like App
  282. [drop_here1, scrut_drops, alts_drops] = sepBindsByDropPoint False [scrut_fvs, all_alts_fvs] to_drop
  283. -- Float into the alts with the is_case flag set
  284. (drop_here2 : alts_drops_s) = sepBindsByDropPoint True alts_fvs alts_drops
  285. scrut_fvs = freeVarsOf scrut
  286. alts_fvs = map alt_fvs alts
  287. all_alts_fvs = unionVarSets alts_fvs
  288. alt_fvs (_con, args, rhs) = foldl delVarSet (freeVarsOf rhs) (case_bndr:args)
  289. -- Delete case_bndr and args from free vars of rhs
  290. -- to get free vars of alt
  291. fi_alt to_drop (con, args, rhs) = (con, args, fiExpr to_drop rhs)
  292. noFloatIntoRhs :: AnnExpr' Var (UniqFM Var) -> Bool
  293. noFloatIntoRhs (AnnLam b _) = not (is_one_shot b)
  294. -- IMPORTANT: don't say 'True' for a RHS with a one-shot lambda at the top.
  295. -- This makes a big difference for things like
  296. -- f x# = let x = I# x#
  297. -- in let j = \() -> ...x...
  298. -- in if <condition> then normal-path else j ()
  299. -- If x is used only in the error case join point, j, we must float the
  300. -- boxing constructor into it, else we box it every time which is very bad
  301. -- news indeed.
  302. noFloatIntoRhs rhs = exprIsHNF (deAnnotate' rhs) -- We'd just float right back out again...
  303. is_one_shot :: Var -> Bool
  304. is_one_shot b = isId b && isOneShotBndr b
  305. \end{code}
  306. %************************************************************************
  307. %* *
  308. \subsection{@sepBindsByDropPoint@}
  309. %* *
  310. %************************************************************************
  311. This is the crucial function. The idea is: We have a wad of bindings
  312. that we'd like to distribute inside a collection of {\em drop points};
  313. insides the alternatives of a \tr{case} would be one example of some
  314. drop points; the RHS and body of a non-recursive \tr{let} binding
  315. would be another (2-element) collection.
  316. So: We're given a list of sets-of-free-variables, one per drop point,
  317. and a list of floating-inwards bindings. If a binding can go into
  318. only one drop point (without suddenly making something out-of-scope),
  319. in it goes. If a binding is used inside {\em multiple} drop points,
  320. then it has to go in a you-must-drop-it-above-all-these-drop-points
  321. point.
  322. We have to maintain the order on these drop-point-related lists.
  323. \begin{code}
  324. sepBindsByDropPoint
  325. :: Bool -- True <=> is case expression
  326. -> [FreeVarsSet] -- One set of FVs per drop point
  327. -> FloatingBinds -- Candidate floaters
  328. -> [FloatingBinds] -- FIRST one is bindings which must not be floated
  329. -- inside any drop point; the rest correspond
  330. -- one-to-one with the input list of FV sets
  331. -- Every input floater is returned somewhere in the result;
  332. -- none are dropped, not even ones which don't seem to be
  333. -- free in *any* of the drop-point fvs. Why? Because, for example,
  334. -- a binding (let x = E in B) might have a specialised version of
  335. -- x (say x') stored inside x, but x' isn't free in E or B.
  336. type DropBox = (FreeVarsSet, FloatingBinds)
  337. sepBindsByDropPoint _is_case drop_pts []
  338. = [] : [[] | _ <- drop_pts] -- cut to the chase scene; it happens
  339. sepBindsByDropPoint is_case drop_pts floaters
  340. = go floaters (map (\fvs -> (fvs, [])) (emptyVarSet : drop_pts))
  341. where
  342. go :: FloatingBinds -> [DropBox] -> [FloatingBinds]
  343. -- The *first* one in the argument list is the drop_here set
  344. -- The FloatingBinds in the lists are in the reverse of
  345. -- the normal FloatingBinds order; that is, they are the right way round!
  346. go [] drop_boxes = map (reverse . snd) drop_boxes
  347. go (bind_w_fvs@(bind, bind_fvs) : binds) drop_boxes@(here_box : fork_boxes)
  348. = go binds new_boxes
  349. where
  350. -- "here" means the group of bindings dropped at the top of the fork
  351. (used_here : used_in_flags) = [ any (`elemVarSet` fvs) (bindersOf bind)
  352. | (fvs, _) <- drop_boxes]
  353. drop_here = used_here || not can_push
  354. -- For case expressions we duplicate the binding if it is
  355. -- reasonably small, and if it is not used in all the RHSs
  356. -- This is good for situations like
  357. -- let x = I# y in
  358. -- case e of
  359. -- C -> error x
  360. -- D -> error x
  361. -- E -> ...not mentioning x...
  362. n_alts = length used_in_flags
  363. n_used_alts = count id used_in_flags -- returns number of Trues in list.
  364. can_push = n_used_alts == 1 -- Used in just one branch
  365. || (is_case && -- We are looking at case alternatives
  366. n_used_alts > 1 && -- It's used in more than one
  367. n_used_alts < n_alts && -- ...but not all
  368. bindIsDupable bind) -- and we can duplicate the binding
  369. new_boxes | drop_here = (insert here_box : fork_boxes)
  370. | otherwise = (here_box : new_fork_boxes)
  371. new_fork_boxes = zipWithEqual "FloatIn.sepBinds" insert_maybe fork_boxes used_in_flags
  372. insert :: DropBox -> DropBox
  373. insert (fvs,drops) = (fvs `unionVarSet` bind_fvs, bind_w_fvs:drops)
  374. insert_maybe box True = insert box
  375. insert_maybe box False = box
  376. go _ _ = panic "sepBindsByDropPoint/go"
  377. floatedBindsFVs :: FloatingBinds -> FreeVarsSet
  378. floatedBindsFVs binds = unionVarSets (map snd binds)
  379. mkCoLets' :: FloatingBinds -> CoreExpr -> CoreExpr
  380. mkCoLets' to_drop e = foldl (flip (Let . fst)) e to_drop
  381. -- Remember to_drop is in *reverse* dependency order
  382. bindIsDupable :: Bind CoreBndr -> Bool
  383. bindIsDupable (Rec prs) = all (exprIsDupable . snd) prs
  384. bindIsDupable (NonRec _ r) = exprIsDupable r
  385. \end{code}