PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/coreSyn/CoreTidy.hs

http://github.com/ghc/ghc
Haskell | 275 lines | 141 code | 30 blank | 104 comment | 0 complexity | e097cd5979ad8b5ca7ffc50c8b45b0b2 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. {-
  2. (c) The University of Glasgow 2006
  3. (c) The AQUA Project, Glasgow University, 1996-1998
  4. This module contains "tidying" code for *nested* expressions, bindings, rules.
  5. The code for *top-level* bindings is in TidyPgm.
  6. -}
  7. {-# LANGUAGE CPP #-}
  8. module CoreTidy (
  9. tidyExpr, tidyVarOcc, tidyRule, tidyRules, tidyUnfolding
  10. ) where
  11. #include "HsVersions.h"
  12. import CoreSyn
  13. import CoreArity
  14. import Id
  15. import IdInfo
  16. import Demand ( zapUsageEnvSig )
  17. import Type( tidyType, tidyTyCoVarBndr )
  18. import Coercion( tidyCo )
  19. import Var
  20. import VarEnv
  21. import UniqFM
  22. import Name hiding (tidyNameOcc)
  23. import SrcLoc
  24. import Maybes
  25. import Data.List
  26. {-
  27. ************************************************************************
  28. * *
  29. \subsection{Tidying expressions, rules}
  30. * *
  31. ************************************************************************
  32. -}
  33. tidyBind :: TidyEnv
  34. -> CoreBind
  35. -> (TidyEnv, CoreBind)
  36. tidyBind env (NonRec bndr rhs)
  37. = tidyLetBndr env env (bndr,rhs) =: \ (env', bndr') ->
  38. (env', NonRec bndr' (tidyExpr env' rhs))
  39. tidyBind env (Rec prs)
  40. = let
  41. (env', bndrs') = mapAccumL (tidyLetBndr env') env prs
  42. in
  43. map (tidyExpr env') (map snd prs) =: \ rhss' ->
  44. (env', Rec (zip bndrs' rhss'))
  45. ------------ Expressions --------------
  46. tidyExpr :: TidyEnv -> CoreExpr -> CoreExpr
  47. tidyExpr env (Var v) = Var (tidyVarOcc env v)
  48. tidyExpr env (Type ty) = Type (tidyType env ty)
  49. tidyExpr env (Coercion co) = Coercion (tidyCo env co)
  50. tidyExpr _ (Lit lit) = Lit lit
  51. tidyExpr env (App f a) = App (tidyExpr env f) (tidyExpr env a)
  52. tidyExpr env (Tick t e) = Tick (tidyTickish env t) (tidyExpr env e)
  53. tidyExpr env (Cast e co) = Cast (tidyExpr env e) (tidyCo env co)
  54. tidyExpr env (Let b e)
  55. = tidyBind env b =: \ (env', b') ->
  56. Let b' (tidyExpr env' e)
  57. tidyExpr env (Case e b ty alts)
  58. = tidyBndr env b =: \ (env', b) ->
  59. Case (tidyExpr env e) b (tidyType env ty)
  60. (map (tidyAlt b env') alts)
  61. tidyExpr env (Lam b e)
  62. = tidyBndr env b =: \ (env', b) ->
  63. Lam b (tidyExpr env' e)
  64. ------------ Case alternatives --------------
  65. tidyAlt :: CoreBndr -> TidyEnv -> CoreAlt -> CoreAlt
  66. tidyAlt _case_bndr env (con, vs, rhs)
  67. = tidyBndrs env vs =: \ (env', vs) ->
  68. (con, vs, tidyExpr env' rhs)
  69. ------------ Tickish --------------
  70. tidyTickish :: TidyEnv -> Tickish Id -> Tickish Id
  71. tidyTickish env (Breakpoint ix ids) = Breakpoint ix (map (tidyVarOcc env) ids)
  72. tidyTickish _ other_tickish = other_tickish
  73. ------------ Rules --------------
  74. tidyRules :: TidyEnv -> [CoreRule] -> [CoreRule]
  75. tidyRules _ [] = []
  76. tidyRules env (rule : rules)
  77. = tidyRule env rule =: \ rule ->
  78. tidyRules env rules =: \ rules ->
  79. (rule : rules)
  80. tidyRule :: TidyEnv -> CoreRule -> CoreRule
  81. tidyRule _ rule@(BuiltinRule {}) = rule
  82. tidyRule env rule@(Rule { ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs,
  83. ru_fn = fn, ru_rough = mb_ns })
  84. = tidyBndrs env bndrs =: \ (env', bndrs) ->
  85. map (tidyExpr env') args =: \ args ->
  86. rule { ru_bndrs = bndrs, ru_args = args,
  87. ru_rhs = tidyExpr env' rhs,
  88. ru_fn = tidyNameOcc env fn,
  89. ru_rough = map (fmap (tidyNameOcc env')) mb_ns }
  90. {-
  91. ************************************************************************
  92. * *
  93. \subsection{Tidying non-top-level binders}
  94. * *
  95. ************************************************************************
  96. -}
  97. tidyNameOcc :: TidyEnv -> Name -> Name
  98. -- In rules and instances, we have Names, and we must tidy them too
  99. -- Fortunately, we can lookup in the VarEnv with a name
  100. tidyNameOcc (_, var_env) n = case lookupUFM var_env n of
  101. Nothing -> n
  102. Just v -> idName v
  103. tidyVarOcc :: TidyEnv -> Var -> Var
  104. tidyVarOcc (_, var_env) v = lookupVarEnv var_env v `orElse` v
  105. -- tidyBndr is used for lambda and case binders
  106. tidyBndr :: TidyEnv -> Var -> (TidyEnv, Var)
  107. tidyBndr env var
  108. | isTyCoVar var = tidyTyCoVarBndr env var
  109. | otherwise = tidyIdBndr env var
  110. tidyBndrs :: TidyEnv -> [Var] -> (TidyEnv, [Var])
  111. tidyBndrs env vars = mapAccumL tidyBndr env vars
  112. -- Non-top-level variables, not covars
  113. tidyIdBndr :: TidyEnv -> Id -> (TidyEnv, Id)
  114. tidyIdBndr env@(tidy_env, var_env) id
  115. = -- Do this pattern match strictly, otherwise we end up holding on to
  116. -- stuff in the OccName.
  117. case tidyOccName tidy_env (getOccName id) of { (tidy_env', occ') ->
  118. let
  119. -- Give the Id a fresh print-name, *and* rename its type
  120. -- The SrcLoc isn't important now,
  121. -- though we could extract it from the Id
  122. --
  123. ty' = tidyType env (idType id)
  124. name' = mkInternalName (idUnique id) occ' noSrcSpan
  125. id' = mkLocalIdWithInfo name' ty' new_info
  126. var_env' = extendVarEnv var_env id id'
  127. -- Note [Tidy IdInfo]
  128. new_info = vanillaIdInfo `setOccInfo` occInfo old_info
  129. `setUnfoldingInfo` new_unf
  130. -- see Note [Preserve OneShotInfo]
  131. `setOneShotInfo` oneShotInfo old_info
  132. old_info = idInfo id
  133. old_unf = unfoldingInfo old_info
  134. new_unf | isEvaldUnfolding old_unf = evaldUnfolding
  135. | otherwise = noUnfolding
  136. -- See Note [Preserve evaluatedness]
  137. in
  138. ((tidy_env', var_env'), id')
  139. }
  140. tidyLetBndr :: TidyEnv -- Knot-tied version for unfoldings
  141. -> TidyEnv -- The one to extend
  142. -> (Id, CoreExpr) -> (TidyEnv, Var)
  143. -- Used for local (non-top-level) let(rec)s
  144. -- Just like tidyIdBndr above, but with more IdInfo
  145. tidyLetBndr rec_tidy_env env@(tidy_env, var_env) (id,rhs)
  146. = case tidyOccName tidy_env (getOccName id) of { (tidy_env', occ') ->
  147. let
  148. ty' = tidyType env (idType id)
  149. name' = mkInternalName (idUnique id) occ' noSrcSpan
  150. details = idDetails id
  151. id' = mkLocalVar details name' ty' new_info
  152. var_env' = extendVarEnv var_env id id'
  153. -- Note [Tidy IdInfo]
  154. -- We need to keep around any interesting strictness and
  155. -- demand info because later on we may need to use it when
  156. -- converting to A-normal form.
  157. -- eg.
  158. -- f (g x), where f is strict in its argument, will be converted
  159. -- into case (g x) of z -> f z by CorePrep, but only if f still
  160. -- has its strictness info.
  161. --
  162. -- Similarly for the demand info - on a let binder, this tells
  163. -- CorePrep to turn the let into a case.
  164. -- But: Remove the usage demand here
  165. -- (See Note [Zapping DmdEnv after Demand Analyzer] in WorkWrap)
  166. --
  167. -- Similarly arity info for eta expansion in CorePrep
  168. --
  169. -- Set inline-prag info so that we preseve it across
  170. -- separate compilation boundaries
  171. old_info = idInfo id
  172. new_info = vanillaIdInfo
  173. `setOccInfo` occInfo old_info
  174. `setArityInfo` exprArity rhs
  175. `setStrictnessInfo` zapUsageEnvSig (strictnessInfo old_info)
  176. `setDemandInfo` demandInfo old_info
  177. `setInlinePragInfo` inlinePragInfo old_info
  178. `setUnfoldingInfo` new_unf
  179. new_unf | isStableUnfolding old_unf = tidyUnfolding rec_tidy_env old_unf old_unf
  180. | otherwise = noUnfolding
  181. old_unf = unfoldingInfo old_info
  182. in
  183. ((tidy_env', var_env'), id') }
  184. ------------ Unfolding --------------
  185. tidyUnfolding :: TidyEnv -> Unfolding -> Unfolding -> Unfolding
  186. tidyUnfolding tidy_env df@(DFunUnfolding { df_bndrs = bndrs, df_args = args }) _
  187. = df { df_bndrs = bndrs', df_args = map (tidyExpr tidy_env') args }
  188. where
  189. (tidy_env', bndrs') = tidyBndrs tidy_env bndrs
  190. tidyUnfolding tidy_env
  191. unf@(CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src })
  192. unf_from_rhs
  193. | isStableSource src
  194. = unf { uf_tmpl = tidyExpr tidy_env unf_rhs } -- Preserves OccInfo
  195. | otherwise
  196. = unf_from_rhs
  197. tidyUnfolding _ unf _ = unf -- NoUnfolding or OtherCon
  198. {-
  199. Note [Tidy IdInfo]
  200. ~~~~~~~~~~~~~~~~~~
  201. All nested Ids now have the same IdInfo, namely vanillaIdInfo, which
  202. should save some space; except that we preserve occurrence info for
  203. two reasons:
  204. (a) To make printing tidy core nicer
  205. (b) Because we tidy RULES and InlineRules, which may then propagate
  206. via --make into the compilation of the next module, and we want
  207. the benefit of that occurrence analysis when we use the rule or
  208. or inline the function. In particular, it's vital not to lose
  209. loop-breaker info, else we get an infinite inlining loop
  210. Note that tidyLetBndr puts more IdInfo back.
  211. Note [Preserve evaluatedness]
  212. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  213. Consider
  214. data T = MkT !Bool
  215. ....(case v of MkT y ->
  216. let z# = case y of
  217. True -> 1#
  218. False -> 2#
  219. in ...)
  220. The z# binding is ok because the RHS is ok-for-speculation,
  221. but Lint will complain unless it can *see* that. So we
  222. preserve the evaluated-ness on 'y' in tidyBndr.
  223. (Another alternative would be to tidy unboxed lets into cases,
  224. but that seems more indirect and surprising.)
  225. Note [Preserve OneShotInfo]
  226. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  227. We keep the OneShotInfo because we want it to propagate into the interface.
  228. Not all OneShotInfo is determined by a compiler analysis; some is added by a
  229. call of GHC.Exts.oneShot, which is then discarded before the end of the
  230. optimisation pipeline, leaving only the OneShotInfo on the lambda. Hence we
  231. must preserve this info in inlinings. See Note [The oneShot function] in MkId.
  232. This applies to lambda binders only, hence it is stored in IfaceLamBndr.
  233. -}
  234. (=:) :: a -> (a -> b) -> b
  235. m =: k = m `seq` k m