summaryrefslogtreecommitdiff
path: root/compiler/simplCore
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2019-01-28 16:49:04 +0100
committerSebastian Graf <sebastian.graf@kit.edu>2020-02-12 11:00:58 +0100
commit059c3c9d7c84fc37c69e9f414ff736d47081e72c (patch)
treeda3c17ac002b9c6d31542af78553769fd40d5d65 /compiler/simplCore
parentf0c0ee7d9a942a19361e72553cd08f42cc12b04a (diff)
downloadhaskell-059c3c9d7c84fc37c69e9f414ff736d47081e72c.tar.gz
Separate CPR analysis from the Demand analyserwip/sep-cpr
The reasons for that can be found in the wiki: https://gitlab.haskell.org/ghc/ghc/wikis/nested-cpr/split-off-cpr We now run CPR after demand analysis (except for after the final demand analysis run just before code gen). CPR got its own dump flags (`-ddump-cpr-anal`, `-ddump-cpr-signatures`), but not its own flag to activate/deactivate. It will run with `-fstrictness`/`-fworker-wrapper`. As explained on the wiki page, this step is necessary for a sane Nested CPR analysis. And it has quite positive impact on compiler performance: Metric Decrease: T9233 T9675 T9961 T15263
Diffstat (limited to 'compiler/simplCore')
-rw-r--r--compiler/simplCore/CallArity.hs2
-rw-r--r--compiler/simplCore/CoreMonad.hs6
-rw-r--r--compiler/simplCore/SetLevels.hs2
-rw-r--r--compiler/simplCore/SimplCore.hs21
-rw-r--r--compiler/simplCore/SimplUtils.hs4
-rw-r--r--compiler/simplCore/Simplify.hs12
6 files changed, 29 insertions, 18 deletions
diff --git a/compiler/simplCore/CallArity.hs b/compiler/simplCore/CallArity.hs
index 75c55c698c..d3709ac82a 100644
--- a/compiler/simplCore/CallArity.hs
+++ b/compiler/simplCore/CallArity.hs
@@ -701,7 +701,7 @@ trimArity v a = minimum [a, max_arity_by_type, max_arity_by_strsig]
where
max_arity_by_type = length (typeArity (idType v))
max_arity_by_strsig
- | isBotRes result_info = length demands
+ | isBotDiv result_info = length demands
| otherwise = a
(demands, result_info) = splitStrictSig (idStrictness v)
diff --git a/compiler/simplCore/CoreMonad.hs b/compiler/simplCore/CoreMonad.hs
index 672b56e64f..24567cb1c3 100644
--- a/compiler/simplCore/CoreMonad.hs
+++ b/compiler/simplCore/CoreMonad.hs
@@ -107,7 +107,8 @@ data CoreToDo -- These are diff core-to-core passes,
| CoreDoStaticArgs
| CoreDoCallArity
| CoreDoExitify
- | CoreDoStrictness
+ | CoreDoDemand
+ | CoreDoCpr
| CoreDoWorkerWrapper
| CoreDoSpecialising
| CoreDoSpecConstr
@@ -134,7 +135,8 @@ instance Outputable CoreToDo where
ppr CoreDoStaticArgs = text "Static argument"
ppr CoreDoCallArity = text "Called arity analysis"
ppr CoreDoExitify = text "Exitification transformation"
- ppr CoreDoStrictness = text "Demand analysis"
+ ppr CoreDoDemand = text "Demand analysis"
+ ppr CoreDoCpr = text "Constructed Product Result analysis"
ppr CoreDoWorkerWrapper = text "Worker Wrapper binds"
ppr CoreDoSpecialising = text "Specialise"
ppr CoreDoSpecConstr = text "SpecConstr"
diff --git a/compiler/simplCore/SetLevels.hs b/compiler/simplCore/SetLevels.hs
index 7cf0b9d524..8f70df9d79 100644
--- a/compiler/simplCore/SetLevels.hs
+++ b/compiler/simplCore/SetLevels.hs
@@ -88,6 +88,7 @@ import UniqDSet ( getUniqDSet )
import VarEnv
import Literal ( litIsTrivial )
import Demand ( StrictSig, Demand, isStrictDmd, splitStrictSig, increaseStrictSigArity )
+import Cpr ( mkCprSig, botCpr )
import Name ( getOccName, mkSystemVarName )
import OccName ( occNameString )
import Type ( Type, mkLamTypes, splitTyConApp_maybe, tyCoVarsOfType
@@ -983,6 +984,7 @@ annotateBotStr id n_extra mb_str
Nothing -> id
Just (arity, sig) -> id `setIdArity` (arity + n_extra)
`setIdStrictness` (increaseStrictSigArity n_extra sig)
+ `setIdCprInfo` mkCprSig (arity + n_extra) botCpr
notWorthFloating :: CoreExpr -> [Var] -> Bool
-- Returns True if the expression would be replaced by
diff --git a/compiler/simplCore/SimplCore.hs b/compiler/simplCore/SimplCore.hs
index 026631df37..4c7e509f4c 100644
--- a/compiler/simplCore/SimplCore.hs
+++ b/compiler/simplCore/SimplCore.hs
@@ -45,6 +45,7 @@ import SAT ( doStaticArgs )
import Specialise ( specProgram)
import SpecConstr ( specConstrProgram)
import DmdAnal ( dmdAnalProgram )
+import CprAnal ( cprAnalProgram )
import CallArity ( callArityAnalProgram )
import Exitify ( exitifyProgram )
import WorkWrap ( wwTopBinds )
@@ -141,7 +142,7 @@ getCoreToDo dflags
maybe_rule_check phase = runMaybe rule_check (CoreDoRuleCheck phase)
maybe_strictness_before phase
- = runWhen (phase `elem` strictnessBefore dflags) CoreDoStrictness
+ = runWhen (phase `elem` strictnessBefore dflags) CoreDoDemand
base_mode = SimplMode { sm_phase = panic "base_mode"
, sm_names = []
@@ -175,14 +176,12 @@ getCoreToDo dflags
-- Don't do case-of-case transformations.
-- This makes full laziness work better
- strictness_pass = if ww_on
- then [CoreDoStrictness,CoreDoWorkerWrapper]
- else [CoreDoStrictness]
+ dmd_cpr_ww = if ww_on then [CoreDoDemand,CoreDoCpr,CoreDoWorkerWrapper]
+ else [CoreDoDemand,CoreDoCpr]
- -- New demand analyser
demand_analyser = (CoreDoPasses (
- strictness_pass ++
+ dmd_cpr_ww ++
[simpl_phase 0 ["post-worker-wrapper"] max_iter]
))
@@ -332,7 +331,7 @@ getCoreToDo dflags
simpl_phase 0 ["final"] max_iter,
runWhen late_dmd_anal $ CoreDoPasses (
- strictness_pass ++
+ dmd_cpr_ww ++
[simpl_phase 0 ["post-late-ww"] max_iter]
),
@@ -341,7 +340,7 @@ getCoreToDo dflags
-- has run at all. See Note [Final Demand Analyser run] in DmdAnal
-- It is EXTREMELY IMPORTANT to run this pass, otherwise execution
-- can become /exponentially/ more expensive. See #11731, #12996.
- runWhen (strictness || late_dmd_anal) CoreDoStrictness,
+ runWhen (strictness || late_dmd_anal) CoreDoDemand,
maybe_rule_check (Phase 0)
]
@@ -445,9 +444,12 @@ doCorePass CoreDoCallArity = {-# SCC "CallArity" #-}
doCorePass CoreDoExitify = {-# SCC "Exitify" #-}
doPass exitifyProgram
-doCorePass CoreDoStrictness = {-# SCC "NewStranal" #-}
+doCorePass CoreDoDemand = {-# SCC "DmdAnal" #-}
doPassDFM dmdAnalProgram
+doCorePass CoreDoCpr = {-# SCC "CprAnal" #-}
+ doPassDFM cprAnalProgram
+
doCorePass CoreDoWorkerWrapper = {-# SCC "WorkWrap" #-}
doPassDFU wwTopBinds
@@ -1020,6 +1022,7 @@ transferIdInfo exported_id local_id
where
local_info = idInfo local_id
transfer exp_info = exp_info `setStrictnessInfo` strictnessInfo local_info
+ `setCprInfo` cprInfo local_info
`setUnfoldingInfo` unfoldingInfo local_info
`setInlinePragInfo` inlinePragInfo local_info
`setRuleInfo` addRuleInfo (ruleInfo exp_info) new_info
diff --git a/compiler/simplCore/SimplUtils.hs b/compiler/simplCore/SimplUtils.hs
index 5c653c7adb..03c4b8ebd6 100644
--- a/compiler/simplCore/SimplUtils.hs
+++ b/compiler/simplCore/SimplUtils.hs
@@ -499,7 +499,7 @@ mkArgInfo env fun rules n_val_args call_cont
-- top-level bindings for (say) strings into
-- calls to error. But now we are more careful about
-- inlining lone variables, so its ok (see SimplUtils.analyseCont)
- if isBotRes result_info then
+ if isBotDiv result_info then
map isStrictDmd demands -- Finite => result is bottom
else
map isStrictDmd demands ++ vanilla_stricts
@@ -1575,7 +1575,7 @@ arguments!
Note [Do not eta-expand join points]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Similarly to CPR (see Note [Don't CPR join points] in WorkWrap), a join point
+Similarly to CPR (see Note [Don't w/w join points for CPR] in WorkWrap), a join point
stands well to gain from its outer binding's eta-expansion, and eta-expanding a
join point is fraught with issues like how to deal with a cast:
diff --git a/compiler/simplCore/Simplify.hs b/compiler/simplCore/Simplify.hs
index 01d802c30b..50d35149d5 100644
--- a/compiler/simplCore/Simplify.hs
+++ b/compiler/simplCore/Simplify.hs
@@ -35,14 +35,15 @@ import DataCon ( DataCon, dataConWorkId, dataConRepStrictness
, StrictnessMark (..) )
import CoreMonad ( Tick(..), SimplMode(..) )
import CoreSyn
-import Demand ( StrictSig(..), dmdTypeDepth, isStrictDmd )
+import Demand ( StrictSig(..), dmdTypeDepth, isStrictDmd
+ , mkClosedStrictSig, topDmd, botDiv )
+import Cpr ( mkCprSig, botCpr )
import PprCore ( pprCoreExpr )
import CoreUnfold
import CoreUtils
import CoreOpt ( pushCoTyArg, pushCoValArg
, joinPointBinding_maybe, joinPointBindings_maybe )
import Rules ( mkRuleInfo, lookupRule, getRules )
-import Demand ( mkClosedStrictSig, topDmd, botRes )
import BasicTypes ( TopLevelFlag(..), isNotTopLevel, isTopLevel,
RecFlag(..), Arity )
import MonadUtils ( mapAccumLM, liftIO )
@@ -447,6 +448,7 @@ prepareRhs mode top_lvl occ info (Cast rhs co) -- Note [Float coercions]
; return (floats, Cast rhs' co) }
where
sanitised_info = vanillaIdInfo `setStrictnessInfo` strictnessInfo info
+ `setCprInfo` cprInfo info
`setDemandInfo` demandInfo info
prepareRhs mode top_lvl occ _ rhs0
@@ -731,8 +733,10 @@ addLetBndrInfo new_bndr new_arity is_bot new_unf
= info2
-- Bottoming bindings: see Note [Bottoming bindings]
- info4 | is_bot = info3 `setStrictnessInfo`
- mkClosedStrictSig (replicate new_arity topDmd) botRes
+ info4 | is_bot = info3
+ `setStrictnessInfo`
+ mkClosedStrictSig (replicate new_arity topDmd) botDiv
+ `setCprInfo` mkCprSig new_arity botCpr
| otherwise = info3
-- Zap call arity info. We have used it by now (via