diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2014-03-18 17:10:18 +0000 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2014-03-18 17:10:46 +0000 |
commit | 87bbc69c40d36046492d754c8d7ff02c3be6ce43 (patch) | |
tree | c3da2b3a6a5759f3da1c7c9494a3de50ca60d7d0 /compiler/simplCore/Simplify.lhs | |
parent | 696bfc4ba5fce6b75cc91bcb67c5d0a3c9f29bd2 (diff) | |
download | haskell-87bbc69c40d36046492d754c8d7ff02c3be6ce43.tar.gz |
Make sure we occurrence-analyse unfoldings (fixes Trac #8892)
For DFunUnfoldings we were failing to occurrence-analyse the unfolding,
and that meant that a loop breaker wasn't marked as such, which in turn
meant it was inlined away when it still had occurrence sites. See
Note [Occurrrence analysis of unfoldings] in CoreUnfold.
This is a pretty long-standing bug, happily nailed by John Lato.
Diffstat (limited to 'compiler/simplCore/Simplify.lhs')
-rw-r--r-- | compiler/simplCore/Simplify.lhs | 78 |
1 files changed, 38 insertions, 40 deletions
diff --git a/compiler/simplCore/Simplify.lhs b/compiler/simplCore/Simplify.lhs index 129f6ef3e9..e1327a6b7f 100644 --- a/compiler/simplCore/Simplify.lhs +++ b/compiler/simplCore/Simplify.lhs @@ -730,53 +730,51 @@ simplUnfolding :: SimplEnv-> TopLevelFlag -> OutExpr -> Unfolding -> SimplM Unfolding -- Note [Setting the new unfolding] -simplUnfolding env _ _ _ df@(DFunUnfolding { df_bndrs = bndrs, df_args = args }) - = do { (env', bndrs') <- simplBinders env bndrs - ; args' <- mapM (simplExpr env') args - ; return (df { df_bndrs = bndrs', df_args = args' }) } - -simplUnfolding env top_lvl id _ - (CoreUnfolding { uf_tmpl = expr, uf_arity = arity - , uf_src = src, uf_guidance = guide }) - | isStableSource src - = do { expr' <- simplExpr rule_env expr - ; let is_top_lvl = isTopLevel top_lvl - ; case guide of - UnfWhen sat_ok _ -- Happens for INLINE things - -> let guide' = UnfWhen sat_ok (inlineBoringOk expr') - -- Refresh the boring-ok flag, in case expr' - -- has got small. This happens, notably in the inlinings - -- for dfuns for single-method classes; see - -- Note [Single-method classes] in TcInstDcls. - -- A test case is Trac #4138 - in return (mkCoreUnfolding src is_top_lvl expr' arity guide') - -- See Note [Top-level flag on inline rules] in CoreUnfold - - _other -- Happens for INLINABLE things - -> let bottoming = isBottomingId id - in bottoming `seq` -- See Note [Force bottoming field] - do dflags <- getDynFlags - return (mkUnfolding dflags src is_top_lvl bottoming expr') +simplUnfolding env top_lvl id new_rhs unf + = case unf of + DFunUnfolding { df_bndrs = bndrs, df_con = con, df_args = args } + -> do { (env', bndrs') <- simplBinders rule_env bndrs + ; args' <- mapM (simplExpr env') args + ; return (mkDFunUnfolding bndrs' con args') } + + CoreUnfolding { uf_tmpl = expr, uf_arity = arity + , uf_src = src, uf_guidance = guide } + | isStableSource src + -> do { expr' <- simplExpr rule_env expr + ; case guide of + UnfWhen sat_ok _ -- Happens for INLINE things + -> let guide' = UnfWhen sat_ok (inlineBoringOk expr') + -- Refresh the boring-ok flag, in case expr' + -- has got small. This happens, notably in the inlinings + -- for dfuns for single-method classes; see + -- Note [Single-method classes] in TcInstDcls. + -- A test case is Trac #4138 + in return (mkCoreUnfolding src is_top_lvl expr' arity guide') + -- See Note [Top-level flag on inline rules] in CoreUnfold + + _other -- Happens for INLINABLE things + -> bottoming `seq` -- See Note [Force bottoming field] + do { dflags <- getDynFlags + ; return (mkUnfolding dflags src is_top_lvl bottoming expr') } } -- If the guidance is UnfIfGoodArgs, this is an INLINABLE -- unfolding, and we need to make sure the guidance is kept up -- to date with respect to any changes in the unfolding. - } + + _other -> bottoming `seq` -- See Note [Force bottoming field] + do { dflags <- getDynFlags + ; return (mkUnfolding dflags InlineRhs is_top_lvl bottoming new_rhs) } + -- We make an unfolding *even for loop-breakers*. + -- Reason: (a) It might be useful to know that they are WHNF + -- (b) In TidyPgm we currently assume that, if we want to + -- expose the unfolding then indeed we *have* an unfolding + -- to expose. (We could instead use the RHS, but currently + -- we don't.) The simple thing is always to have one. where + bottoming = isBottomingId id + is_top_lvl = isTopLevel top_lvl act = idInlineActivation id rule_env = updMode (updModeForInlineRules act) env -- See Note [Simplifying inside InlineRules] in SimplUtils - -simplUnfolding _ top_lvl id new_rhs _ - = let bottoming = isBottomingId id - in bottoming `seq` -- See Note [Force bottoming field] - do dflags <- getDynFlags - return (mkUnfolding dflags InlineRhs (isTopLevel top_lvl) bottoming new_rhs) - -- We make an unfolding *even for loop-breakers*. - -- Reason: (a) It might be useful to know that they are WHNF - -- (b) In TidyPgm we currently assume that, if we want to - -- expose the unfolding then indeed we *have* an unfolding - -- to expose. (We could instead use the RHS, but currently - -- we don't.) The simple thing is always to have one. \end{code} Note [Force bottoming field] |