summaryrefslogtreecommitdiff
path: root/compiler/simplCore/Simplify.lhs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2014-03-18 17:10:18 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2014-03-18 17:10:46 +0000
commit87bbc69c40d36046492d754c8d7ff02c3be6ce43 (patch)
treec3da2b3a6a5759f3da1c7c9494a3de50ca60d7d0 /compiler/simplCore/Simplify.lhs
parent696bfc4ba5fce6b75cc91bcb67c5d0a3c9f29bd2 (diff)
downloadhaskell-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.lhs78
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]