summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Opt
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core/Opt')
-rw-r--r--compiler/GHC/Core/Opt/Arity.hs2
-rw-r--r--compiler/GHC/Core/Opt/ConstantFold.hs6
-rw-r--r--compiler/GHC/Core/Opt/CprAnal.hs11
-rw-r--r--compiler/GHC/Core/Opt/DmdAnal.hs4
-rw-r--r--compiler/GHC/Core/Opt/Simplify/Env.hs11
-rw-r--r--compiler/GHC/Core/Opt/Simplify/Iteration.hs15
6 files changed, 27 insertions, 22 deletions
diff --git a/compiler/GHC/Core/Opt/Arity.hs b/compiler/GHC/Core/Opt/Arity.hs
index 3716dc6ea0..33abf5e640 100644
--- a/compiler/GHC/Core/Opt/Arity.hs
+++ b/compiler/GHC/Core/Opt/Arity.hs
@@ -1443,7 +1443,7 @@ myExprIsCheap (AE { am_opts = opts, am_sigs = sigs }) e mb_ty
-- See Note [Eta expanding through dictionaries]
-- See Note [Eta expanding through CallStacks]
- cheap_fun e = exprIsCheapX (myIsCheapApp sigs) e
+ cheap_fun e = exprIsCheapX (myIsCheapApp sigs) False e
-- | A version of 'isCheapApp' that considers results from arity analysis.
-- See Note [Arity analysis] for what's in the signature environment and why
diff --git a/compiler/GHC/Core/Opt/ConstantFold.hs b/compiler/GHC/Core/Opt/ConstantFold.hs
index 86fdc5cdb5..3c2c1348d1 100644
--- a/compiler/GHC/Core/Opt/ConstantFold.hs
+++ b/compiler/GHC/Core/Opt/ConstantFold.hs
@@ -46,7 +46,7 @@ import GHC.Core
import GHC.Core.Make
import GHC.Core.SimpleOpt ( exprIsConApp_maybe, exprIsLiteral_maybe )
import GHC.Core.DataCon ( DataCon,dataConTagZ, dataConTyCon, dataConWrapId, dataConWorkId )
-import GHC.Core.Utils ( cheapEqExpr, exprIsHNF
+import GHC.Core.Utils ( cheapEqExpr, exprOkForSpeculation
, stripTicksTop, stripTicksTopT, mkTicks )
import GHC.Core.Multiplicity
import GHC.Core.Rules.Config
@@ -1932,7 +1932,7 @@ Things to note
Implementing seq#. The compiler has magic for SeqOp in
-- GHC.Core.Opt.ConstantFold.seqRule: eliminate (seq# <whnf> s)
+- GHC.Core.Opt.ConstantFold.seqRule: eliminate (seq# <ok-for-spec> s)
- GHC.StgToCmm.Expr.cgExpr, and cgCase: special case for seq#
@@ -1947,7 +1947,7 @@ Implementing seq#. The compiler has magic for SeqOp in
seqRule :: RuleM CoreExpr
seqRule = do
[Type _ty_a, Type _ty_s, a, s] <- getArgs
- guard $ exprIsHNF a
+ guard $ exprOkForSpeculation a
return $ mkCoreUnboxedTuple [s, a]
-- spark# :: forall a s . a -> State# s -> (# State# s, a #)
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]
diff --git a/compiler/GHC/Core/Opt/DmdAnal.hs b/compiler/GHC/Core/Opt/DmdAnal.hs
index 0bcabf55d3..d495d93245 100644
--- a/compiler/GHC/Core/Opt/DmdAnal.hs
+++ b/compiler/GHC/Core/Opt/DmdAnal.hs
@@ -814,6 +814,10 @@ to the Divergence lattice, but in practice it turned out to be hard to untaint
from 'topDiv' to 'conDiv', leading to bugs, performance regressions and
complexity that didn't justify the single fixed testcase T13380c.
+You might think that we should check for side-effects rather than just for
+precise exceptions. Right you are! See Note [Side-effects and strictness]
+for why we unfortunately do not.
+
Note [Demand analysis for recursive data constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T11545 features a single-product, recursive data type
diff --git a/compiler/GHC/Core/Opt/Simplify/Env.hs b/compiler/GHC/Core/Opt/Simplify/Env.hs
index 759f6e24fa..07f84cc7de 100644
--- a/compiler/GHC/Core/Opt/Simplify/Env.hs
+++ b/compiler/GHC/Core/Opt/Simplify/Env.hs
@@ -8,14 +8,13 @@
module GHC.Core.Opt.Simplify.Env (
-- * The simplifier mode
- SimplMode(..), updMode,
- smPedanticBottoms, smPlatform,
+ SimplMode(..), updMode, smPlatform,
-- * Environments
SimplEnv(..), pprSimplEnv, -- Temp not abstract
seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
- seOptCoercionOpts, sePedanticBottoms, sePhase, sePlatform, sePreInline,
+ seOptCoercionOpts, sePhase, sePlatform, sePreInline,
seRuleOpts, seRules, seUnfoldingOpts,
mkSimplEnv, extendIdSubst,
extendTvSubst, extendCvSubst,
@@ -216,9 +215,6 @@ seNames env = sm_names (seMode env)
seOptCoercionOpts :: SimplEnv -> OptCoercionOpts
seOptCoercionOpts env = sm_co_opt_opts (seMode env)
-sePedanticBottoms :: SimplEnv -> Bool
-sePedanticBottoms env = smPedanticBottoms (seMode env)
-
sePhase :: SimplEnv -> CompilerPhase
sePhase env = sm_phase (seMode env)
@@ -273,9 +269,6 @@ instance Outputable SimplMode where
where
pp_flag f s = ppUnless f (text "no") <+> s
-smPedanticBottoms :: SimplMode -> Bool
-smPedanticBottoms opts = ao_ped_bot (sm_arity_opts opts)
-
smPlatform :: SimplMode -> Platform
smPlatform opts = roPlatform (sm_rule_opts opts)
diff --git a/compiler/GHC/Core/Opt/Simplify/Iteration.hs b/compiler/GHC/Core/Opt/Simplify/Iteration.hs
index 07ea775fc0..cf83b44be9 100644
--- a/compiler/GHC/Core/Opt/Simplify/Iteration.hs
+++ b/compiler/GHC/Core/Opt/Simplify/Iteration.hs
@@ -32,7 +32,7 @@ import GHC.Core.Reduction
import GHC.Core.Coercion.Opt ( optCoercion )
import GHC.Core.FamInstEnv ( FamInstEnv, topNormaliseType_maybe )
import GHC.Core.DataCon
- ( DataCon, dataConWorkId, dataConRepStrictness
+ ( DataCon, dataConWorkId, dataConRepStrictness, dataConRepStrictness_maybe
, dataConRepArgTys, isUnboxedTupleDataCon
, StrictnessMark (..) )
import GHC.Core.Opt.Stats ( Tick(..) )
@@ -2094,14 +2094,14 @@ zap the SubstEnv. This is VITAL. Consider
We'll clone the inner \x, adding x->x' in the id_subst Then when we
inline y, we must *not* replace x by x' in the inlined copy!!
-Note [Fast path for data constructors]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Note [Fast path for lazy data constructors]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For applications of a data constructor worker, the full glory of
rebuildCall is a waste of effort;
* They never inline, obviously
* They have no rewrite rules
-* They are not strict (see Note [Data-con worker strictness]
- in GHC.Core.DataCon)
+* Though they might be strict (see Note [Strict fields in Core] in GHC.Core),
+ we will exploit that strictness through their demand signature
So it's fine to zoom straight to `rebuild` which just rebuilds the
call in a very straightforward way.
@@ -2125,7 +2125,8 @@ simplVar env var
simplIdF :: SimplEnv -> InId -> SimplCont -> SimplM (SimplFloats, OutExpr)
simplIdF env var cont
- | isDataConWorkId var -- See Note [Fast path for data constructors]
+ | Just dc <- isDataConWorkId_maybe var -- See Note [Fast path for lazy data constructors]
+ , Nothing <- dataConRepStrictness_maybe dc
= rebuild env (Var var) cont
| otherwise
= case substId env var of
@@ -3304,7 +3305,7 @@ a case pattern. This is *important*. Consider
We really must record that b is already evaluated so that we don't
go and re-evaluate it when constructing the result.
-See Note [Data-con worker strictness] in GHC.Core.DataCon
+See Note [Strict fields in Core] in GHC.Core.
NB: simplLamBndrs preserves this eval info