summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Opt/CprAnal.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core/Opt/CprAnal.hs')
-rw-r--r--compiler/GHC/Core/Opt/CprAnal.hs11
1 files changed, 9 insertions, 2 deletions
diff --git a/compiler/GHC/Core/Opt/CprAnal.hs b/compiler/GHC/Core/Opt/CprAnal.hs
index 87d9eb2ec7..5199635c4e 100644
--- a/compiler/GHC/Core/Opt/CprAnal.hs
+++ b/compiler/GHC/Core/Opt/CprAnal.hs
@@ -297,9 +297,16 @@ data TermFlag -- Better than using a Bool
-- See Note [Nested CPR]
exprTerminates :: CoreExpr -> TermFlag
+-- ^ A /very/ simple termination analysis.
exprTerminates e
- | exprIsHNF e = Terminates -- A /very/ simple termination analysis.
- | otherwise = MightDiverge
+ | exprIsHNF e = Terminates
+ | exprOkForSpeculation e = Terminates
+ | otherwise = MightDiverge
+ -- Annyingly, we have to check both for HNF and ok-for-spec.
+ -- * `I# (x# *# 2#)` is ok-for-spec, but not in HNF. Still worth CPR'ing!
+ -- * `lvl` is an HNF if its unfolding is evaluated
+ -- (perhaps `lvl = I# 0#` at top-level). But, tiresomely, it is never
+ -- ok-for-spec due to Note [exprOkForSpeculation and evaluated variables].
cprAnalApp :: AnalEnv -> CoreExpr -> [(CprType, CoreArg)] -> (CprType, CoreExpr)
-- Main function that takes care of /nested/ CPR. See Note [Nested CPR]