Commit f4fd98c7 authored by Joachim Breitner's avatar Joachim Breitner

Add a final demand analyzer run right before TidyCore

in order to have precise used-once information in the exported
strictness signatures, as well as precise used-once information on
thunks. This avoids the bad effects of #11731.

The subsequent worker-wrapper pass is responsible for removing the
demand environment part of the strictness signature. It does not run
after the final demand analyzer pass, so remove this also in CoreTidy.

The subsequent worker-wrapper pass is also responsible for removing
used-once-information from the demands and strictness signatures, as
these might not be preserved by the simplifier. This is _not_ done by
CoreTidy, because we _do_ want this information, as produced by the last
round of the demand analyzer, to be available to the code generator.

Differential Revision: https://phabricator.haskell.org/D2073
parent 3a34b5c3
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
\section[Demand]{@Demand@: A decoupled implementation of a demand domain} \section[Demand]{@Demand@: A decoupled implementation of a demand domain}
-} -}
{-# LANGUAGE CPP, FlexibleInstances, TypeSynonymInstances #-} {-# LANGUAGE CPP, FlexibleInstances, TypeSynonymInstances, RecordWildCards #-}
module Demand ( module Demand (
StrDmd, UseDmd(..), Count(..), StrDmd, UseDmd(..), Count(..),
...@@ -37,7 +37,7 @@ module Demand ( ...@@ -37,7 +37,7 @@ module Demand (
appIsBottom, isBottomingSig, pprIfaceStrictSig, appIsBottom, isBottomingSig, pprIfaceStrictSig,
trimCPRInfo, returnsCPR_maybe, trimCPRInfo, returnsCPR_maybe,
StrictSig(..), mkStrictSig, mkClosedStrictSig, nopSig, botSig, cprProdSig, StrictSig(..), mkStrictSig, mkClosedStrictSig, nopSig, botSig, cprProdSig,
isTopSig, splitStrictSig, increaseStrictSigArity, isTopSig, hasDemandEnvSig, splitStrictSig, increaseStrictSigArity,
seqDemand, seqDemandList, seqDmdType, seqStrictSig, seqDemand, seqDemandList, seqDmdType, seqStrictSig,
...@@ -52,7 +52,8 @@ module Demand ( ...@@ -52,7 +52,8 @@ module Demand (
trimToType, TypeShape(..), trimToType, TypeShape(..),
useCount, isUsedOnce, reuseEnv, useCount, isUsedOnce, reuseEnv,
killUsageDemand, killUsageSig, zapUsageDemand, killUsageDemand, killUsageSig, zapUsageDemand, zapUsageEnvSig,
zapUsedOnceDemand, zapUsedOnceSig,
strictifyDictDmd strictifyDictDmd
) where ) where
...@@ -1677,6 +1678,9 @@ increaseStrictSigArity arity_increase (StrictSig (DmdType env dmds res)) ...@@ -1677,6 +1678,9 @@ increaseStrictSigArity arity_increase (StrictSig (DmdType env dmds res))
isTopSig :: StrictSig -> Bool isTopSig :: StrictSig -> Bool
isTopSig (StrictSig ty) = isTopDmdType ty isTopSig (StrictSig ty) = isTopDmdType ty
hasDemandEnvSig :: StrictSig -> Bool
hasDemandEnvSig (StrictSig (DmdType env _ _)) = not (isEmptyVarEnv env)
isBottomingSig :: StrictSig -> Bool isBottomingSig :: StrictSig -> Bool
-- True if the signature diverges or throws an exception -- True if the signature diverges or throws an exception
isBottomingSig (StrictSig (DmdType _ _ res)) = isBotRes res isBottomingSig (StrictSig (DmdType _ _ res)) = isBotRes res
...@@ -1861,9 +1865,31 @@ of absence or one-shot information altogether. This is only used for performanc ...@@ -1861,9 +1865,31 @@ of absence or one-shot information altogether. This is only used for performanc
tests, to see how important they are. tests, to see how important they are.
-} -}
zapUsageEnvSig :: StrictSig -> StrictSig
-- Remove the usage environment from the demand
zapUsageEnvSig (StrictSig (DmdType _ ds r)) = mkClosedStrictSig ds r
zapUsageDemand :: Demand -> Demand zapUsageDemand :: Demand -> Demand
-- Remove the usage info, but not the strictness info, from the demand -- Remove the usage info, but not the strictness info, from the demand
zapUsageDemand = kill_usage (True, True) zapUsageDemand = kill_usage $ KillFlags
{ kf_abs = True
, kf_used_once = True
, kf_called_once = True
}
-- | Remove all 1* information (but not C1 information) from the demand
zapUsedOnceDemand :: Demand -> Demand
zapUsedOnceDemand = kill_usage $ KillFlags
{ kf_abs = False
, kf_used_once = True
, kf_called_once = False
}
-- | Remove all 1* information (but not C1 information) from the strictness
-- signature
zapUsedOnceSig :: StrictSig -> StrictSig
zapUsedOnceSig (StrictSig (DmdType env ds r))
= StrictSig (DmdType env (map zapUsedOnceDemand ds) r)
killUsageDemand :: DynFlags -> Demand -> Demand killUsageDemand :: DynFlags -> Demand -> Demand
-- See Note [Killing usage information] -- See Note [Killing usage information]
...@@ -1877,35 +1903,39 @@ killUsageSig dflags sig@(StrictSig (DmdType env ds r)) ...@@ -1877,35 +1903,39 @@ killUsageSig dflags sig@(StrictSig (DmdType env ds r))
| Just kfs <- killFlags dflags = StrictSig (DmdType env (map (kill_usage kfs) ds) r) | Just kfs <- killFlags dflags = StrictSig (DmdType env (map (kill_usage kfs) ds) r)
| otherwise = sig | otherwise = sig
type KillFlags = (Bool, Bool) data KillFlags = KillFlags
{ kf_abs :: Bool
, kf_used_once :: Bool
, kf_called_once :: Bool
}
killFlags :: DynFlags -> Maybe KillFlags killFlags :: DynFlags -> Maybe KillFlags
-- See Note [Killing usage information] -- See Note [Killing usage information]
killFlags dflags killFlags dflags
| not kill_abs && not kill_one_shot = Nothing | not kf_abs && not kf_used_once = Nothing
| otherwise = Just (kill_abs, kill_one_shot) | otherwise = Just (KillFlags {..})
where where
kill_abs = gopt Opt_KillAbsence dflags kf_abs = gopt Opt_KillAbsence dflags
kill_one_shot = gopt Opt_KillOneShot dflags kf_used_once = gopt Opt_KillOneShot dflags
kf_called_once = kf_used_once
kill_usage :: KillFlags -> Demand -> Demand kill_usage :: KillFlags -> Demand -> Demand
kill_usage kfs (JD {sd = s, ud = u}) = JD {sd = s, ud = zap_musg kfs u} kill_usage kfs (JD {sd = s, ud = u}) = JD {sd = s, ud = zap_musg kfs u}
zap_musg :: KillFlags -> ArgUse -> ArgUse zap_musg :: KillFlags -> ArgUse -> ArgUse
zap_musg (kill_abs, _) Abs zap_musg kfs Abs
| kill_abs = useTop | kf_abs kfs = useTop
| otherwise = Abs | otherwise = Abs
zap_musg kfs (Use c u) = Use (zap_count kfs c) (zap_usg kfs u) zap_musg kfs (Use c u)
| kf_used_once kfs = Use Many (zap_usg kfs u)
zap_count :: KillFlags -> Count -> Count | otherwise = Use c (zap_usg kfs u)
zap_count (_, kill_one_shot) c
| kill_one_shot = Many
| otherwise = c
zap_usg :: KillFlags -> UseDmd -> UseDmd zap_usg :: KillFlags -> UseDmd -> UseDmd
zap_usg kfs (UCall c u) = UCall (zap_count kfs c) (zap_usg kfs u) zap_usg kfs (UCall c u)
zap_usg kfs (UProd us) = UProd (map (zap_musg kfs) us) | kf_called_once kfs = UCall Many (zap_usg kfs u)
zap_usg _ u = u | otherwise = UCall c (zap_usg kfs u)
zap_usg kfs (UProd us) = UProd (map (zap_musg kfs) us)
zap_usg _ u = u
-- If the argument is a used non-newtype dictionary, give it strict -- If the argument is a used non-newtype dictionary, give it strict
-- demand. Also split the product type & demand and recur in order to -- demand. Also split the product type & demand and recur in order to
......
...@@ -47,8 +47,9 @@ module Id ( ...@@ -47,8 +47,9 @@ module Id (
setIdExported, setIdNotExported, setIdExported, setIdNotExported,
globaliseId, localiseId, globaliseId, localiseId,
setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo, setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
zapLamIdInfo, zapIdDemandInfo, zapIdUsageInfo, zapFragileIdInfo, zapLamIdInfo, zapIdDemandInfo, zapIdUsageInfo, zapIdUsageEnvInfo,
zapIdStrictness, zapIdUsedOnceInfo,
zapFragileIdInfo, zapIdStrictness,
transferPolyIdInfo, transferPolyIdInfo,
-- ** Predicates on Ids -- ** Predicates on Ids
...@@ -785,6 +786,12 @@ zapIdDemandInfo = zapInfo zapDemandInfo ...@@ -785,6 +786,12 @@ zapIdDemandInfo = zapInfo zapDemandInfo
zapIdUsageInfo :: Id -> Id zapIdUsageInfo :: Id -> Id
zapIdUsageInfo = zapInfo zapUsageInfo zapIdUsageInfo = zapInfo zapUsageInfo
zapIdUsageEnvInfo :: Id -> Id
zapIdUsageEnvInfo = zapInfo zapUsageEnvInfo
zapIdUsedOnceInfo :: Id -> Id
zapIdUsedOnceInfo = zapInfo zapUsedOnceInfo
{- {-
Note [transferPolyIdInfo] Note [transferPolyIdInfo]
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -24,7 +24,7 @@ module IdInfo ( ...@@ -24,7 +24,7 @@ module IdInfo (
-- ** Zapping various forms of Info -- ** Zapping various forms of Info
zapLamInfo, zapFragileInfo, zapLamInfo, zapFragileInfo,
zapDemandInfo, zapUsageInfo, zapDemandInfo, zapUsageInfo, zapUsageEnvInfo, zapUsedOnceInfo,
-- ** The ArityInfo type -- ** The ArityInfo type
ArityInfo, ArityInfo,
...@@ -470,6 +470,19 @@ zapDemandInfo info = Just (info {demandInfo = topDmd}) ...@@ -470,6 +470,19 @@ zapDemandInfo info = Just (info {demandInfo = topDmd})
zapUsageInfo :: IdInfo -> Maybe IdInfo zapUsageInfo :: IdInfo -> Maybe IdInfo
zapUsageInfo info = Just (info {demandInfo = zapUsageDemand (demandInfo info)}) zapUsageInfo info = Just (info {demandInfo = zapUsageDemand (demandInfo info)})
-- | Remove usage environment info from the strictness signature on the 'IdInfo'
zapUsageEnvInfo :: IdInfo -> Maybe IdInfo
zapUsageEnvInfo info
| hasDemandEnvSig (strictnessInfo info)
= Just (info {strictnessInfo = zapUsageEnvSig (strictnessInfo info)})
| otherwise
= Nothing
zapUsedOnceInfo :: IdInfo -> Maybe IdInfo
zapUsedOnceInfo info
= Just $ info { strictnessInfo = zapUsedOnceSig (strictnessInfo info)
, demandInfo = zapUsedOnceDemand (demandInfo info) }
zapFragileInfo :: IdInfo -> Maybe IdInfo zapFragileInfo :: IdInfo -> Maybe IdInfo
-- ^ Zap info that depends on free variables -- ^ Zap info that depends on free variables
zapFragileInfo info zapFragileInfo info
......
...@@ -18,6 +18,7 @@ import CoreSyn ...@@ -18,6 +18,7 @@ import CoreSyn
import CoreArity import CoreArity
import Id import Id
import IdInfo import IdInfo
import Demand ( zapUsageEnvSig )
import Type( tidyType, tidyTyCoVarBndr ) import Type( tidyType, tidyTyCoVarBndr )
import Coercion( tidyCo ) import Coercion( tidyCo )
import Var import Var
...@@ -187,6 +188,8 @@ tidyLetBndr rec_tidy_env env@(tidy_env, var_env) (id,rhs) ...@@ -187,6 +188,8 @@ tidyLetBndr rec_tidy_env env@(tidy_env, var_env) (id,rhs)
-- --
-- Similarly for the demand info - on a let binder, this tells -- Similarly for the demand info - on a let binder, this tells
-- CorePrep to turn the let into a case. -- CorePrep to turn the let into a case.
-- But: Remove the usage demand here
-- (See Note [Zapping DmdEnv after Demand Analyzer] in WorkWrap)
-- --
-- Similarly arity info for eta expansion in CorePrep -- Similarly arity info for eta expansion in CorePrep
-- --
...@@ -196,7 +199,7 @@ tidyLetBndr rec_tidy_env env@(tidy_env, var_env) (id,rhs) ...@@ -196,7 +199,7 @@ tidyLetBndr rec_tidy_env env@(tidy_env, var_env) (id,rhs)
new_info = vanillaIdInfo new_info = vanillaIdInfo
`setOccInfo` occInfo old_info `setOccInfo` occInfo old_info
`setArityInfo` exprArity rhs `setArityInfo` exprArity rhs
`setStrictnessInfo` strictnessInfo old_info `setStrictnessInfo` zapUsageEnvSig (strictnessInfo old_info)
`setDemandInfo` demandInfo old_info `setDemandInfo` demandInfo old_info
`setInlinePragInfo` inlinePragInfo old_info `setInlinePragInfo` inlinePragInfo old_info
`setUnfoldingInfo` new_unf `setUnfoldingInfo` new_unf
......
...@@ -319,6 +319,11 @@ getCoreToDo dflags ...@@ -319,6 +319,11 @@ getCoreToDo dflags
[simpl_phase 0 ["post-late-ww"] max_iter] [simpl_phase 0 ["post-late-ww"] max_iter]
), ),
-- Final run of the demand_analyser, ensures that one-shot thunks are
-- really really one-shot thunks. Only needed if the demand analyser
-- has run at all. See Note [Final Demand Analyser run] in DmdAnal
runWhen (strictness || late_dmd_anal) CoreDoStrictness,
maybe_rule_check (Phase 0) maybe_rule_check (Phase 0)
] ]
......
...@@ -1331,4 +1331,32 @@ of the Id, and start from "bottom". Nowadays the Id can have a current ...@@ -1331,4 +1331,32 @@ of the Id, and start from "bottom". Nowadays the Id can have a current
strictness, because interface files record strictness for nested bindings. strictness, because interface files record strictness for nested bindings.
To know when we are in the first iteration, we look at the ae_virgin To know when we are in the first iteration, we look at the ae_virgin
field of the AnalEnv. field of the AnalEnv.
Note [Final Demand Analyser run]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some of the information that the demand analyser determines is not always
preserved by the simplifier, for example, the simplifier will happily rewrite
\y [Demand=1*U] let x = y in x + x
to
\y [Demand=1*U] y + y
which is quite a lie.
The once-used information is (currently) only used by the code generator, though. So we
* do not bother keeping this information up-to-date in the simplifier, or
removing it after the demand analyser is done (keeping in mind not to
critically rely on this information in, say, the simplifier).
It should still be fine to use this as in heuristics, e.g. when deciding to
inline things, as the data will usually be correct.
* Just before TidyCore, we add a pass of the demand analyse, without
subsequent worker/wrapper and simplifier, right before TidyCore.
This way, correct information finds its way into the module interface
(strictness signatures!) and the code generator (single-entry thunks!)
Note that the single-call information (C1(..)) can be relied upon, as the
simplifier tends to be very careful about not duplicating actual function
calls.
Also see #11731.
-} -}
...@@ -16,7 +16,6 @@ import IdInfo ...@@ -16,7 +16,6 @@ import IdInfo
import UniqSupply import UniqSupply
import BasicTypes import BasicTypes
import DynFlags import DynFlags
import VarEnv ( isEmptyVarEnv )
import Demand import Demand
import WwLib import WwLib
import Util import Util
...@@ -107,7 +106,10 @@ wwExpr _ _ e@(Lit {}) = return e ...@@ -107,7 +106,10 @@ wwExpr _ _ e@(Lit {}) = return e
wwExpr _ _ e@(Var {}) = return e wwExpr _ _ e@(Var {}) = return e
wwExpr dflags fam_envs (Lam binder expr) wwExpr dflags fam_envs (Lam binder expr)
= Lam binder <$> wwExpr dflags fam_envs expr = Lam new_binder <$> wwExpr dflags fam_envs expr
where new_binder | isId binder = zapIdUsedOnceInfo binder
| otherwise = binder
-- See Note [Zapping Used Once info in WorkWrap]
wwExpr dflags fam_envs (App f a) wwExpr dflags fam_envs (App f a)
= App <$> wwExpr dflags fam_envs f <*> wwExpr dflags fam_envs a = App <$> wwExpr dflags fam_envs f <*> wwExpr dflags fam_envs a
...@@ -125,11 +127,16 @@ wwExpr dflags fam_envs (Let bind expr) ...@@ -125,11 +127,16 @@ wwExpr dflags fam_envs (Let bind expr)
wwExpr dflags fam_envs (Case expr binder ty alts) = do wwExpr dflags fam_envs (Case expr binder ty alts) = do
new_expr <- wwExpr dflags fam_envs expr new_expr <- wwExpr dflags fam_envs expr
new_alts <- mapM ww_alt alts new_alts <- mapM ww_alt alts
return (Case new_expr binder ty new_alts) let new_binder = zapIdUsedOnceInfo binder
-- See Note [Zapping Used Once info in WorkWrap]
return (Case new_expr new_binder ty new_alts)
where where
ww_alt (con, binders, rhs) = do ww_alt (con, binders, rhs) = do
new_rhs <- wwExpr dflags fam_envs rhs new_rhs <- wwExpr dflags fam_envs rhs
return (con, binders, new_rhs) let new_binders = [ if isId b then zapIdUsedOnceInfo b else b
| b <- binders ]
-- See Note [Zapping Used Once info in WorkWrap]
return (con, new_binders, new_rhs)
{- {-
************************************************************************ ************************************************************************
...@@ -279,9 +286,7 @@ tryWW dflags fam_envs is_rec fn_id rhs ...@@ -279,9 +286,7 @@ tryWW dflags fam_envs is_rec fn_id rhs
-- No point in worker/wrappering if the thing is never inlined! -- No point in worker/wrappering if the thing is never inlined!
-- Because the no-inline prag will prevent the wrapper ever -- Because the no-inline prag will prevent the wrapper ever
-- being inlined at a call site. -- being inlined at a call site.
-- = return [ (new_fn_id, rhs) ]
-- Furthermore, don't even expose strictness info
= return [ (fn_id, rhs) ]
| not loop_breaker | not loop_breaker
, Just stable_unf <- certainlyWillInline dflags fn_unf , Just stable_unf <- certainlyWillInline dflags fn_unf
...@@ -304,24 +309,58 @@ tryWW dflags fam_envs is_rec fn_id rhs ...@@ -304,24 +309,58 @@ tryWW dflags fam_envs is_rec fn_id rhs
fn_info = idInfo fn_id fn_info = idInfo fn_id
inline_act = inlinePragmaActivation (inlinePragInfo fn_info) inline_act = inlinePragmaActivation (inlinePragInfo fn_info)
fn_unf = unfoldingInfo fn_info fn_unf = unfoldingInfo fn_info
(wrap_dmds, res_info) = splitStrictSig (strictnessInfo fn_info)
-- In practice it always will have a strictness new_fn_id = zapIdUsedOnceInfo (zapIdUsageEnvInfo fn_id)
-- signature, even if it's a uninformative one -- See Note [Zapping DmdEnv after Demand Analyzer] and
strict_sig = strictnessInfo fn_info -- See Note [Zapping Used Once info in WorkWrap]
StrictSig (DmdType env wrap_dmds res_info) = strict_sig
-- new_fn_id has the DmdEnv zapped.
-- (a) it is never used again
-- (b) it wastes space
-- (c) it becomes incorrect as things are cloned, because
-- we don't push the substitution into it
new_fn_id | isEmptyVarEnv env = fn_id
| otherwise = fn_id `setIdStrictness`
mkClosedStrictSig wrap_dmds res_info
is_fun = notNull wrap_dmds is_fun = notNull wrap_dmds
is_thunk = not is_fun && not (exprIsHNF rhs) is_thunk = not is_fun && not (exprIsHNF rhs)
{-
Note [Zapping DmdEnv after Demand Analyzer]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the worker-wrapper pass we zap the DmdEnv.
Why?
(a) it is never used again
(b) it wastes space
(c) it becomes incorrect as things are cloned, because
we don't push the substitution into it
Why here?
* Because we don’t want to do it in the Demand Analyzer, as we never know
there when we are doing the last pass.
* We want them to be still there at the end of DmdAnal, so that
-ddump-str-anal contains them.
* We don’t want a second pass just for that.
* WorkWrap looks at all bindings anyways.
We also need to do it in TidyCore to clean up after the final,
worker/wrapper-less run of the demand analyser.
Note [Zapping Used Once info in WorkWrap]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the worker-wrapper pass we zap the used once info in demands and in
strictness signatures.
Why?
* The simplifier may happen to transform code in a way that invalidates the
data (see #11731 for an example).
* It is not used in later passes, up to code generation.
So as the data is useless and possibly wrong, we want to remove it. The most
convenient place to do that is the worker wrapper phase, as it runs after every
run of the demand analyser besides the very last one (which is the one where we
want to _keep_ the info for the code generator).
We do not do it in the demand analyser for the same reasons outlined in
Note [Zapping DmdEnv after Demand Analyzer] above.
-}
--------------------- ---------------------
splitFun :: DynFlags -> FamInstEnvs -> Id -> IdInfo -> [Demand] -> DmdResult -> CoreExpr splitFun :: DynFlags -> FamInstEnvs -> Id -> IdInfo -> [Demand] -> DmdResult -> CoreExpr
......
...@@ -639,7 +639,7 @@ test('T9020', ...@@ -639,7 +639,7 @@ test('T9020',
test('T9675', test('T9675',
[ only_ways(['optasm']), [ only_ways(['optasm']),
compiler_stats_num_field('max_bytes_used', # Note [residency] compiler_stats_num_field('max_bytes_used', # Note [residency]
[(wordsize(64), 30837312, 15), [(wordsize(64), 38776008, 15),
# 2014-10-13 29596552 # 2014-10-13 29596552
# 2014-10-13 26570896 seq the DmdEnv in seqDmdType as well # 2014-10-13 26570896 seq the DmdEnv in seqDmdType as well
# 2014-10-13 18582472 different machines giving different results.. # 2014-10-13 18582472 different machines giving different results..
...@@ -647,12 +647,13 @@ test('T9675', ...@@ -647,12 +647,13 @@ test('T9675',
# 2015-06-21 28056344 switch to `+RTS -G1`, tighten bound to 15% # 2015-06-21 28056344 switch to `+RTS -G1`, tighten bound to 15%
# 2015-10-28 23776640 emit Typeable at definition site # 2015-10-28 23776640 emit Typeable at definition site
# 2015-12-11 30837312 TypeInType (see #11196) # 2015-12-11 30837312 TypeInType (see #11196)
# 2016-04-14 38776008 Final demand analyzer run
(wordsize(32), 18043224, 15) (wordsize(32), 18043224, 15)
# 2015-07-11 15341228 (x86/Linux, 64-bit machine) use +RTS -G1 # 2015-07-11 15341228 (x86/Linux, 64-bit machine) use +RTS -G1
# 2016-04-06 18043224 (x86/Linux, 64-bit machine) # 2016-04-06 18043224 (x86/Linux, 64-bit machine)
]), ]),
compiler_stats_num_field('peak_megabytes_allocated', # Note [residency] compiler_stats_num_field('peak_megabytes_allocated', # Note [residency]
[(wordsize(64), 113, 15), [(wordsize(64), 144, 15),
# 2014-10-13 66 # 2014-10-13 66
# 2014-10-13 58 seq the DmdEnv in seqDmdType as well # 2014-10-13 58 seq the DmdEnv in seqDmdType as well
# 2014-10-13 49 different machines giving different results... # 2014-10-13 49 different machines giving different results...
...@@ -661,6 +662,7 @@ test('T9675', ...@@ -661,6 +662,7 @@ test('T9675',
# 2015-06-21 105 switch to `+RTS -G1` # 2015-06-21 105 switch to `+RTS -G1`
# 2015-12-04 88 new pattern checker (D1535) # 2015-12-04 88 new pattern checker (D1535)
# 2015-12-11 113 TypeInType (see #11196) # 2015-12-11 113 TypeInType (see #11196)
# 2016-04-14 144 Final demand analyzer run
(wordsize(32), 56, 15) (wordsize(32), 56, 15)
# 2015-07-11 56 (x86/Linux, 64-bit machine) use +RTS -G1 # 2015-07-11 56 (x86/Linux, 64-bit machine) use +RTS -G1
]), ]),
...@@ -771,10 +773,11 @@ test('T9961', ...@@ -771,10 +773,11 @@ test('T9961',
test('T9233', test('T9233',
[ only_ways(['normal']), [ only_ways(['normal']),
compiler_stats_num_field('bytes allocated', compiler_stats_num_field('bytes allocated',
[(wordsize(64), 999826288, 5), [(wordsize(64), 1066246248, 5),
# 2015-08-04 999826288 initial value # 2015-08-04 999826288 initial value
(wordsize(32), 515672240, 5) # Put in your value here if you hit this # 2016-04-14 1066246248 Final demand analyzer run
# 2016-04-06 515672240 (x86/Linux) initial value (wordsize(32), 515672240, 5) # Put in your value here if you hit this
# 2016-04-06 515672240 (x86/Linux) initial value
]), ]),
extra_clean(['T9233a.hi', 'T9233a.o']) extra_clean(['T9233a.hi', 'T9233a.o'])
], ],
...@@ -784,17 +787,19 @@ test('T9233', ...@@ -784,17 +787,19 @@ test('T9233',
test('T10370', test('T10370',
[ only_ways(['optasm']), [ only_ways(['optasm']),
compiler_stats_num_field('max_bytes_used', # Note [residency] compiler_stats_num_field('max_bytes_used', # Note [residency]
[(wordsize(64), 22823976, 15), [(wordsize(64), 28256896, 15),
# 2015-10-22 19548720 # 2015-10-22 19548720
# 2016-02-24 22823976 Changing Levity to RuntimeRep; not sure why this regresses though, even after some analysis # 2016-02-24 22823976 Changing Levity to RuntimeRep; not sure why this regresses though, even after some analysis
# 2016-04-14 28256896 final demand analyzer run
(wordsize(32), 11371496, 15), (wordsize(32), 11371496, 15),
# 2015-10-22 11371496 # 2015-10-22 11371496
]), ]),
compiler_stats_num_field('peak_megabytes_allocated', # Note [residency] compiler_stats_num_field('peak_megabytes_allocated', # Note [residency]
[(wordsize(64), 76, 15), [(wordsize(64), 101, 15),
# 2015-10-22 76 # 2015-10-22 76
(wordsize(32), 39, 15), # 2016-04-14 101 final demand analyzer run
# 2015-10-22 39 (wordsize(32), 39, 15),
# 2015-10-22 39
]), ]),
# Use `+RTS -G1` for more stable residency measurements. Note [residency]. # Use `+RTS -G1` for more stable residency measurements. Note [residency].
extra_hc_opts('+RTS -G1 -RTS') extra_hc_opts('+RTS -G1 -RTS')
......
...@@ -33,7 +33,7 @@ T4908.$trModule = ...@@ -33,7 +33,7 @@ T4908.$trModule =
Rec { Rec {
-- RHS size: {terms: 19, types: 5, coercions: 0} -- RHS size: {terms: 19, types: 5, coercions: 0}
T4908.f_$s$wf [Occ=LoopBreaker] :: Int -> Int# -> Int# -> Bool T4908.f_$s$wf [Occ=LoopBreaker] :: Int -> Int# -> Int# -> Bool
[GblId, Arity=3, Caf=NoCafRefs, Str=<L,A><L,U><S,1*U>] [GblId, Arity=3, Caf=NoCafRefs, Str=<L,A><L,1*U><S,1*U>]
T4908.f_$s$wf = T4908.f_$s$wf =
\ (sc :: Int) (sc1 :: Int#) (sc2 :: Int#) -> \ (sc :: Int) (sc1 :: Int#) (sc2 :: Int#) ->
case sc2 of ds { case sc2 of ds {
...@@ -51,7 +51,7 @@ T4908.$wf [InlPrag=[0]] :: Int# -> (Int, Int) -> Bool ...@@ -51,7 +51,7 @@ T4908.$wf [InlPrag=[0]] :: Int# -> (Int, Int) -> Bool
[GblId, [GblId,
Arity=2, Arity=2,
Caf=NoCafRefs, Caf=NoCafRefs,
Str=<S,1*U><L,1*U(A,U(U))>, Str=<S,1*U><L,1*U(A,1*U(1*U))>,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [30 20] 101 20}] WorkFree=True, Expandable=True, Guidance=IF_ARGS [30 20] 101 20}]
T4908.$wf =