| 1 | % |
|---|
| 2 | % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998 |
|---|
| 3 | % |
|---|
| 4 | \section[CoreToStg]{Converts Core to STG Syntax} |
|---|
| 5 | |
|---|
| 6 | And, as we have the info in hand, we may convert some lets to |
|---|
| 7 | let-no-escapes. |
|---|
| 8 | |
|---|
| 9 | \begin{code} |
|---|
| 10 | {-# OPTIONS -fno-warn-tabs #-} |
|---|
| 11 | -- The above warning supression flag is a temporary kludge. |
|---|
| 12 | -- While working on this module you are encouraged to remove it and |
|---|
| 13 | -- detab the module (please do the detabbing in a separate patch). See |
|---|
| 14 | -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces |
|---|
| 15 | -- for details |
|---|
| 16 | |
|---|
| 17 | module CoreToStg ( coreToStg, coreExprToStg ) where |
|---|
| 18 | |
|---|
| 19 | #include "HsVersions.h" |
|---|
| 20 | |
|---|
| 21 | import CoreSyn |
|---|
| 22 | import CoreUtils ( exprType, findDefault ) |
|---|
| 23 | import CoreArity ( manifestArity ) |
|---|
| 24 | import StgSyn |
|---|
| 25 | |
|---|
| 26 | import Type |
|---|
| 27 | import TyCon |
|---|
| 28 | import MkId ( coercionTokenId ) |
|---|
| 29 | import Id |
|---|
| 30 | import IdInfo |
|---|
| 31 | import DataCon |
|---|
| 32 | import CostCentre ( noCCS ) |
|---|
| 33 | import VarSet |
|---|
| 34 | import VarEnv |
|---|
| 35 | import Maybes ( maybeToBool ) |
|---|
| 36 | import Name ( getOccName, isExternalName, nameOccName ) |
|---|
| 37 | import OccName ( occNameString, occNameFS ) |
|---|
| 38 | import BasicTypes ( Arity ) |
|---|
| 39 | import Literal |
|---|
| 40 | import Outputable |
|---|
| 41 | import MonadUtils |
|---|
| 42 | import FastString |
|---|
| 43 | import Util |
|---|
| 44 | import DynFlags |
|---|
| 45 | import ForeignCall |
|---|
| 46 | import PrimOp ( PrimCall(..) ) |
|---|
| 47 | \end{code} |
|---|
| 48 | |
|---|
| 49 | %************************************************************************ |
|---|
| 50 | %* * |
|---|
| 51 | \subsection[live-vs-free-doc]{Documentation} |
|---|
| 52 | %* * |
|---|
| 53 | %************************************************************************ |
|---|
| 54 | |
|---|
| 55 | (There is other relevant documentation in codeGen/CgLetNoEscape.) |
|---|
| 56 | |
|---|
| 57 | The actual Stg datatype is decorated with {\em live variable} |
|---|
| 58 | information, as well as {\em free variable} information. The two are |
|---|
| 59 | {\em not} the same. Liveness is an operational property rather than a |
|---|
| 60 | semantic one. A variable is live at a particular execution point if |
|---|
| 61 | it can be referred to {\em directly} again. In particular, a dead |
|---|
| 62 | variable's stack slot (if it has one): |
|---|
| 63 | \begin{enumerate} |
|---|
| 64 | \item |
|---|
| 65 | should be stubbed to avoid space leaks, and |
|---|
| 66 | \item |
|---|
| 67 | may be reused for something else. |
|---|
| 68 | \end{enumerate} |
|---|
| 69 | |
|---|
| 70 | There ought to be a better way to say this. Here are some examples: |
|---|
| 71 | \begin{verbatim} |
|---|
| 72 | let v = [q] \[x] -> e |
|---|
| 73 | in |
|---|
| 74 | ...v... (but no q's) |
|---|
| 75 | \end{verbatim} |
|---|
| 76 | |
|---|
| 77 | Just after the `in', v is live, but q is dead. If the whole of that |
|---|
| 78 | let expression was enclosed in a case expression, thus: |
|---|
| 79 | \begin{verbatim} |
|---|
| 80 | case (let v = [q] \[x] -> e in ...v...) of |
|---|
| 81 | alts[...q...] |
|---|
| 82 | \end{verbatim} |
|---|
| 83 | (ie @alts@ mention @q@), then @q@ is live even after the `in'; because |
|---|
| 84 | we'll return later to the @alts@ and need it. |
|---|
| 85 | |
|---|
| 86 | Let-no-escapes make this a bit more interesting: |
|---|
| 87 | \begin{verbatim} |
|---|
| 88 | let-no-escape v = [q] \ [x] -> e |
|---|
| 89 | in |
|---|
| 90 | ...v... |
|---|
| 91 | \end{verbatim} |
|---|
| 92 | Here, @q@ is still live at the `in', because @v@ is represented not by |
|---|
| 93 | a closure but by the current stack state. In other words, if @v@ is |
|---|
| 94 | live then so is @q@. Furthermore, if @e@ mentions an enclosing |
|---|
| 95 | let-no-escaped variable, then {\em its} free variables are also live |
|---|
| 96 | if @v@ is. |
|---|
| 97 | |
|---|
| 98 | %************************************************************************ |
|---|
| 99 | %* * |
|---|
| 100 | \subsection[caf-info]{Collecting live CAF info} |
|---|
| 101 | %* * |
|---|
| 102 | %************************************************************************ |
|---|
| 103 | |
|---|
| 104 | In this pass we also collect information on which CAFs are live for |
|---|
| 105 | constructing SRTs (see SRT.lhs). |
|---|
| 106 | |
|---|
| 107 | A top-level Id has CafInfo, which is |
|---|
| 108 | |
|---|
| 109 | - MayHaveCafRefs, if it may refer indirectly to |
|---|
| 110 | one or more CAFs, or |
|---|
| 111 | - NoCafRefs if it definitely doesn't |
|---|
| 112 | |
|---|
| 113 | The CafInfo has already been calculated during the CoreTidy pass. |
|---|
| 114 | |
|---|
| 115 | During CoreToStg, we then pin onto each binding and case expression, a |
|---|
| 116 | list of Ids which represents the "live" CAFs at that point. The meaning |
|---|
| 117 | of "live" here is the same as for live variables, see above (which is |
|---|
| 118 | why it's convenient to collect CAF information here rather than elsewhere). |
|---|
| 119 | |
|---|
| 120 | The later SRT pass takes these lists of Ids and uses them to construct |
|---|
| 121 | the actual nested SRTs, and replaces the lists of Ids with (offset,length) |
|---|
| 122 | pairs. |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | Interaction of let-no-escape with SRTs [Sept 01] |
|---|
| 126 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 127 | Consider |
|---|
| 128 | |
|---|
| 129 | let-no-escape x = ...caf1...caf2... |
|---|
| 130 | in |
|---|
| 131 | ...x...x...x... |
|---|
| 132 | |
|---|
| 133 | where caf1,caf2 are CAFs. Since x doesn't have a closure, we |
|---|
| 134 | build SRTs just as if x's defn was inlined at each call site, and |
|---|
| 135 | that means that x's CAF refs get duplicated in the overall SRT. |
|---|
| 136 | |
|---|
| 137 | This is unlike ordinary lets, in which the CAF refs are not duplicated. |
|---|
| 138 | |
|---|
| 139 | We could fix this loss of (static) sharing by making a sort of pseudo-closure |
|---|
| 140 | for x, solely to put in the SRTs lower down. |
|---|
| 141 | |
|---|
| 142 | |
|---|
| 143 | %************************************************************************ |
|---|
| 144 | %* * |
|---|
| 145 | \subsection[binds-StgVarInfo]{Setting variable info: top-level, binds, RHSs} |
|---|
| 146 | %* * |
|---|
| 147 | %************************************************************************ |
|---|
| 148 | |
|---|
| 149 | \begin{code} |
|---|
| 150 | coreToStg :: DynFlags -> CoreProgram -> IO [StgBinding] |
|---|
| 151 | coreToStg dflags pgm |
|---|
| 152 | = return pgm' |
|---|
| 153 | where (_, _, pgm') = coreTopBindsToStg dflags emptyVarEnv pgm |
|---|
| 154 | |
|---|
| 155 | coreExprToStg :: CoreExpr -> StgExpr |
|---|
| 156 | coreExprToStg expr |
|---|
| 157 | = new_expr where (new_expr,_,_) = initLne emptyVarEnv (coreToStgExpr expr) |
|---|
| 158 | |
|---|
| 159 | |
|---|
| 160 | coreTopBindsToStg |
|---|
| 161 | :: DynFlags |
|---|
| 162 | -> IdEnv HowBound -- environment for the bindings |
|---|
| 163 | -> CoreProgram |
|---|
| 164 | -> (IdEnv HowBound, FreeVarsInfo, [StgBinding]) |
|---|
| 165 | |
|---|
| 166 | coreTopBindsToStg _ env [] = (env, emptyFVInfo, []) |
|---|
| 167 | coreTopBindsToStg dflags env (b:bs) |
|---|
| 168 | = (env2, fvs2, b':bs') |
|---|
| 169 | where |
|---|
| 170 | -- Notice the mutually-recursive "knot" here: |
|---|
| 171 | -- env accumulates down the list of binds, |
|---|
| 172 | -- fvs accumulates upwards |
|---|
| 173 | (env1, fvs2, b' ) = coreTopBindToStg dflags env fvs1 b |
|---|
| 174 | (env2, fvs1, bs') = coreTopBindsToStg dflags env1 bs |
|---|
| 175 | |
|---|
| 176 | coreTopBindToStg |
|---|
| 177 | :: DynFlags |
|---|
| 178 | -> IdEnv HowBound |
|---|
| 179 | -> FreeVarsInfo -- Info about the body |
|---|
| 180 | -> CoreBind |
|---|
| 181 | -> (IdEnv HowBound, FreeVarsInfo, StgBinding) |
|---|
| 182 | |
|---|
| 183 | coreTopBindToStg dflags env body_fvs (NonRec id rhs) |
|---|
| 184 | = let |
|---|
| 185 | env' = extendVarEnv env id how_bound |
|---|
| 186 | how_bound = LetBound TopLet $! manifestArity rhs |
|---|
| 187 | |
|---|
| 188 | (stg_rhs, fvs') = |
|---|
| 189 | initLne env $ do |
|---|
| 190 | (stg_rhs, fvs') <- coreToTopStgRhs dflags body_fvs (id,rhs) |
|---|
| 191 | return (stg_rhs, fvs') |
|---|
| 192 | |
|---|
| 193 | bind = StgNonRec id stg_rhs |
|---|
| 194 | in |
|---|
| 195 | ASSERT2(consistentCafInfo id bind, ppr id ) |
|---|
| 196 | -- NB: previously the assertion printed 'rhs' and 'bind' |
|---|
| 197 | -- as well as 'id', but that led to a black hole |
|---|
| 198 | -- where printing the assertion error tripped the |
|---|
| 199 | -- assertion again! |
|---|
| 200 | (env', fvs' `unionFVInfo` body_fvs, bind) |
|---|
| 201 | |
|---|
| 202 | coreTopBindToStg dflags env body_fvs (Rec pairs) |
|---|
| 203 | = ASSERT( not (null pairs) ) |
|---|
| 204 | let |
|---|
| 205 | binders = map fst pairs |
|---|
| 206 | |
|---|
| 207 | extra_env' = [ (b, LetBound TopLet $! manifestArity rhs) |
|---|
| 208 | | (b, rhs) <- pairs ] |
|---|
| 209 | env' = extendVarEnvList env extra_env' |
|---|
| 210 | |
|---|
| 211 | (stg_rhss, fvs') |
|---|
| 212 | = initLne env' $ do |
|---|
| 213 | (stg_rhss, fvss') <- mapAndUnzipM (coreToTopStgRhs dflags body_fvs) pairs |
|---|
| 214 | let fvs' = unionFVInfos fvss' |
|---|
| 215 | return (stg_rhss, fvs') |
|---|
| 216 | |
|---|
| 217 | bind = StgRec (zip binders stg_rhss) |
|---|
| 218 | in |
|---|
| 219 | ASSERT2(consistentCafInfo (head binders) bind, ppr binders) |
|---|
| 220 | (env', fvs' `unionFVInfo` body_fvs, bind) |
|---|
| 221 | |
|---|
| 222 | |
|---|
| 223 | -- Assertion helper: this checks that the CafInfo on the Id matches |
|---|
| 224 | -- what CoreToStg has figured out about the binding's SRT. The |
|---|
| 225 | -- CafInfo will be exact in all cases except when CorePrep has |
|---|
| 226 | -- floated out a binding, in which case it will be approximate. |
|---|
| 227 | consistentCafInfo :: Id -> GenStgBinding Var Id -> Bool |
|---|
| 228 | consistentCafInfo id bind |
|---|
| 229 | = WARN( not (exact || is_sat_thing) , ppr id <+> ppr id_marked_caffy <+> ppr binding_is_caffy ) |
|---|
| 230 | safe |
|---|
| 231 | where |
|---|
| 232 | safe = id_marked_caffy || not binding_is_caffy |
|---|
| 233 | exact = id_marked_caffy == binding_is_caffy |
|---|
| 234 | id_marked_caffy = mayHaveCafRefs (idCafInfo id) |
|---|
| 235 | binding_is_caffy = stgBindHasCafRefs bind |
|---|
| 236 | is_sat_thing = occNameFS (nameOccName (idName id)) == fsLit "sat" |
|---|
| 237 | \end{code} |
|---|
| 238 | |
|---|
| 239 | \begin{code} |
|---|
| 240 | coreToTopStgRhs |
|---|
| 241 | :: DynFlags |
|---|
| 242 | -> FreeVarsInfo -- Free var info for the scope of the binding |
|---|
| 243 | -> (Id,CoreExpr) |
|---|
| 244 | -> LneM (StgRhs, FreeVarsInfo) |
|---|
| 245 | |
|---|
| 246 | coreToTopStgRhs dflags scope_fv_info (bndr, rhs) |
|---|
| 247 | = do { (new_rhs, rhs_fvs, _) <- coreToStgExpr rhs |
|---|
| 248 | ; lv_info <- freeVarsToLiveVars rhs_fvs |
|---|
| 249 | |
|---|
| 250 | ; let stg_rhs = mkTopStgRhs dflags rhs_fvs (mkSRT lv_info) bndr_info new_rhs |
|---|
| 251 | stg_arity = stgRhsArity stg_rhs |
|---|
| 252 | ; return (ASSERT2( arity_ok stg_arity, mk_arity_msg stg_arity) stg_rhs, |
|---|
| 253 | rhs_fvs) } |
|---|
| 254 | where |
|---|
| 255 | bndr_info = lookupFVInfo scope_fv_info bndr |
|---|
| 256 | |
|---|
| 257 | -- It's vital that the arity on a top-level Id matches |
|---|
| 258 | -- the arity of the generated STG binding, else an importing |
|---|
| 259 | -- module will use the wrong calling convention |
|---|
| 260 | -- (Trac #2844 was an example where this happened) |
|---|
| 261 | -- NB1: we can't move the assertion further out without |
|---|
| 262 | -- blocking the "knot" tied in coreTopBindsToStg |
|---|
| 263 | -- NB2: the arity check is only needed for Ids with External |
|---|
| 264 | -- Names, because they are externally visible. The CorePrep |
|---|
| 265 | -- pass introduces "sat" things with Local Names and does |
|---|
| 266 | -- not bother to set their Arity info, so don't fail for those |
|---|
| 267 | arity_ok stg_arity |
|---|
| 268 | | isExternalName (idName bndr) = id_arity == stg_arity |
|---|
| 269 | | otherwise = True |
|---|
| 270 | id_arity = idArity bndr |
|---|
| 271 | mk_arity_msg stg_arity |
|---|
| 272 | = vcat [ppr bndr, |
|---|
| 273 | ptext (sLit "Id arity:") <+> ppr id_arity, |
|---|
| 274 | ptext (sLit "STG arity:") <+> ppr stg_arity] |
|---|
| 275 | |
|---|
| 276 | mkTopStgRhs :: DynFlags -> FreeVarsInfo |
|---|
| 277 | -> SRT -> StgBinderInfo -> StgExpr |
|---|
| 278 | -> StgRhs |
|---|
| 279 | |
|---|
| 280 | mkTopStgRhs _ rhs_fvs srt binder_info (StgLam _ bndrs body) |
|---|
| 281 | = StgRhsClosure noCCS binder_info |
|---|
| 282 | (getFVs rhs_fvs) |
|---|
| 283 | ReEntrant |
|---|
| 284 | srt |
|---|
| 285 | bndrs body |
|---|
| 286 | |
|---|
| 287 | mkTopStgRhs dflags _ _ _ (StgConApp con args) |
|---|
| 288 | | not (isDllConApp dflags con args) -- Dynamic StgConApps are updatable |
|---|
| 289 | = StgRhsCon noCCS con args |
|---|
| 290 | |
|---|
| 291 | mkTopStgRhs _ rhs_fvs srt binder_info rhs |
|---|
| 292 | = StgRhsClosure noCCS binder_info |
|---|
| 293 | (getFVs rhs_fvs) |
|---|
| 294 | Updatable |
|---|
| 295 | srt |
|---|
| 296 | [] rhs |
|---|
| 297 | \end{code} |
|---|
| 298 | |
|---|
| 299 | |
|---|
| 300 | -- --------------------------------------------------------------------------- |
|---|
| 301 | -- Expressions |
|---|
| 302 | -- --------------------------------------------------------------------------- |
|---|
| 303 | |
|---|
| 304 | \begin{code} |
|---|
| 305 | coreToStgExpr |
|---|
| 306 | :: CoreExpr |
|---|
| 307 | -> LneM (StgExpr, -- Decorated STG expr |
|---|
| 308 | FreeVarsInfo, -- Its free vars (NB free, not live) |
|---|
| 309 | EscVarsSet) -- Its escapees, a subset of its free vars; |
|---|
| 310 | -- also a subset of the domain of the envt |
|---|
| 311 | -- because we are only interested in the escapees |
|---|
| 312 | -- for vars which might be turned into |
|---|
| 313 | -- let-no-escaped ones. |
|---|
| 314 | \end{code} |
|---|
| 315 | |
|---|
| 316 | The second and third components can be derived in a simple bottom up pass, not |
|---|
| 317 | dependent on any decisions about which variables will be let-no-escaped or |
|---|
| 318 | not. The first component, that is, the decorated expression, may then depend |
|---|
| 319 | on these components, but it in turn is not scrutinised as the basis for any |
|---|
| 320 | decisions. Hence no black holes. |
|---|
| 321 | |
|---|
| 322 | \begin{code} |
|---|
| 323 | -- No LitInteger's should be left by the time this is called. CorePrep |
|---|
| 324 | -- should have converted them all to a real core representation. |
|---|
| 325 | coreToStgExpr (Lit (LitInteger {})) = panic "coreToStgExpr: LitInteger" |
|---|
| 326 | coreToStgExpr (Lit l) = return (StgLit l, emptyFVInfo, emptyVarSet) |
|---|
| 327 | coreToStgExpr (Var v) = coreToStgApp Nothing v [] |
|---|
| 328 | coreToStgExpr (Coercion _) = coreToStgApp Nothing coercionTokenId [] |
|---|
| 329 | |
|---|
| 330 | coreToStgExpr expr@(App _ _) |
|---|
| 331 | = coreToStgApp Nothing f args |
|---|
| 332 | where |
|---|
| 333 | (f, args) = myCollectArgs expr |
|---|
| 334 | |
|---|
| 335 | coreToStgExpr expr@(Lam _ _) |
|---|
| 336 | = let |
|---|
| 337 | (args, body) = myCollectBinders expr |
|---|
| 338 | args' = filterStgBinders args |
|---|
| 339 | in |
|---|
| 340 | extendVarEnvLne [ (a, LambdaBound) | a <- args' ] $ do |
|---|
| 341 | (body, body_fvs, body_escs) <- coreToStgExpr body |
|---|
| 342 | let |
|---|
| 343 | fvs = args' `minusFVBinders` body_fvs |
|---|
| 344 | escs = body_escs `delVarSetList` args' |
|---|
| 345 | result_expr | null args' = body |
|---|
| 346 | | otherwise = StgLam (exprType expr) args' body |
|---|
| 347 | |
|---|
| 348 | return (result_expr, fvs, escs) |
|---|
| 349 | |
|---|
| 350 | coreToStgExpr (Tick (HpcTick m n) expr) |
|---|
| 351 | = do (expr2, fvs, escs) <- coreToStgExpr expr |
|---|
| 352 | return (StgTick m n expr2, fvs, escs) |
|---|
| 353 | |
|---|
| 354 | coreToStgExpr (Tick (ProfNote cc tick push) expr) |
|---|
| 355 | = do (expr2, fvs, escs) <- coreToStgExpr expr |
|---|
| 356 | return (StgSCC cc tick push expr2, fvs, escs) |
|---|
| 357 | |
|---|
| 358 | coreToStgExpr (Tick Breakpoint{} _expr) |
|---|
| 359 | = panic "coreToStgExpr: breakpoint should not happen" |
|---|
| 360 | |
|---|
| 361 | coreToStgExpr (Cast expr _) |
|---|
| 362 | = coreToStgExpr expr |
|---|
| 363 | |
|---|
| 364 | -- Cases require a little more real work. |
|---|
| 365 | |
|---|
| 366 | coreToStgExpr (Case scrut _ _ []) |
|---|
| 367 | = coreToStgExpr scrut |
|---|
| 368 | -- See Note [Empty case alternatives] in CoreSyn If the case |
|---|
| 369 | -- alternatives are empty, the scrutinee must diverge or raise an |
|---|
| 370 | -- exception, so we can just dive into it. |
|---|
| 371 | -- |
|---|
| 372 | -- Of course this may seg-fault if the scrutinee *does* return. A |
|---|
| 373 | -- belt-and-braces approach would be to move this case into the |
|---|
| 374 | -- code generator, and put a return point anyway that calls a |
|---|
| 375 | -- runtime system error function. |
|---|
| 376 | |
|---|
| 377 | |
|---|
| 378 | coreToStgExpr (Case scrut bndr _ alts) = do |
|---|
| 379 | (alts2, alts_fvs, alts_escs) |
|---|
| 380 | <- extendVarEnvLne [(bndr, LambdaBound)] $ do |
|---|
| 381 | (alts2, fvs_s, escs_s) <- mapAndUnzip3M vars_alt alts |
|---|
| 382 | return ( alts2, |
|---|
| 383 | unionFVInfos fvs_s, |
|---|
| 384 | unionVarSets escs_s ) |
|---|
| 385 | let |
|---|
| 386 | -- Determine whether the default binder is dead or not |
|---|
| 387 | -- This helps the code generator to avoid generating an assignment |
|---|
| 388 | -- for the case binder (is extremely rare cases) ToDo: remove. |
|---|
| 389 | bndr' | bndr `elementOfFVInfo` alts_fvs = bndr |
|---|
| 390 | | otherwise = bndr `setIdOccInfo` IAmDead |
|---|
| 391 | |
|---|
| 392 | -- Don't consider the default binder as being 'live in alts', |
|---|
| 393 | -- since this is from the point of view of the case expr, where |
|---|
| 394 | -- the default binder is not free. |
|---|
| 395 | alts_fvs_wo_bndr = bndr `minusFVBinder` alts_fvs |
|---|
| 396 | alts_escs_wo_bndr = alts_escs `delVarSet` bndr |
|---|
| 397 | |
|---|
| 398 | alts_lv_info <- freeVarsToLiveVars alts_fvs_wo_bndr |
|---|
| 399 | |
|---|
| 400 | -- We tell the scrutinee that everything |
|---|
| 401 | -- live in the alts is live in it, too. |
|---|
| 402 | (scrut2, scrut_fvs, _scrut_escs, scrut_lv_info) |
|---|
| 403 | <- setVarsLiveInCont alts_lv_info $ do |
|---|
| 404 | (scrut2, scrut_fvs, scrut_escs) <- coreToStgExpr scrut |
|---|
| 405 | scrut_lv_info <- freeVarsToLiveVars scrut_fvs |
|---|
| 406 | return (scrut2, scrut_fvs, scrut_escs, scrut_lv_info) |
|---|
| 407 | |
|---|
| 408 | return ( |
|---|
| 409 | StgCase scrut2 (getLiveVars scrut_lv_info) |
|---|
| 410 | (getLiveVars alts_lv_info) |
|---|
| 411 | bndr' |
|---|
| 412 | (mkSRT alts_lv_info) |
|---|
| 413 | (mkStgAltType bndr alts) |
|---|
| 414 | alts2, |
|---|
| 415 | scrut_fvs `unionFVInfo` alts_fvs_wo_bndr, |
|---|
| 416 | alts_escs_wo_bndr `unionVarSet` getFVSet scrut_fvs |
|---|
| 417 | -- You might think we should have scrut_escs, not |
|---|
| 418 | -- (getFVSet scrut_fvs), but actually we can't call, and |
|---|
| 419 | -- then return from, a let-no-escape thing. |
|---|
| 420 | ) |
|---|
| 421 | where |
|---|
| 422 | vars_alt (con, binders, rhs) |
|---|
| 423 | = let -- Remove type variables |
|---|
| 424 | binders' = filterStgBinders binders |
|---|
| 425 | in |
|---|
| 426 | extendVarEnvLne [(b, LambdaBound) | b <- binders'] $ do |
|---|
| 427 | (rhs2, rhs_fvs, rhs_escs) <- coreToStgExpr rhs |
|---|
| 428 | let |
|---|
| 429 | -- Records whether each param is used in the RHS |
|---|
| 430 | good_use_mask = [ b `elementOfFVInfo` rhs_fvs | b <- binders' ] |
|---|
| 431 | |
|---|
| 432 | return ( (con, binders', good_use_mask, rhs2), |
|---|
| 433 | binders' `minusFVBinders` rhs_fvs, |
|---|
| 434 | rhs_escs `delVarSetList` binders' ) |
|---|
| 435 | -- ToDo: remove the delVarSet; |
|---|
| 436 | -- since escs won't include any of these binders |
|---|
| 437 | \end{code} |
|---|
| 438 | |
|---|
| 439 | Lets not only take quite a bit of work, but this is where we convert |
|---|
| 440 | then to let-no-escapes, if we wish. |
|---|
| 441 | |
|---|
| 442 | (Meanwhile, we don't expect to see let-no-escapes...) |
|---|
| 443 | \begin{code} |
|---|
| 444 | coreToStgExpr (Let bind body) = do |
|---|
| 445 | (new_let, fvs, escs, _) |
|---|
| 446 | <- mfix (\ ~(_, _, _, no_binder_escapes) -> |
|---|
| 447 | coreToStgLet no_binder_escapes bind body |
|---|
| 448 | ) |
|---|
| 449 | |
|---|
| 450 | return (new_let, fvs, escs) |
|---|
| 451 | |
|---|
| 452 | coreToStgExpr e = pprPanic "coreToStgExpr" (ppr e) |
|---|
| 453 | \end{code} |
|---|
| 454 | |
|---|
| 455 | \begin{code} |
|---|
| 456 | mkStgAltType :: Id -> [CoreAlt] -> AltType |
|---|
| 457 | mkStgAltType bndr alts |
|---|
| 458 | = case tyConAppTyCon_maybe (repType (idType bndr)) of |
|---|
| 459 | Just tc | isUnboxedTupleTyCon tc -> UbxTupAlt tc |
|---|
| 460 | | isUnLiftedTyCon tc -> PrimAlt tc |
|---|
| 461 | | isAbstractTyCon tc -> look_for_better_tycon |
|---|
| 462 | | isAlgTyCon tc -> AlgAlt tc |
|---|
| 463 | | otherwise -> ASSERT2( _is_poly_alt_tycon tc, ppr tc ) |
|---|
| 464 | PolyAlt |
|---|
| 465 | Nothing -> PolyAlt |
|---|
| 466 | |
|---|
| 467 | where |
|---|
| 468 | _is_poly_alt_tycon tc |
|---|
| 469 | = isFunTyCon tc |
|---|
| 470 | || isPrimTyCon tc -- "Any" is lifted but primitive |
|---|
| 471 | || isFamilyTyCon tc -- Type family; e.g. arising from strict |
|---|
| 472 | -- function application where argument has a |
|---|
| 473 | -- type-family type |
|---|
| 474 | |
|---|
| 475 | -- Sometimes, the TyCon is a AbstractTyCon which may not have any |
|---|
| 476 | -- constructors inside it. Then we may get a better TyCon by |
|---|
| 477 | -- grabbing the one from a constructor alternative |
|---|
| 478 | -- if one exists. |
|---|
| 479 | look_for_better_tycon |
|---|
| 480 | | ((DataAlt con, _, _) : _) <- data_alts = |
|---|
| 481 | AlgAlt (dataConTyCon con) |
|---|
| 482 | | otherwise = |
|---|
| 483 | ASSERT(null data_alts) |
|---|
| 484 | PolyAlt |
|---|
| 485 | where |
|---|
| 486 | (data_alts, _deflt) = findDefault alts |
|---|
| 487 | \end{code} |
|---|
| 488 | |
|---|
| 489 | |
|---|
| 490 | -- --------------------------------------------------------------------------- |
|---|
| 491 | -- Applications |
|---|
| 492 | -- --------------------------------------------------------------------------- |
|---|
| 493 | |
|---|
| 494 | \begin{code} |
|---|
| 495 | coreToStgApp |
|---|
| 496 | :: Maybe UpdateFlag -- Just upd <=> this application is |
|---|
| 497 | -- the rhs of a thunk binding |
|---|
| 498 | -- x = [...] \upd [] -> the_app |
|---|
| 499 | -- with specified update flag |
|---|
| 500 | -> Id -- Function |
|---|
| 501 | -> [CoreArg] -- Arguments |
|---|
| 502 | -> LneM (StgExpr, FreeVarsInfo, EscVarsSet) |
|---|
| 503 | |
|---|
| 504 | |
|---|
| 505 | coreToStgApp _ f args = do |
|---|
| 506 | (args', args_fvs) <- coreToStgArgs args |
|---|
| 507 | how_bound <- lookupVarLne f |
|---|
| 508 | |
|---|
| 509 | let |
|---|
| 510 | n_val_args = valArgCount args |
|---|
| 511 | not_letrec_bound = not (isLetBound how_bound) |
|---|
| 512 | fun_fvs = singletonFVInfo f how_bound fun_occ |
|---|
| 513 | -- e.g. (f :: a -> int) (x :: a) |
|---|
| 514 | -- Here the free variables are "f", "x" AND the type variable "a" |
|---|
| 515 | -- coreToStgArgs will deal with the arguments recursively |
|---|
| 516 | |
|---|
| 517 | -- Mostly, the arity info of a function is in the fn's IdInfo |
|---|
| 518 | -- But new bindings introduced by CoreSat may not have no |
|---|
| 519 | -- arity info; it would do us no good anyway. For example: |
|---|
| 520 | -- let f = \ab -> e in f |
|---|
| 521 | -- No point in having correct arity info for f! |
|---|
| 522 | -- Hence the hasArity stuff below. |
|---|
| 523 | -- NB: f_arity is only consulted for LetBound things |
|---|
| 524 | f_arity = stgArity f how_bound |
|---|
| 525 | saturated = f_arity <= n_val_args |
|---|
| 526 | |
|---|
| 527 | fun_occ |
|---|
| 528 | | not_letrec_bound = noBinderInfo -- Uninteresting variable |
|---|
| 529 | | f_arity > 0 && saturated = stgSatOcc -- Saturated or over-saturated function call |
|---|
| 530 | | otherwise = stgUnsatOcc -- Unsaturated function or thunk |
|---|
| 531 | |
|---|
| 532 | fun_escs |
|---|
| 533 | | not_letrec_bound = emptyVarSet -- Only letrec-bound escapees are interesting |
|---|
| 534 | | f_arity == n_val_args = emptyVarSet -- A function *or thunk* with an exactly |
|---|
| 535 | -- saturated call doesn't escape |
|---|
| 536 | -- (let-no-escape applies to 'thunks' too) |
|---|
| 537 | |
|---|
| 538 | | otherwise = unitVarSet f -- Inexact application; it does escape |
|---|
| 539 | |
|---|
| 540 | -- At the moment of the call: |
|---|
| 541 | |
|---|
| 542 | -- either the function is *not* let-no-escaped, in which case |
|---|
| 543 | -- nothing is live except live_in_cont |
|---|
| 544 | -- or the function *is* let-no-escaped in which case the |
|---|
| 545 | -- variables it uses are live, but still the function |
|---|
| 546 | -- itself is not. PS. In this case, the function's |
|---|
| 547 | -- live vars should already include those of the |
|---|
| 548 | -- continuation, but it does no harm to just union the |
|---|
| 549 | -- two regardless. |
|---|
| 550 | |
|---|
| 551 | res_ty = exprType (mkApps (Var f) args) |
|---|
| 552 | app = case idDetails f of |
|---|
| 553 | DataConWorkId dc | saturated -> StgConApp dc args' |
|---|
| 554 | |
|---|
| 555 | -- Some primitive operator that might be implemented as a library call. |
|---|
| 556 | PrimOpId op -> ASSERT( saturated ) |
|---|
| 557 | StgOpApp (StgPrimOp op) args' res_ty |
|---|
| 558 | |
|---|
| 559 | -- A call to some primitive Cmm function. |
|---|
| 560 | FCallId (CCall (CCallSpec (StaticTarget lbl (Just pkgId) True) PrimCallConv _)) |
|---|
| 561 | -> ASSERT( saturated ) |
|---|
| 562 | StgOpApp (StgPrimCallOp (PrimCall lbl pkgId)) args' res_ty |
|---|
| 563 | |
|---|
| 564 | -- A regular foreign call. |
|---|
| 565 | FCallId call -> ASSERT( saturated ) |
|---|
| 566 | StgOpApp (StgFCallOp call (idUnique f)) args' res_ty |
|---|
| 567 | |
|---|
| 568 | TickBoxOpId {} -> pprPanic "coreToStg TickBox" $ ppr (f,args') |
|---|
| 569 | _other -> StgApp f args' |
|---|
| 570 | fvs = fun_fvs `unionFVInfo` args_fvs |
|---|
| 571 | vars = fun_escs `unionVarSet` (getFVSet args_fvs) |
|---|
| 572 | -- All the free vars of the args are disqualified |
|---|
| 573 | -- from being let-no-escaped. |
|---|
| 574 | |
|---|
| 575 | -- Forcing these fixes a leak in the code generator, noticed while |
|---|
| 576 | -- profiling for trac #4367 |
|---|
| 577 | app `seq` fvs `seq` seqVarSet vars `seq` return ( |
|---|
| 578 | app, |
|---|
| 579 | fvs, |
|---|
| 580 | vars |
|---|
| 581 | ) |
|---|
| 582 | |
|---|
| 583 | |
|---|
| 584 | |
|---|
| 585 | -- --------------------------------------------------------------------------- |
|---|
| 586 | -- Argument lists |
|---|
| 587 | -- This is the guy that turns applications into A-normal form |
|---|
| 588 | -- --------------------------------------------------------------------------- |
|---|
| 589 | |
|---|
| 590 | coreToStgArgs :: [CoreArg] -> LneM ([StgArg], FreeVarsInfo) |
|---|
| 591 | coreToStgArgs [] |
|---|
| 592 | = return ([], emptyFVInfo) |
|---|
| 593 | |
|---|
| 594 | coreToStgArgs (Type _ : args) = do -- Type argument |
|---|
| 595 | (args', fvs) <- coreToStgArgs args |
|---|
| 596 | return (args', fvs) |
|---|
| 597 | |
|---|
| 598 | coreToStgArgs (Coercion _ : args) -- Coercion argument; replace with place holder |
|---|
| 599 | = do { (args', fvs) <- coreToStgArgs args |
|---|
| 600 | ; return (StgVarArg coercionTokenId : args', fvs) } |
|---|
| 601 | |
|---|
| 602 | coreToStgArgs (arg : args) = do -- Non-type argument |
|---|
| 603 | (stg_args, args_fvs) <- coreToStgArgs args |
|---|
| 604 | (arg', arg_fvs, _escs) <- coreToStgExpr arg |
|---|
| 605 | let |
|---|
| 606 | fvs = args_fvs `unionFVInfo` arg_fvs |
|---|
| 607 | stg_arg = case arg' of |
|---|
| 608 | StgApp v [] -> StgVarArg v |
|---|
| 609 | StgConApp con [] -> StgVarArg (dataConWorkId con) |
|---|
| 610 | StgLit lit -> StgLitArg lit |
|---|
| 611 | _ -> pprPanic "coreToStgArgs" (ppr arg) |
|---|
| 612 | |
|---|
| 613 | -- WARNING: what if we have an argument like (v `cast` co) |
|---|
| 614 | -- where 'co' changes the representation type? |
|---|
| 615 | -- (This really only happens if co is unsafe.) |
|---|
| 616 | -- Then all the getArgAmode stuff in CgBindery will set the |
|---|
| 617 | -- cg_rep of the CgIdInfo based on the type of v, rather |
|---|
| 618 | -- than the type of 'co'. |
|---|
| 619 | -- This matters particularly when the function is a primop |
|---|
| 620 | -- or foreign call. |
|---|
| 621 | -- Wanted: a better solution than this hacky warning |
|---|
| 622 | let |
|---|
| 623 | arg_ty = exprType arg |
|---|
| 624 | stg_arg_ty = stgArgType stg_arg |
|---|
| 625 | bad_args = (isUnLiftedType arg_ty && not (isUnLiftedType stg_arg_ty)) |
|---|
| 626 | || (typePrimRep arg_ty /= typePrimRep stg_arg_ty) |
|---|
| 627 | -- In GHCi we coerce an argument of type BCO# (unlifted) to HValue (lifted), |
|---|
| 628 | -- and pass it to a function expecting an HValue (arg_ty). This is ok because |
|---|
| 629 | -- we can treat an unlifted value as lifted. But the other way round |
|---|
| 630 | -- we complain. |
|---|
| 631 | -- We also want to check if a pointer is cast to a non-ptr etc |
|---|
| 632 | |
|---|
| 633 | WARN( bad_args, ptext (sLit "Dangerous-looking argument. Probable cause: bad unsafeCoerce#") $$ ppr arg ) |
|---|
| 634 | return (stg_arg : stg_args, fvs) |
|---|
| 635 | |
|---|
| 636 | |
|---|
| 637 | -- --------------------------------------------------------------------------- |
|---|
| 638 | -- The magic for lets: |
|---|
| 639 | -- --------------------------------------------------------------------------- |
|---|
| 640 | |
|---|
| 641 | coreToStgLet |
|---|
| 642 | :: Bool -- True <=> yes, we are let-no-escaping this let |
|---|
| 643 | -> CoreBind -- bindings |
|---|
| 644 | -> CoreExpr -- body |
|---|
| 645 | -> LneM (StgExpr, -- new let |
|---|
| 646 | FreeVarsInfo, -- variables free in the whole let |
|---|
| 647 | EscVarsSet, -- variables that escape from the whole let |
|---|
| 648 | Bool) -- True <=> none of the binders in the bindings |
|---|
| 649 | -- is among the escaping vars |
|---|
| 650 | |
|---|
| 651 | coreToStgLet let_no_escape bind body = do |
|---|
| 652 | (bind2, bind_fvs, bind_escs, bind_lvs, |
|---|
| 653 | body2, body_fvs, body_escs, body_lvs) |
|---|
| 654 | <- mfix $ \ ~(_, _, _, _, _, rec_body_fvs, _, _) -> do |
|---|
| 655 | |
|---|
| 656 | -- Do the bindings, setting live_in_cont to empty if |
|---|
| 657 | -- we ain't in a let-no-escape world |
|---|
| 658 | live_in_cont <- getVarsLiveInCont |
|---|
| 659 | ( bind2, bind_fvs, bind_escs, bind_lv_info, env_ext) |
|---|
| 660 | <- setVarsLiveInCont (if let_no_escape |
|---|
| 661 | then live_in_cont |
|---|
| 662 | else emptyLiveInfo) |
|---|
| 663 | (vars_bind rec_body_fvs bind) |
|---|
| 664 | |
|---|
| 665 | -- Do the body |
|---|
| 666 | extendVarEnvLne env_ext $ do |
|---|
| 667 | (body2, body_fvs, body_escs) <- coreToStgExpr body |
|---|
| 668 | body_lv_info <- freeVarsToLiveVars body_fvs |
|---|
| 669 | |
|---|
| 670 | return (bind2, bind_fvs, bind_escs, getLiveVars bind_lv_info, |
|---|
| 671 | body2, body_fvs, body_escs, getLiveVars body_lv_info) |
|---|
| 672 | |
|---|
| 673 | |
|---|
| 674 | -- Compute the new let-expression |
|---|
| 675 | let |
|---|
| 676 | new_let | let_no_escape = StgLetNoEscape live_in_whole_let bind_lvs bind2 body2 |
|---|
| 677 | | otherwise = StgLet bind2 body2 |
|---|
| 678 | |
|---|
| 679 | free_in_whole_let |
|---|
| 680 | = binders `minusFVBinders` (bind_fvs `unionFVInfo` body_fvs) |
|---|
| 681 | |
|---|
| 682 | live_in_whole_let |
|---|
| 683 | = bind_lvs `unionVarSet` (body_lvs `delVarSetList` binders) |
|---|
| 684 | |
|---|
| 685 | real_bind_escs = if let_no_escape then |
|---|
| 686 | bind_escs |
|---|
| 687 | else |
|---|
| 688 | getFVSet bind_fvs |
|---|
| 689 | -- Everything escapes which is free in the bindings |
|---|
| 690 | |
|---|
| 691 | let_escs = (real_bind_escs `unionVarSet` body_escs) `delVarSetList` binders |
|---|
| 692 | |
|---|
| 693 | all_escs = bind_escs `unionVarSet` body_escs -- Still includes binders of |
|---|
| 694 | -- this let(rec) |
|---|
| 695 | |
|---|
| 696 | no_binder_escapes = isEmptyVarSet (set_of_binders `intersectVarSet` all_escs) |
|---|
| 697 | |
|---|
| 698 | -- Debugging code as requested by Andrew Kennedy |
|---|
| 699 | checked_no_binder_escapes |
|---|
| 700 | | debugIsOn && not no_binder_escapes && any is_join_var binders |
|---|
| 701 | = pprTrace "Interesting! A join var that isn't let-no-escaped" (ppr binders) |
|---|
| 702 | False |
|---|
| 703 | | otherwise = no_binder_escapes |
|---|
| 704 | |
|---|
| 705 | -- Mustn't depend on the passed-in let_no_escape flag, since |
|---|
| 706 | -- no_binder_escapes is used by the caller to derive the flag! |
|---|
| 707 | return ( |
|---|
| 708 | new_let, |
|---|
| 709 | free_in_whole_let, |
|---|
| 710 | let_escs, |
|---|
| 711 | checked_no_binder_escapes |
|---|
| 712 | ) |
|---|
| 713 | where |
|---|
| 714 | set_of_binders = mkVarSet binders |
|---|
| 715 | binders = bindersOf bind |
|---|
| 716 | |
|---|
| 717 | mk_binding bind_lv_info binder rhs |
|---|
| 718 | = (binder, LetBound (NestedLet live_vars) (manifestArity rhs)) |
|---|
| 719 | where |
|---|
| 720 | live_vars | let_no_escape = addLiveVar bind_lv_info binder |
|---|
| 721 | | otherwise = unitLiveVar binder |
|---|
| 722 | -- c.f. the invariant on NestedLet |
|---|
| 723 | |
|---|
| 724 | vars_bind :: FreeVarsInfo -- Free var info for body of binding |
|---|
| 725 | -> CoreBind |
|---|
| 726 | -> LneM (StgBinding, |
|---|
| 727 | FreeVarsInfo, |
|---|
| 728 | EscVarsSet, -- free vars; escapee vars |
|---|
| 729 | LiveInfo, -- Vars and CAFs live in binding |
|---|
| 730 | [(Id, HowBound)]) -- extension to environment |
|---|
| 731 | |
|---|
| 732 | |
|---|
| 733 | vars_bind body_fvs (NonRec binder rhs) = do |
|---|
| 734 | (rhs2, bind_fvs, bind_lv_info, escs) <- coreToStgRhs body_fvs [] (binder,rhs) |
|---|
| 735 | let |
|---|
| 736 | env_ext_item = mk_binding bind_lv_info binder rhs |
|---|
| 737 | |
|---|
| 738 | return (StgNonRec binder rhs2, |
|---|
| 739 | bind_fvs, escs, bind_lv_info, [env_ext_item]) |
|---|
| 740 | |
|---|
| 741 | |
|---|
| 742 | vars_bind body_fvs (Rec pairs) |
|---|
| 743 | = mfix $ \ ~(_, rec_rhs_fvs, _, bind_lv_info, _) -> |
|---|
| 744 | let |
|---|
| 745 | rec_scope_fvs = unionFVInfo body_fvs rec_rhs_fvs |
|---|
| 746 | binders = map fst pairs |
|---|
| 747 | env_ext = [ mk_binding bind_lv_info b rhs |
|---|
| 748 | | (b,rhs) <- pairs ] |
|---|
| 749 | in |
|---|
| 750 | extendVarEnvLne env_ext $ do |
|---|
| 751 | (rhss2, fvss, lv_infos, escss) |
|---|
| 752 | <- mapAndUnzip4M (coreToStgRhs rec_scope_fvs binders) pairs |
|---|
| 753 | let |
|---|
| 754 | bind_fvs = unionFVInfos fvss |
|---|
| 755 | bind_lv_info = foldr unionLiveInfo emptyLiveInfo lv_infos |
|---|
| 756 | escs = unionVarSets escss |
|---|
| 757 | |
|---|
| 758 | return (StgRec (binders `zip` rhss2), |
|---|
| 759 | bind_fvs, escs, bind_lv_info, env_ext) |
|---|
| 760 | |
|---|
| 761 | |
|---|
| 762 | is_join_var :: Id -> Bool |
|---|
| 763 | -- A hack (used only for compiler debuggging) to tell if |
|---|
| 764 | -- a variable started life as a join point ($j) |
|---|
| 765 | is_join_var j = occNameString (getOccName j) == "$j" |
|---|
| 766 | \end{code} |
|---|
| 767 | |
|---|
| 768 | \begin{code} |
|---|
| 769 | coreToStgRhs :: FreeVarsInfo -- Free var info for the scope of the binding |
|---|
| 770 | -> [Id] |
|---|
| 771 | -> (Id,CoreExpr) |
|---|
| 772 | -> LneM (StgRhs, FreeVarsInfo, LiveInfo, EscVarsSet) |
|---|
| 773 | |
|---|
| 774 | coreToStgRhs scope_fv_info binders (bndr, rhs) = do |
|---|
| 775 | (new_rhs, rhs_fvs, rhs_escs) <- coreToStgExpr rhs |
|---|
| 776 | lv_info <- freeVarsToLiveVars (binders `minusFVBinders` rhs_fvs) |
|---|
| 777 | return (mkStgRhs rhs_fvs (mkSRT lv_info) bndr_info new_rhs, |
|---|
| 778 | rhs_fvs, lv_info, rhs_escs) |
|---|
| 779 | where |
|---|
| 780 | bndr_info = lookupFVInfo scope_fv_info bndr |
|---|
| 781 | |
|---|
| 782 | mkStgRhs :: FreeVarsInfo -> SRT -> StgBinderInfo -> StgExpr -> StgRhs |
|---|
| 783 | |
|---|
| 784 | mkStgRhs _ _ _ (StgConApp con args) = StgRhsCon noCCS con args |
|---|
| 785 | |
|---|
| 786 | mkStgRhs rhs_fvs srt binder_info (StgLam _ bndrs body) |
|---|
| 787 | = StgRhsClosure noCCS binder_info |
|---|
| 788 | (getFVs rhs_fvs) |
|---|
| 789 | ReEntrant |
|---|
| 790 | srt bndrs body |
|---|
| 791 | |
|---|
| 792 | mkStgRhs rhs_fvs srt binder_info rhs |
|---|
| 793 | = StgRhsClosure noCCS binder_info |
|---|
| 794 | (getFVs rhs_fvs) |
|---|
| 795 | upd_flag srt [] rhs |
|---|
| 796 | where |
|---|
| 797 | upd_flag = Updatable |
|---|
| 798 | {- |
|---|
| 799 | SDM: disabled. Eval/Apply can't handle functions with arity zero very |
|---|
| 800 | well; and making these into simple non-updatable thunks breaks other |
|---|
| 801 | assumptions (namely that they will be entered only once). |
|---|
| 802 | |
|---|
| 803 | upd_flag | isPAP env rhs = ReEntrant |
|---|
| 804 | | otherwise = Updatable |
|---|
| 805 | -} |
|---|
| 806 | |
|---|
| 807 | {- ToDo: |
|---|
| 808 | upd = if isOnceDem dem |
|---|
| 809 | then (if isNotTop toplev |
|---|
| 810 | then SingleEntry -- HA! Paydirt for "dem" |
|---|
| 811 | else |
|---|
| 812 | (if debugIsOn then trace "WARNING: SE CAFs unsupported, forcing UPD instead" else id) $ |
|---|
| 813 | Updatable) |
|---|
| 814 | else Updatable |
|---|
| 815 | -- For now we forbid SingleEntry CAFs; they tickle the |
|---|
| 816 | -- ASSERT in rts/Storage.c line 215 at newCAF() re mut_link, |
|---|
| 817 | -- and I don't understand why. There's only one SE_CAF (well, |
|---|
| 818 | -- only one that tickled a great gaping bug in an earlier attempt |
|---|
| 819 | -- at ClosureInfo.getEntryConvention) in the whole of nofib, |
|---|
| 820 | -- specifically Main.lvl6 in spectral/cryptarithm2. |
|---|
| 821 | -- So no great loss. KSW 2000-07. |
|---|
| 822 | -} |
|---|
| 823 | \end{code} |
|---|
| 824 | |
|---|
| 825 | Detect thunks which will reduce immediately to PAPs, and make them |
|---|
| 826 | non-updatable. This has several advantages: |
|---|
| 827 | |
|---|
| 828 | - the non-updatable thunk behaves exactly like the PAP, |
|---|
| 829 | |
|---|
| 830 | - the thunk is more efficient to enter, because it is |
|---|
| 831 | specialised to the task. |
|---|
| 832 | |
|---|
| 833 | - we save one update frame, one stg_update_PAP, one update |
|---|
| 834 | and lots of PAP_enters. |
|---|
| 835 | |
|---|
| 836 | - in the case where the thunk is top-level, we save building |
|---|
| 837 | a black hole and futhermore the thunk isn't considered to |
|---|
| 838 | be a CAF any more, so it doesn't appear in any SRTs. |
|---|
| 839 | |
|---|
| 840 | We do it here, because the arity information is accurate, and we need |
|---|
| 841 | to do it before the SRT pass to save the SRT entries associated with |
|---|
| 842 | any top-level PAPs. |
|---|
| 843 | |
|---|
| 844 | isPAP env (StgApp f args) = listLengthCmp args arity == LT -- idArity f > length args |
|---|
| 845 | where |
|---|
| 846 | arity = stgArity f (lookupBinding env f) |
|---|
| 847 | isPAP env _ = False |
|---|
| 848 | |
|---|
| 849 | |
|---|
| 850 | %************************************************************************ |
|---|
| 851 | %* * |
|---|
| 852 | \subsection[LNE-monad]{A little monad for this let-no-escaping pass} |
|---|
| 853 | %* * |
|---|
| 854 | %************************************************************************ |
|---|
| 855 | |
|---|
| 856 | There's a lot of stuff to pass around, so we use this @LneM@ monad to |
|---|
| 857 | help. All the stuff here is only passed *down*. |
|---|
| 858 | |
|---|
| 859 | \begin{code} |
|---|
| 860 | newtype LneM a = LneM |
|---|
| 861 | { unLneM :: IdEnv HowBound |
|---|
| 862 | -> LiveInfo -- Vars and CAFs live in continuation |
|---|
| 863 | -> a |
|---|
| 864 | } |
|---|
| 865 | |
|---|
| 866 | type LiveInfo = (StgLiveVars, -- Dynamic live variables; |
|---|
| 867 | -- i.e. ones with a nested (non-top-level) binding |
|---|
| 868 | CafSet) -- Static live variables; |
|---|
| 869 | -- i.e. top-level variables that are CAFs or refer to them |
|---|
| 870 | |
|---|
| 871 | type EscVarsSet = IdSet |
|---|
| 872 | type CafSet = IdSet |
|---|
| 873 | |
|---|
| 874 | data HowBound |
|---|
| 875 | = ImportBound -- Used only as a response to lookupBinding; never |
|---|
| 876 | -- exists in the range of the (IdEnv HowBound) |
|---|
| 877 | |
|---|
| 878 | | LetBound -- A let(rec) in this module |
|---|
| 879 | LetInfo -- Whether top level or nested |
|---|
| 880 | Arity -- Its arity (local Ids don't have arity info at this point) |
|---|
| 881 | |
|---|
| 882 | | LambdaBound -- Used for both lambda and case |
|---|
| 883 | |
|---|
| 884 | data LetInfo |
|---|
| 885 | = TopLet -- top level things |
|---|
| 886 | | NestedLet LiveInfo -- For nested things, what is live if this |
|---|
| 887 | -- thing is live? Invariant: the binder |
|---|
| 888 | -- itself is always a member of |
|---|
| 889 | -- the dynamic set of its own LiveInfo |
|---|
| 890 | |
|---|
| 891 | isLetBound :: HowBound -> Bool |
|---|
| 892 | isLetBound (LetBound _ _) = True |
|---|
| 893 | isLetBound _ = False |
|---|
| 894 | |
|---|
| 895 | topLevelBound :: HowBound -> Bool |
|---|
| 896 | topLevelBound ImportBound = True |
|---|
| 897 | topLevelBound (LetBound TopLet _) = True |
|---|
| 898 | topLevelBound _ = False |
|---|
| 899 | \end{code} |
|---|
| 900 | |
|---|
| 901 | For a let(rec)-bound variable, x, we record LiveInfo, the set of |
|---|
| 902 | variables that are live if x is live. This LiveInfo comprises |
|---|
| 903 | (a) dynamic live variables (ones with a non-top-level binding) |
|---|
| 904 | (b) static live variabes (CAFs or things that refer to CAFs) |
|---|
| 905 | |
|---|
| 906 | For "normal" variables (a) is just x alone. If x is a let-no-escaped |
|---|
| 907 | variable then x is represented by a code pointer and a stack pointer |
|---|
| 908 | (well, one for each stack). So all of the variables needed in the |
|---|
| 909 | execution of x are live if x is, and are therefore recorded in the |
|---|
| 910 | LetBound constructor; x itself *is* included. |
|---|
| 911 | |
|---|
| 912 | The set of dynamic live variables is guaranteed ot have no further let-no-escaped |
|---|
| 913 | variables in it. |
|---|
| 914 | |
|---|
| 915 | \begin{code} |
|---|
| 916 | emptyLiveInfo :: LiveInfo |
|---|
| 917 | emptyLiveInfo = (emptyVarSet,emptyVarSet) |
|---|
| 918 | |
|---|
| 919 | unitLiveVar :: Id -> LiveInfo |
|---|
| 920 | unitLiveVar lv = (unitVarSet lv, emptyVarSet) |
|---|
| 921 | |
|---|
| 922 | unitLiveCaf :: Id -> LiveInfo |
|---|
| 923 | unitLiveCaf caf = (emptyVarSet, unitVarSet caf) |
|---|
| 924 | |
|---|
| 925 | addLiveVar :: LiveInfo -> Id -> LiveInfo |
|---|
| 926 | addLiveVar (lvs, cafs) id = (lvs `extendVarSet` id, cafs) |
|---|
| 927 | |
|---|
| 928 | unionLiveInfo :: LiveInfo -> LiveInfo -> LiveInfo |
|---|
| 929 | unionLiveInfo (lv1,caf1) (lv2,caf2) = (lv1 `unionVarSet` lv2, caf1 `unionVarSet` caf2) |
|---|
| 930 | |
|---|
| 931 | mkSRT :: LiveInfo -> SRT |
|---|
| 932 | mkSRT (_, cafs) = SRTEntries cafs |
|---|
| 933 | |
|---|
| 934 | getLiveVars :: LiveInfo -> StgLiveVars |
|---|
| 935 | getLiveVars (lvs, _) = lvs |
|---|
| 936 | \end{code} |
|---|
| 937 | |
|---|
| 938 | |
|---|
| 939 | The std monad functions: |
|---|
| 940 | \begin{code} |
|---|
| 941 | initLne :: IdEnv HowBound -> LneM a -> a |
|---|
| 942 | initLne env m = unLneM m env emptyLiveInfo |
|---|
| 943 | |
|---|
| 944 | |
|---|
| 945 | |
|---|
| 946 | {-# INLINE thenLne #-} |
|---|
| 947 | {-# INLINE returnLne #-} |
|---|
| 948 | |
|---|
| 949 | returnLne :: a -> LneM a |
|---|
| 950 | returnLne e = LneM $ \_ _ -> e |
|---|
| 951 | |
|---|
| 952 | thenLne :: LneM a -> (a -> LneM b) -> LneM b |
|---|
| 953 | thenLne m k = LneM $ \env lvs_cont |
|---|
| 954 | -> unLneM (k (unLneM m env lvs_cont)) env lvs_cont |
|---|
| 955 | |
|---|
| 956 | instance Monad LneM where |
|---|
| 957 | return = returnLne |
|---|
| 958 | (>>=) = thenLne |
|---|
| 959 | |
|---|
| 960 | instance MonadFix LneM where |
|---|
| 961 | mfix expr = LneM $ \env lvs_cont -> |
|---|
| 962 | let result = unLneM (expr result) env lvs_cont |
|---|
| 963 | in result |
|---|
| 964 | \end{code} |
|---|
| 965 | |
|---|
| 966 | Functions specific to this monad: |
|---|
| 967 | |
|---|
| 968 | \begin{code} |
|---|
| 969 | getVarsLiveInCont :: LneM LiveInfo |
|---|
| 970 | getVarsLiveInCont = LneM $ \_env lvs_cont -> lvs_cont |
|---|
| 971 | |
|---|
| 972 | setVarsLiveInCont :: LiveInfo -> LneM a -> LneM a |
|---|
| 973 | setVarsLiveInCont new_lvs_cont expr |
|---|
| 974 | = LneM $ \env _lvs_cont |
|---|
| 975 | -> unLneM expr env new_lvs_cont |
|---|
| 976 | |
|---|
| 977 | extendVarEnvLne :: [(Id, HowBound)] -> LneM a -> LneM a |
|---|
| 978 | extendVarEnvLne ids_w_howbound expr |
|---|
| 979 | = LneM $ \env lvs_cont |
|---|
| 980 | -> unLneM expr (extendVarEnvList env ids_w_howbound) lvs_cont |
|---|
| 981 | |
|---|
| 982 | lookupVarLne :: Id -> LneM HowBound |
|---|
| 983 | lookupVarLne v = LneM $ \env _lvs_cont -> lookupBinding env v |
|---|
| 984 | |
|---|
| 985 | lookupBinding :: IdEnv HowBound -> Id -> HowBound |
|---|
| 986 | lookupBinding env v = case lookupVarEnv env v of |
|---|
| 987 | Just xx -> xx |
|---|
| 988 | Nothing -> ASSERT2( isGlobalId v, ppr v ) ImportBound |
|---|
| 989 | |
|---|
| 990 | |
|---|
| 991 | -- The result of lookupLiveVarsForSet, a set of live variables, is |
|---|
| 992 | -- only ever tacked onto a decorated expression. It is never used as |
|---|
| 993 | -- the basis of a control decision, which might give a black hole. |
|---|
| 994 | |
|---|
| 995 | freeVarsToLiveVars :: FreeVarsInfo -> LneM LiveInfo |
|---|
| 996 | freeVarsToLiveVars fvs = LneM freeVarsToLiveVars' |
|---|
| 997 | where |
|---|
| 998 | freeVarsToLiveVars' _env live_in_cont = live_info |
|---|
| 999 | where |
|---|
| 1000 | live_info = foldr unionLiveInfo live_in_cont lvs_from_fvs |
|---|
| 1001 | lvs_from_fvs = map do_one (allFreeIds fvs) |
|---|
| 1002 | |
|---|
| 1003 | do_one (v, how_bound) |
|---|
| 1004 | = case how_bound of |
|---|
| 1005 | ImportBound -> unitLiveCaf v -- Only CAF imports are |
|---|
| 1006 | -- recorded in fvs |
|---|
| 1007 | LetBound TopLet _ |
|---|
| 1008 | | mayHaveCafRefs (idCafInfo v) -> unitLiveCaf v |
|---|
| 1009 | | otherwise -> emptyLiveInfo |
|---|
| 1010 | |
|---|
| 1011 | LetBound (NestedLet lvs) _ -> lvs -- lvs already contains v |
|---|
| 1012 | -- (see the invariant on NestedLet) |
|---|
| 1013 | |
|---|
| 1014 | _lambda_or_case_binding -> unitLiveVar v -- Bound by lambda or case |
|---|
| 1015 | \end{code} |
|---|
| 1016 | |
|---|
| 1017 | %************************************************************************ |
|---|
| 1018 | %* * |
|---|
| 1019 | \subsection[Free-var info]{Free variable information} |
|---|
| 1020 | %* * |
|---|
| 1021 | %************************************************************************ |
|---|
| 1022 | |
|---|
| 1023 | \begin{code} |
|---|
| 1024 | type FreeVarsInfo = VarEnv (Var, HowBound, StgBinderInfo) |
|---|
| 1025 | -- The Var is so we can gather up the free variables |
|---|
| 1026 | -- as a set. |
|---|
| 1027 | -- |
|---|
| 1028 | -- The HowBound info just saves repeated lookups; |
|---|
| 1029 | -- we look up just once when we encounter the occurrence. |
|---|
| 1030 | -- INVARIANT: Any ImportBound Ids are HaveCafRef Ids |
|---|
| 1031 | -- Imported Ids without CAF refs are simply |
|---|
| 1032 | -- not put in the FreeVarsInfo for an expression. |
|---|
| 1033 | -- See singletonFVInfo and freeVarsToLiveVars |
|---|
| 1034 | -- |
|---|
| 1035 | -- StgBinderInfo records how it occurs; notably, we |
|---|
| 1036 | -- are interested in whether it only occurs in saturated |
|---|
| 1037 | -- applications, because then we don't need to build a |
|---|
| 1038 | -- curried version. |
|---|
| 1039 | -- If f is mapped to noBinderInfo, that means |
|---|
| 1040 | -- that f *is* mentioned (else it wouldn't be in the |
|---|
| 1041 | -- IdEnv at all), but perhaps in an unsaturated applications. |
|---|
| 1042 | -- |
|---|
| 1043 | -- All case/lambda-bound things are also mapped to |
|---|
| 1044 | -- noBinderInfo, since we aren't interested in their |
|---|
| 1045 | -- occurence info. |
|---|
| 1046 | -- |
|---|
| 1047 | -- For ILX we track free var info for type variables too; |
|---|
| 1048 | -- hence VarEnv not IdEnv |
|---|
| 1049 | \end{code} |
|---|
| 1050 | |
|---|
| 1051 | \begin{code} |
|---|
| 1052 | emptyFVInfo :: FreeVarsInfo |
|---|
| 1053 | emptyFVInfo = emptyVarEnv |
|---|
| 1054 | |
|---|
| 1055 | singletonFVInfo :: Id -> HowBound -> StgBinderInfo -> FreeVarsInfo |
|---|
| 1056 | -- Don't record non-CAF imports at all, to keep free-var sets small |
|---|
| 1057 | singletonFVInfo id ImportBound info |
|---|
| 1058 | | mayHaveCafRefs (idCafInfo id) = unitVarEnv id (id, ImportBound, info) |
|---|
| 1059 | | otherwise = emptyVarEnv |
|---|
| 1060 | singletonFVInfo id how_bound info = unitVarEnv id (id, how_bound, info) |
|---|
| 1061 | |
|---|
| 1062 | unionFVInfo :: FreeVarsInfo -> FreeVarsInfo -> FreeVarsInfo |
|---|
| 1063 | unionFVInfo fv1 fv2 = plusVarEnv_C plusFVInfo fv1 fv2 |
|---|
| 1064 | |
|---|
| 1065 | unionFVInfos :: [FreeVarsInfo] -> FreeVarsInfo |
|---|
| 1066 | unionFVInfos fvs = foldr unionFVInfo emptyFVInfo fvs |
|---|
| 1067 | |
|---|
| 1068 | minusFVBinders :: [Id] -> FreeVarsInfo -> FreeVarsInfo |
|---|
| 1069 | minusFVBinders vs fv = foldr minusFVBinder fv vs |
|---|
| 1070 | |
|---|
| 1071 | minusFVBinder :: Id -> FreeVarsInfo -> FreeVarsInfo |
|---|
| 1072 | minusFVBinder v fv = fv `delVarEnv` v |
|---|
| 1073 | -- When removing a binder, remember to add its type variables |
|---|
| 1074 | -- c.f. CoreFVs.delBinderFV |
|---|
| 1075 | |
|---|
| 1076 | elementOfFVInfo :: Id -> FreeVarsInfo -> Bool |
|---|
| 1077 | elementOfFVInfo id fvs = maybeToBool (lookupVarEnv fvs id) |
|---|
| 1078 | |
|---|
| 1079 | lookupFVInfo :: FreeVarsInfo -> Id -> StgBinderInfo |
|---|
| 1080 | -- Find how the given Id is used. |
|---|
| 1081 | -- Externally visible things may be used any old how |
|---|
| 1082 | lookupFVInfo fvs id |
|---|
| 1083 | | isExternalName (idName id) = noBinderInfo |
|---|
| 1084 | | otherwise = case lookupVarEnv fvs id of |
|---|
| 1085 | Nothing -> noBinderInfo |
|---|
| 1086 | Just (_,_,info) -> info |
|---|
| 1087 | |
|---|
| 1088 | allFreeIds :: FreeVarsInfo -> [(Id,HowBound)] -- Both top level and non-top-level Ids |
|---|
| 1089 | allFreeIds fvs = ASSERT( all (isId . fst) ids ) ids |
|---|
| 1090 | where |
|---|
| 1091 | ids = [(id,how_bound) | (id,how_bound,_) <- varEnvElts fvs] |
|---|
| 1092 | |
|---|
| 1093 | -- Non-top-level things only, both type variables and ids |
|---|
| 1094 | getFVs :: FreeVarsInfo -> [Var] |
|---|
| 1095 | getFVs fvs = [id | (id, how_bound, _) <- varEnvElts fvs, |
|---|
| 1096 | not (topLevelBound how_bound) ] |
|---|
| 1097 | |
|---|
| 1098 | getFVSet :: FreeVarsInfo -> VarSet |
|---|
| 1099 | getFVSet fvs = mkVarSet (getFVs fvs) |
|---|
| 1100 | |
|---|
| 1101 | plusFVInfo :: (Var, HowBound, StgBinderInfo) |
|---|
| 1102 | -> (Var, HowBound, StgBinderInfo) |
|---|
| 1103 | -> (Var, HowBound, StgBinderInfo) |
|---|
| 1104 | plusFVInfo (id1,hb1,info1) (id2,hb2,info2) |
|---|
| 1105 | = ASSERT (id1 == id2 && hb1 `check_eq_how_bound` hb2) |
|---|
| 1106 | (id1, hb1, combineStgBinderInfo info1 info2) |
|---|
| 1107 | |
|---|
| 1108 | -- The HowBound info for a variable in the FVInfo should be consistent |
|---|
| 1109 | check_eq_how_bound :: HowBound -> HowBound -> Bool |
|---|
| 1110 | check_eq_how_bound ImportBound ImportBound = True |
|---|
| 1111 | check_eq_how_bound LambdaBound LambdaBound = True |
|---|
| 1112 | check_eq_how_bound (LetBound li1 ar1) (LetBound li2 ar2) = ar1 == ar2 && check_eq_li li1 li2 |
|---|
| 1113 | check_eq_how_bound _ _ = False |
|---|
| 1114 | |
|---|
| 1115 | check_eq_li :: LetInfo -> LetInfo -> Bool |
|---|
| 1116 | check_eq_li (NestedLet _) (NestedLet _) = True |
|---|
| 1117 | check_eq_li TopLet TopLet = True |
|---|
| 1118 | check_eq_li _ _ = False |
|---|
| 1119 | \end{code} |
|---|
| 1120 | |
|---|
| 1121 | Misc. |
|---|
| 1122 | \begin{code} |
|---|
| 1123 | filterStgBinders :: [Var] -> [Var] |
|---|
| 1124 | filterStgBinders bndrs = filter isId bndrs |
|---|
| 1125 | \end{code} |
|---|
| 1126 | |
|---|
| 1127 | |
|---|
| 1128 | \begin{code} |
|---|
| 1129 | myCollectBinders :: Expr Var -> ([Var], Expr Var) |
|---|
| 1130 | myCollectBinders expr |
|---|
| 1131 | = go [] expr |
|---|
| 1132 | where |
|---|
| 1133 | go bs (Lam b e) = go (b:bs) e |
|---|
| 1134 | go bs e@(Tick t e') |
|---|
| 1135 | | tickishIsCode t = (reverse bs, e) |
|---|
| 1136 | | otherwise = go bs e' |
|---|
| 1137 | -- Ignore only non-code source annotations |
|---|
| 1138 | go bs (Cast e _) = go bs e |
|---|
| 1139 | go bs e = (reverse bs, e) |
|---|
| 1140 | |
|---|
| 1141 | myCollectArgs :: CoreExpr -> (Id, [CoreArg]) |
|---|
| 1142 | -- We assume that we only have variables |
|---|
| 1143 | -- in the function position by now |
|---|
| 1144 | myCollectArgs expr |
|---|
| 1145 | = go expr [] |
|---|
| 1146 | where |
|---|
| 1147 | go (Var v) as = (v, as) |
|---|
| 1148 | go (App f a) as = go f (a:as) |
|---|
| 1149 | go (Tick _ _) _ = pprPanic "CoreToStg.myCollectArgs" (ppr expr) |
|---|
| 1150 | go (Cast e _) as = go e as |
|---|
| 1151 | go (Lam b e) as |
|---|
| 1152 | | isTyVar b = go e as -- Note [Collect args] |
|---|
| 1153 | go _ _ = pprPanic "CoreToStg.myCollectArgs" (ppr expr) |
|---|
| 1154 | \end{code} |
|---|
| 1155 | |
|---|
| 1156 | Note [Collect args] |
|---|
| 1157 | ~~~~~~~~~~~~~~~~~~~ |
|---|
| 1158 | This big-lambda case occurred following a rather obscure eta expansion. |
|---|
| 1159 | It all seems a bit yukky to me. |
|---|
| 1160 | |
|---|
| 1161 | \begin{code} |
|---|
| 1162 | stgArity :: Id -> HowBound -> Arity |
|---|
| 1163 | stgArity _ (LetBound _ arity) = arity |
|---|
| 1164 | stgArity f ImportBound = idArity f |
|---|
| 1165 | stgArity _ LambdaBound = 0 |
|---|
| 1166 | \end{code} |
|---|