Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
2da84b7a
by sheaf at 2025-09-01T23:03:23-04:00
28 changed files:
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Parser.y
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Utils/Binary.hs
- hie.yaml
- testsuite/tests/perf/compiler/T4007.stdout
- testsuite/tests/simplCore/should_compile/T15056.stderr
- testsuite/tests/simplCore/should_compile/T15445.stderr
- + testsuite/tests/simplCore/should_compile/T26323b.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T26323.hs
- + testsuite/tests/simplCore/should_run/T26323.stdout
- testsuite/tests/simplCore/should_run/all.T
- utils/check-exact/ExactPrint.hs
Changes:
| ... | ... | @@ -10,7 +10,7 @@ import GHC.Core ( CoreProgram ) |
| 10 | 10 | import GHC.Core.Opt.Monad ( CoreM, FloatOutSwitches )
|
| 11 | 11 | import GHC.Core.Opt.Simplify ( SimplifyOpts(..) )
|
| 12 | 12 | |
| 13 | -import GHC.Types.Basic ( CompilerPhase(..) )
|
|
| 13 | +import GHC.Types.Basic ( CompilerPhase )
|
|
| 14 | 14 | import GHC.Unit.Module.ModGuts
|
| 15 | 15 | import GHC.Utils.Outputable as Outputable
|
| 16 | 16 | |
| ... | ... | @@ -52,8 +52,8 @@ data CoreToDo -- These are diff core-to-core passes, |
| 52 | 52 | | CoreDoSpecialising
|
| 53 | 53 | | CoreDoSpecConstr
|
| 54 | 54 | | CoreCSE
|
| 55 | - | CoreDoRuleCheck CompilerPhase String -- Check for non-application of rules
|
|
| 56 | - -- matching this string
|
|
| 55 | + | CoreDoRuleCheck CompilerPhase String -- Check for non-application of rules
|
|
| 56 | + -- matching this string
|
|
| 57 | 57 | | CoreDoNothing -- Useful when building up
|
| 58 | 58 | | CoreDoPasses [CoreToDo] -- lists of these things
|
| 59 | 59 |
| ... | ... | @@ -12,6 +12,7 @@ module GHC.Core.Opt.Simplify.Env ( |
| 12 | 12 | |
| 13 | 13 | -- * Environments
|
| 14 | 14 | SimplEnv(..), pprSimplEnv, -- Temp not abstract
|
| 15 | + SimplPhase(..), isActive,
|
|
| 15 | 16 | seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
|
| 16 | 17 | seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
|
| 17 | 18 | seOptCoercionOpts, sePhase, sePlatform, sePreInline,
|
| ... | ... | @@ -145,7 +146,7 @@ here is between "freely set by the caller" and "internally managed by the pass". |
| 145 | 146 | Note that it doesn't matter for the decision procedure wheter a value is altered
|
| 146 | 147 | throughout an iteration of the Simplify pass: The fields sm_phase, sm_inline,
|
| 147 | 148 | sm_rules, sm_cast_swizzle and sm_eta_expand are updated locally (See the
|
| 148 | -definitions of `updModeForStableUnfoldings` and `updModeForRules` in
|
|
| 149 | +definitions of `updModeForStableUnfoldings` and `updModeForRule{LHS,RHS}` in
|
|
| 149 | 150 | GHC.Core.Opt.Simplify.Utils) but they are still part of `SimplMode` as the
|
| 150 | 151 | caller of the Simplify pass needs to provide the initial values for those fields.
|
| 151 | 152 | |
| ... | ... | @@ -250,7 +251,7 @@ seNames env = sm_names (seMode env) |
| 250 | 251 | seOptCoercionOpts :: SimplEnv -> OptCoercionOpts
|
| 251 | 252 | seOptCoercionOpts env = sm_co_opt_opts (seMode env)
|
| 252 | 253 | |
| 253 | -sePhase :: SimplEnv -> CompilerPhase
|
|
| 254 | +sePhase :: SimplEnv -> SimplPhase
|
|
| 254 | 255 | sePhase env = sm_phase (seMode env)
|
| 255 | 256 | |
| 256 | 257 | sePlatform :: SimplEnv -> Platform
|
| ... | ... | @@ -270,7 +271,7 @@ seUnfoldingOpts env = sm_uf_opts (seMode env) |
| 270 | 271 | |
| 271 | 272 | -- See Note [The environments of the Simplify pass]
|
| 272 | 273 | data SimplMode = SimplMode -- See comments in GHC.Core.Opt.Simplify.Monad
|
| 273 | - { sm_phase :: !CompilerPhase
|
|
| 274 | + { sm_phase :: !SimplPhase -- ^ The phase of the simplifier
|
|
| 274 | 275 | , sm_names :: ![String] -- ^ Name(s) of the phase
|
| 275 | 276 | , sm_rules :: !Bool -- ^ Whether RULES are enabled
|
| 276 | 277 | , sm_inline :: !Bool -- ^ Whether inlining is enabled
|
| ... | ... | @@ -288,13 +289,76 @@ data SimplMode = SimplMode -- See comments in GHC.Core.Opt.Simplify.Monad |
| 288 | 289 | , sm_co_opt_opts :: !OptCoercionOpts -- ^ Coercion optimiser options
|
| 289 | 290 | }
|
| 290 | 291 | |
| 292 | +-- | See Note [SimplPhase]
|
|
| 293 | +data SimplPhase
|
|
| 294 | + -- | A simplifier phase: InitialPhase, Phase 2, Phase 1, Phase 0, FinalPhase
|
|
| 295 | + = SimplPhase CompilerPhase
|
|
| 296 | + -- | Simplifying the RHS of a rule or of a stable unfolding: the range of
|
|
| 297 | + -- phases of the activation of the rule/stable unfolding.
|
|
| 298 | + --
|
|
| 299 | + -- _Invariant:_ 'simplStartPhase' is not a later phase than 'simplEndPhase'.
|
|
| 300 | + -- Equivalently, 'SimplPhaseRange' is always a non-empty interval of phases.
|
|
| 301 | + --
|
|
| 302 | + -- See Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
|
|
| 303 | + | SimplPhaseRange
|
|
| 304 | + { simplStartPhase :: CompilerPhase
|
|
| 305 | + , simplEndPhase :: CompilerPhase
|
|
| 306 | + }
|
|
| 307 | + |
|
| 308 | + deriving Eq
|
|
| 309 | + |
|
| 310 | +instance Outputable SimplPhase where
|
|
| 311 | + ppr (SimplPhase p) = ppr p
|
|
| 312 | + ppr (SimplPhaseRange s e) = brackets $ ppr s <> text "..." <> ppr e
|
|
| 313 | + |
|
| 314 | +-- | Is this activation active in this simplifier phase?
|
|
| 315 | +--
|
|
| 316 | +-- For a phase range, @isActive simpl_phase_range act@ is true if and only if
|
|
| 317 | +-- @act@ is active throughout the entire range, as per
|
|
| 318 | +-- Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
|
|
| 319 | +--
|
|
| 320 | +-- See Note [SimplPhase].
|
|
| 321 | +isActive :: SimplPhase -> Activation -> Bool
|
|
| 322 | +isActive (SimplPhase p) act = isActiveInPhase p act
|
|
| 323 | +isActive (SimplPhaseRange start end) act =
|
|
| 324 | + -- To check whether the activation is active throughout the whole phase range,
|
|
| 325 | + -- it's sufficient to check the endpoints of the phase range, because an
|
|
| 326 | + -- activation can never have gaps (all activations are phase intervals).
|
|
| 327 | + isActiveInPhase start act && isActiveInPhase end act
|
|
| 328 | + |
|
| 329 | +{- Note [SimplPhase]
|
|
| 330 | +~~~~~~~~~~~~~~~~~~~~
|
|
| 331 | +In general, the simplifier is invoked in successive phases:
|
|
| 332 | + |
|
| 333 | + InitialPhase, Phase 2, Phase 1, Phase 0, FinalPhase
|
|
| 334 | + |
|
| 335 | +This allows us to control which rules, specialisations and inlinings are
|
|
| 336 | +active at any given point. For example,
|
|
| 337 | + |
|
| 338 | + {-# RULE "myRule" [1] lhs = rhs #-}
|
|
| 339 | + |
|
| 340 | +starts being active in Phase 1, and stays active thereafter. Thus it is active
|
|
| 341 | +in Phase 1, Phase 0, FinalPhase, but not active in InitialPhase or Phase 2.
|
|
| 342 | + |
|
| 343 | +This simplifier phase is stored in the sm_phase field of SimplMode, usin
|
|
| 344 | +the 'SimplPhase' constructor. This allows us to determine which rules/inlinings
|
|
| 345 | +are active.
|
|
| 346 | + |
|
| 347 | +When we invoke the simplifier on the RHS of a rule, such as 'rhs' above, instead
|
|
| 348 | +of setting the simplifier mode to a single phase, we use a phase range
|
|
| 349 | +corresponding to the range of phases in which the rule is active, with the
|
|
| 350 | +'SimplPhaseRange' constructor. This allows us to check whether other rules or
|
|
| 351 | +inlinings are active throughout the whole activation of the rule.
|
|
| 352 | +See Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
|
|
| 353 | +-}
|
|
| 354 | + |
|
| 291 | 355 | instance Outputable SimplMode where
|
| 292 | - ppr (SimplMode { sm_phase = p , sm_names = ss
|
|
| 356 | + ppr (SimplMode { sm_phase = phase , sm_names = ss
|
|
| 293 | 357 | , sm_rules = r, sm_inline = i
|
| 294 | 358 | , sm_cast_swizzle = cs
|
| 295 | 359 | , sm_eta_expand = eta, sm_case_case = cc })
|
| 296 | 360 | = text "SimplMode" <+> braces (
|
| 297 | - sep [ text "Phase =" <+> ppr p <+>
|
|
| 361 | + sep [ text "Phase =" <+> ppr phase <+>
|
|
| 298 | 362 | brackets (text (concat $ intersperse "," ss)) <> comma
|
| 299 | 363 | , pp_flag i (text "inline") <> comma
|
| 300 | 364 | , pp_flag r (text "rules") <> comma
|
| ... | ... | @@ -312,9 +376,8 @@ data FloatEnable -- Controls local let-floating |
| 312 | 376 | | FloatNestedOnly -- Local let-floating for nested (NotTopLevel) bindings only
|
| 313 | 377 | | FloatEnabled -- Do local let-floating on all bindings
|
| 314 | 378 | |
| 315 | -{-
|
|
| 316 | -Note [Local floating]
|
|
| 317 | -~~~~~~~~~~~~~~~~~~~~~
|
|
| 379 | +{- Note [Local floating]
|
|
| 380 | +~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 318 | 381 | The Simplifier can perform local let-floating: it floats let-bindings
|
| 319 | 382 | out of the RHS of let-bindings. See
|
| 320 | 383 | Let-floating: moving bindings to give faster programs (ICFP'96)
|
| ... | ... | @@ -29,7 +29,7 @@ import GHC.Core.FVs( exprFreeIds ) |
| 29 | 29 | import GHC.Types.Id
|
| 30 | 30 | import GHC.Types.Var.Env( InScopeSet, lookupInScope )
|
| 31 | 31 | import GHC.Types.Var.Set
|
| 32 | -import GHC.Types.Basic ( Arity, RecFlag(..), isActive )
|
|
| 32 | +import GHC.Types.Basic ( Arity, RecFlag(..) )
|
|
| 33 | 33 | import GHC.Utils.Logger
|
| 34 | 34 | import GHC.Utils.Misc
|
| 35 | 35 | import GHC.Utils.Outputable
|
| ... | ... | @@ -124,7 +124,7 @@ activeUnfolding mode id |
| 124 | 124 | | isCompulsoryUnfolding (realIdUnfolding id)
|
| 125 | 125 | = True -- Even sm_inline can't override compulsory unfoldings
|
| 126 | 126 | | otherwise
|
| 127 | - = isActive (sm_phase mode) (idInlineActivation id)
|
|
| 127 | + = isActive (sm_phase mode) (idInlineActivation id)
|
|
| 128 | 128 | && sm_inline mode
|
| 129 | 129 | -- `or` isStableUnfolding (realIdUnfolding id)
|
| 130 | 130 | -- Inline things when
|
| ... | ... | @@ -2458,7 +2458,11 @@ tryInlining env logger var cont |
| 2458 | 2458 | | not (logHasDumpFlag logger Opt_D_verbose_core2core)
|
| 2459 | 2459 | = when (isExternalName (idName var)) $
|
| 2460 | 2460 | log_inlining $
|
| 2461 | - sep [text "Inlining done:", nest 4 (ppr var)]
|
|
| 2461 | + sep [text "Inlining done:", nest 4 (ppr var)]
|
|
| 2462 | + -- $$ nest 2 (vcat
|
|
| 2463 | + -- [ text "Simplifier phase:" <+> ppr (sePhase env)
|
|
| 2464 | + -- , text "Unfolding activation:" <+> ppr (idInlineActivation var)
|
|
| 2465 | + -- ])
|
|
| 2462 | 2466 | | otherwise
|
| 2463 | 2467 | = log_inlining $
|
| 2464 | 2468 | sep [text "Inlining done: " <> ppr var,
|
| ... | ... | @@ -2645,6 +2649,8 @@ tryRules env rules fn args |
| 2645 | 2649 | = log_rule Opt_D_dump_rule_rewrites "Rule fired" $ vcat
|
| 2646 | 2650 | [ text "Rule:" <+> ftext (ruleName rule)
|
| 2647 | 2651 | , text "Module:" <+> printRuleModule rule
|
| 2652 | + --, text "Simplifier phase:" <+> ppr (sePhase env)
|
|
| 2653 | + --, text "Rule activation:" <+> ppr (ruleActivation rule)
|
|
| 2648 | 2654 | , text "Full arity:" <+> ppr (ruleArity rule)
|
| 2649 | 2655 | , text "Before:" <+> hang (ppr fn) 2 (sep (map ppr args))
|
| 2650 | 2656 | , text "After: " <+> pprCoreExpr rule_rhs ]
|
| ... | ... | @@ -4790,9 +4796,12 @@ simplRules env mb_new_id rules bind_cxt |
| 4790 | 4796 | rhs_cont = case bind_cxt of -- See Note [Rules and unfolding for join points]
|
| 4791 | 4797 | BC_Let {} -> mkBoringStop rhs_ty
|
| 4792 | 4798 | BC_Join _ cont -> assertPpr join_ok bad_join_msg cont
|
| 4793 | - lhs_env = updMode updModeForRules env'
|
|
| 4794 | - rhs_env = updMode (updModeForStableUnfoldings act) env'
|
|
| 4795 | - -- See Note [Simplifying the RHS of a RULE]
|
|
| 4799 | + |
|
| 4800 | + -- See Note [Simplifying rules] and Note [What is active in the RHS of a RULE?]
|
|
| 4801 | + -- in GHC.Core.Opt.Simplify.Utils.
|
|
| 4802 | + lhs_env = updMode updModeForRuleLHS env'
|
|
| 4803 | + rhs_env = updMode (updModeForRuleRHS act) env'
|
|
| 4804 | + |
|
| 4796 | 4805 | -- Force this to avoid retaining reference to old Id
|
| 4797 | 4806 | !fn_name' = case mb_new_id of
|
| 4798 | 4807 | Just id -> idName id
|
| ... | ... | @@ -4816,12 +4825,3 @@ simplRules env mb_new_id rules bind_cxt |
| 4816 | 4825 | , ru_rhs = occurAnalyseExpr rhs' }) }
|
| 4817 | 4826 | -- Remember to occ-analyse, to drop dead code.
|
| 4818 | 4827 | -- See Note [OccInfo in unfoldings and rules] in GHC.Core |
| 4819 | - |
|
| 4820 | -{- Note [Simplifying the RHS of a RULE]
|
|
| 4821 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 4822 | -We can simplify the RHS of a RULE much as we do the RHS of a stable
|
|
| 4823 | -unfolding. We used to use the much more conservative updModeForRules
|
|
| 4824 | -for the RHS as well as the LHS, but that seems more conservative
|
|
| 4825 | -than necesary. Allowing some inlining might, for example, eliminate
|
|
| 4826 | -a binding.
|
|
| 4827 | --} |
| ... | ... | @@ -15,7 +15,7 @@ module GHC.Core.Opt.Simplify.Utils ( |
| 15 | 15 | preInlineUnconditionally, postInlineUnconditionally,
|
| 16 | 16 | activeRule,
|
| 17 | 17 | getUnfoldingInRuleMatch,
|
| 18 | - updModeForStableUnfoldings, updModeForRules,
|
|
| 18 | + updModeForStableUnfoldings, updModeForRuleLHS, updModeForRuleRHS,
|
|
| 19 | 19 | |
| 20 | 20 | -- The BindContext type
|
| 21 | 21 | BindContext(..), bindContextLevel,
|
| ... | ... | @@ -719,7 +719,7 @@ the LHS. |
| 719 | 719 | |
| 720 | 720 | This is a pretty pathological example, so I'm not losing sleep over
|
| 721 | 721 | it, but the simplest solution was to check sm_inline; if it is False,
|
| 722 | -which it is on the LHS of a rule (see updModeForRules), then don't
|
|
| 722 | +which it is on the LHS of a rule (see updModeForRuleLHS), then don't
|
|
| 723 | 723 | make use of the strictness info for the function.
|
| 724 | 724 | -}
|
| 725 | 725 | |
| ... | ... | @@ -1069,22 +1069,22 @@ Reason for (b): we want to inline integerCompare here |
| 1069 | 1069 | |
| 1070 | 1070 | updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
|
| 1071 | 1071 | -- See Note [The environments of the Simplify pass]
|
| 1072 | +-- See Note [Simplifying inside stable unfoldings]
|
|
| 1072 | 1073 | updModeForStableUnfoldings unf_act current_mode
|
| 1073 | - = current_mode { sm_phase = phaseFromActivation unf_act
|
|
| 1074 | - , sm_eta_expand = False
|
|
| 1075 | - , sm_inline = True }
|
|
| 1076 | - -- sm_eta_expand: see Note [Eta expansion in stable unfoldings and rules]
|
|
| 1077 | - -- sm_rules: just inherit; sm_rules might be "off"
|
|
| 1078 | - -- because of -fno-enable-rewrite-rules
|
|
| 1079 | - where
|
|
| 1080 | - phaseFromActivation (ActiveAfter _ n) = Phase n
|
|
| 1081 | - phaseFromActivation _ = InitialPhase
|
|
| 1074 | + = current_mode
|
|
| 1075 | + { sm_phase = phaseFromActivation (sm_phase current_mode) unf_act
|
|
| 1076 | + -- See Note [What is active in the RHS of a RULE?]
|
|
| 1077 | + , sm_eta_expand = False
|
|
| 1078 | + -- See Note [Eta expansion in stable unfoldings and rules]
|
|
| 1079 | + , sm_inline = True
|
|
| 1080 | + -- sm_rules: just inherit; sm_rules might be "off" because of -fno-enable-rewrite-rules
|
|
| 1081 | + }
|
|
| 1082 | 1082 | |
| 1083 | -updModeForRules :: SimplMode -> SimplMode
|
|
| 1083 | +updModeForRuleLHS :: SimplMode -> SimplMode
|
|
| 1084 | 1084 | -- See Note [Simplifying rules]
|
| 1085 | 1085 | -- See Note [The environments of the Simplify pass]
|
| 1086 | -updModeForRules current_mode
|
|
| 1087 | - = current_mode { sm_phase = InitialPhase
|
|
| 1086 | +updModeForRuleLHS current_mode
|
|
| 1087 | + = current_mode { sm_phase = SimplPhase InitialPhase -- doesn't matter
|
|
| 1088 | 1088 | , sm_inline = False
|
| 1089 | 1089 | -- See Note [Do not expose strictness if sm_inline=False]
|
| 1090 | 1090 | , sm_rules = False
|
| ... | ... | @@ -1092,8 +1092,34 @@ updModeForRules current_mode |
| 1092 | 1092 | -- See Note [Cast swizzling on rule LHSs]
|
| 1093 | 1093 | , sm_eta_expand = False }
|
| 1094 | 1094 | |
| 1095 | +updModeForRuleRHS :: Activation -> SimplMode -> SimplMode
|
|
| 1096 | +updModeForRuleRHS rule_act current_mode =
|
|
| 1097 | + current_mode
|
|
| 1098 | + -- See Note [What is active in the RHS of a RULE?]
|
|
| 1099 | + { sm_phase = phaseFromActivation (sm_phase current_mode) rule_act
|
|
| 1100 | + , sm_eta_expand = False
|
|
| 1101 | + -- See Note [Eta expansion in stable unfoldings and rules]
|
|
| 1102 | + }
|
|
| 1103 | + |
|
| 1104 | +-- | Compute the phase range to set the 'SimplMode' to
|
|
| 1105 | +-- when simplifying the RHS of a rule or of a stable unfolding.
|
|
| 1106 | +--
|
|
| 1107 | +-- See Note [What is active in the RHS of a RULE?]
|
|
| 1108 | +phaseFromActivation
|
|
| 1109 | + :: SimplPhase -- ^ the current simplifier phase
|
|
| 1110 | + -> Activation -- ^ the activation of the RULE or stable unfolding
|
|
| 1111 | + -> SimplPhase
|
|
| 1112 | +phaseFromActivation p act
|
|
| 1113 | + | isNeverActive act
|
|
| 1114 | + = p
|
|
| 1115 | + | otherwise
|
|
| 1116 | + = SimplPhaseRange act_start act_end
|
|
| 1117 | + where
|
|
| 1118 | + act_start = beginPhase act
|
|
| 1119 | + act_end = endPhase act
|
|
| 1120 | + |
|
| 1095 | 1121 | {- Note [Simplifying rules]
|
| 1096 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1122 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1097 | 1123 | When simplifying a rule LHS, refrain from /any/ inlining or applying
|
| 1098 | 1124 | of other RULES. Doing anything to the LHS is plain confusing, because
|
| 1099 | 1125 | it means that what the rule matches is not what the user
|
| ... | ... | @@ -1136,7 +1162,7 @@ where `cv` is a coercion variable. Critically, we really only want |
| 1136 | 1162 | coercion /variables/, not general coercions, on the LHS of a RULE. So
|
| 1137 | 1163 | we don't want to swizzle this to
|
| 1138 | 1164 | (\x. blah) |> (Refl xty `FunCo` CoVar cv)
|
| 1139 | -So we switch off cast swizzling in updModeForRules.
|
|
| 1165 | +So we switch off cast swizzling in updModeForRuleLHS.
|
|
| 1140 | 1166 | |
| 1141 | 1167 | Note [Eta expansion in stable unfoldings and rules]
|
| 1142 | 1168 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1200,6 +1226,62 @@ running it, we don't want to use -O2. Indeed, we don't want to inline |
| 1200 | 1226 | anything, because the byte-code interpreter might get confused about
|
| 1201 | 1227 | unboxed tuples and suchlike.
|
| 1202 | 1228 | |
| 1229 | +Note [What is active in the RHS of a RULE?]
|
|
| 1230 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1231 | +Suppose we have either a RULE or an inline pragma with an explicit activation:
|
|
| 1232 | + |
|
| 1233 | + {-# RULE "R" [p] lhs = rhs #-}
|
|
| 1234 | + {-# INLINE [p] foo #-}
|
|
| 1235 | + |
|
| 1236 | +We should do some modest rules/inlining stuff in the right-hand sides, partly to
|
|
| 1237 | +eliminate senseless crap, and partly to break the recursive knots generated by
|
|
| 1238 | +instance declarations. However, we have to be careful about precisely which
|
|
| 1239 | +rules/inlinings are active. In particular:
|
|
| 1240 | + |
|
| 1241 | + a) Rules/inlinings that *cease* being active before p should not apply.
|
|
| 1242 | + b) Rules/inlinings that only become active *after* p should also not apply.
|
|
| 1243 | + |
|
| 1244 | +In the rest of this Note, we will focus on rules, but everything applies equally
|
|
| 1245 | +to the RHSs of stable unfoldings.
|
|
| 1246 | + |
|
| 1247 | +Our carefully crafted plan is as follows:
|
|
| 1248 | + |
|
| 1249 | + -------------------------------------------------------------
|
|
| 1250 | + When simplifying the RHS of a RULE R with activation range A,
|
|
| 1251 | + fire only other rules R' that are active throughout all of A.
|
|
| 1252 | + -------------------------------------------------------------
|
|
| 1253 | + |
|
| 1254 | +Reason: R might fire in any phase in A. Then R' can fire only if R' is active
|
|
| 1255 | +in that phase. If not, it's not safe to unconditionally fire R' in the RHS of R.
|
|
| 1256 | + |
|
| 1257 | +This plan is implemented by:
|
|
| 1258 | + |
|
| 1259 | + 1. Setting the simplifier phase to the range of phases
|
|
| 1260 | + corresponding to the start/end phases of the rule's activation.
|
|
| 1261 | + 2. When checking whether another rule is active, we use the function
|
|
| 1262 | + isActive :: SimplPhase -> Activation -> Bool
|
|
| 1263 | + from GHC.Core.Opt.Simplify.Env, which checks whether the other rule is
|
|
| 1264 | + active throughout the whole range of phases.
|
|
| 1265 | + |
|
| 1266 | +However, if the rule whose RHS we are simplifying is never active, instead of
|
|
| 1267 | +setting the phase range to an empty interval, we keep the current simplifier
|
|
| 1268 | +phase. This special case avoids firing ALL rules in the RHS of a never-active
|
|
| 1269 | +rule.
|
|
| 1270 | + |
|
| 1271 | +You might wonder about a situation such as the following:
|
|
| 1272 | + |
|
| 1273 | + module M1 where
|
|
| 1274 | + {-# RULES "r1" [1] lhs1 = rhs1 #-}
|
|
| 1275 | + {-# RULES "r2" [2] lhs2 = rhs2 #-}
|
|
| 1276 | + |
|
| 1277 | + Current simplifier phase: 1
|
|
| 1278 | + |
|
| 1279 | +It looks tempting to use "r1" when simplifying the RHS of "r2", yet we
|
|
| 1280 | +**must not** do so: for any module M that imports M1, we are going to start
|
|
| 1281 | +simplification in M starting at InitialPhase, and we will see the
|
|
| 1282 | +fully simplified rules RHSs imported from M1.
|
|
| 1283 | +Conclusion: stick to the plan.
|
|
| 1284 | + |
|
| 1203 | 1285 | Note [Simplifying inside stable unfoldings]
|
| 1204 | 1286 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1205 | 1287 | We must take care with simplification inside stable unfoldings (which come from
|
| ... | ... | @@ -1216,33 +1298,9 @@ and thence copied multiple times when g is inlined. HENCE we treat |
| 1216 | 1298 | any occurrence in a stable unfolding as a multiple occurrence, not a single
|
| 1217 | 1299 | one; see OccurAnal.addRuleUsage.
|
| 1218 | 1300 | |
| 1219 | -Second, we do want *do* to some modest rules/inlining stuff in stable
|
|
| 1220 | -unfoldings, partly to eliminate senseless crap, and partly to break
|
|
| 1221 | -the recursive knots generated by instance declarations.
|
|
| 1222 | - |
|
| 1223 | -However, suppose we have
|
|
| 1224 | - {-# INLINE <act> f #-}
|
|
| 1225 | - f = <rhs>
|
|
| 1226 | -meaning "inline f in phases p where activation <act>(p) holds".
|
|
| 1227 | -Then what inlinings/rules can we apply to the copy of <rhs> captured in
|
|
| 1228 | -f's stable unfolding? Our model is that literally <rhs> is substituted for
|
|
| 1229 | -f when it is inlined. So our conservative plan (implemented by
|
|
| 1230 | -updModeForStableUnfoldings) is this:
|
|
| 1231 | - |
|
| 1232 | - -------------------------------------------------------------
|
|
| 1233 | - When simplifying the RHS of a stable unfolding, set the phase
|
|
| 1234 | - to the phase in which the stable unfolding first becomes active
|
|
| 1235 | - -------------------------------------------------------------
|
|
| 1236 | - |
|
| 1237 | -That ensures that
|
|
| 1238 | - |
|
| 1239 | - a) Rules/inlinings that *cease* being active before p will
|
|
| 1240 | - not apply to the stable unfolding, consistent with it being
|
|
| 1241 | - inlined in its *original* form in phase p.
|
|
| 1242 | - |
|
| 1243 | - b) Rules/inlinings that only become active *after* p will
|
|
| 1244 | - not apply to the stable unfolding, again to be consistent with
|
|
| 1245 | - inlining the *original* rhs in phase p.
|
|
| 1301 | +Second, we must be careful when simplifying the RHS that we do not apply RULES
|
|
| 1302 | +which are not active over the whole active range of the stable unfolding.
|
|
| 1303 | +This is all explained in Note [What is active in the RHS of a RULE?].
|
|
| 1246 | 1304 | |
| 1247 | 1305 | For example,
|
| 1248 | 1306 | {-# INLINE f #-}
|
| ... | ... | @@ -1291,8 +1349,7 @@ getUnfoldingInRuleMatch env |
| 1291 | 1349 | = ISE in_scope id_unf
|
| 1292 | 1350 | where
|
| 1293 | 1351 | in_scope = seInScope env
|
| 1294 | - phase = sePhase env
|
|
| 1295 | - id_unf = whenActiveUnfoldingFun (isActive phase)
|
|
| 1352 | + id_unf = whenActiveUnfoldingFun (isActive (sePhase env))
|
|
| 1296 | 1353 | -- When sm_rules was off we used to test for a /stable/ unfolding,
|
| 1297 | 1354 | -- but that seems wrong (#20941)
|
| 1298 | 1355 | |
| ... | ... | @@ -1468,7 +1525,8 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env |
| 1468 | 1525 | one_occ _ = False
|
| 1469 | 1526 | |
| 1470 | 1527 | pre_inline_unconditionally = sePreInline env
|
| 1471 | - active = isActive (sePhase env) (inlinePragmaActivation inline_prag)
|
|
| 1528 | + active = isActive (sePhase env)
|
|
| 1529 | + $ inlinePragmaActivation inline_prag
|
|
| 1472 | 1530 | -- See Note [pre/postInlineUnconditionally in gentle mode]
|
| 1473 | 1531 | inline_prag = idInlinePragma bndr
|
| 1474 | 1532 | |
| ... | ... | @@ -1505,7 +1563,10 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env |
| 1505 | 1563 | -- not ticks. Counting ticks cannot be duplicated, and non-counting
|
| 1506 | 1564 | -- ticks around a Lam will disappear anyway.
|
| 1507 | 1565 | |
| 1508 | - early_phase = sePhase env /= FinalPhase
|
|
| 1566 | + early_phase =
|
|
| 1567 | + case sePhase env of
|
|
| 1568 | + SimplPhase p -> p /= FinalPhase
|
|
| 1569 | + SimplPhaseRange _start end -> end /= FinalPhase
|
|
| 1509 | 1570 | -- If we don't have this early_phase test, consider
|
| 1510 | 1571 | -- x = length [1,2,3]
|
| 1511 | 1572 | -- The full laziness pass carefully floats all the cons cells to
|
| ... | ... | @@ -1516,9 +1577,8 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env |
| 1516 | 1577 | --
|
| 1517 | 1578 | -- On the other hand, I have seen cases where top-level fusion is
|
| 1518 | 1579 | -- lost if we don't inline top level thing (e.g. string constants)
|
| 1519 | - -- Hence the test for phase zero (which is the phase for all the final
|
|
| 1520 | - -- simplifications). Until phase zero we take no special notice of
|
|
| 1521 | - -- top level things, but then we become more leery about inlining
|
|
| 1580 | + -- Hence the final phase test: until the final phase, we take no special
|
|
| 1581 | + -- notice of top level things, but then we become more leery about inlining
|
|
| 1522 | 1582 | -- them.
|
| 1523 | 1583 | --
|
| 1524 | 1584 | -- What exactly to check in `early_phase` above is the subject of #17910.
|
| ... | ... | @@ -1645,8 +1705,7 @@ postInlineUnconditionally env bind_cxt old_bndr bndr rhs |
| 1645 | 1705 | occ_info = idOccInfo old_bndr
|
| 1646 | 1706 | unfolding = idUnfolding bndr
|
| 1647 | 1707 | uf_opts = seUnfoldingOpts env
|
| 1648 | - phase = sePhase env
|
|
| 1649 | - active = isActive phase (idInlineActivation bndr)
|
|
| 1708 | + active = isActive (sePhase env) $ idInlineActivation bndr
|
|
| 1650 | 1709 | -- See Note [pre/postInlineUnconditionally in gentle mode]
|
| 1651 | 1710 | |
| 1652 | 1711 | {- Note [Inline small things to avoid creating a thunk]
|
| ... | ... | @@ -19,18 +19,23 @@ import GHC.Core.SimpleOpt( defaultSimpleOpts, simpleOptExprWith, exprIsConApp_ma |
| 19 | 19 | import GHC.Core.Predicate
|
| 20 | 20 | import GHC.Core.Class( classMethods )
|
| 21 | 21 | import GHC.Core.Coercion( Coercion )
|
| 22 | -import GHC.Core.Opt.Monad
|
|
| 22 | +import GHC.Core.DataCon (dataConTyCon)
|
|
| 23 | + |
|
| 23 | 24 | import qualified GHC.Core.Subst as Core
|
| 24 | 25 | import GHC.Core.Unfold.Make
|
| 25 | 26 | import GHC.Core
|
| 26 | 27 | import GHC.Core.Make ( mkLitRubbish )
|
| 27 | 28 | import GHC.Core.Unify ( tcMatchTy )
|
| 28 | 29 | import GHC.Core.Rules
|
| 30 | +import GHC.Core.Subst (substTickish)
|
|
| 31 | +import GHC.Core.TyCon (tyConClass_maybe)
|
|
| 29 | 32 | import GHC.Core.Utils ( exprIsTrivial, exprIsTopLevelBindable
|
| 30 | 33 | , mkCast, exprType, exprIsHNF
|
| 31 | 34 | , stripTicksTop, mkInScopeSetBndrs )
|
| 32 | 35 | import GHC.Core.FVs
|
| 33 | 36 | import GHC.Core.Opt.Arity( collectBindersPushingCo )
|
| 37 | +import GHC.Core.Opt.Monad
|
|
| 38 | +import GHC.Core.Opt.Simplify.Env ( SimplPhase(..), isActive )
|
|
| 34 | 39 | |
| 35 | 40 | import GHC.Builtin.Types ( unboxedUnitTy )
|
| 36 | 41 | |
| ... | ... | @@ -64,9 +69,6 @@ import GHC.Core.Unfold |
| 64 | 69 | |
| 65 | 70 | import Data.List( partition )
|
| 66 | 71 | -- import Data.List.NonEmpty ( NonEmpty (..) )
|
| 67 | -import GHC.Core.Subst (substTickish)
|
|
| 68 | -import GHC.Core.TyCon (tyConClass_maybe)
|
|
| 69 | -import GHC.Core.DataCon (dataConTyCon)
|
|
| 70 | 72 | |
| 71 | 73 | {-
|
| 72 | 74 | ************************************************************************
|
| ... | ... | @@ -1609,7 +1611,8 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1609 | 1611 | fn_unf = realIdUnfolding fn -- Ignore loop-breaker-ness here
|
| 1610 | 1612 | inl_prag = idInlinePragma fn
|
| 1611 | 1613 | inl_act = inlinePragmaActivation inl_prag
|
| 1612 | - is_active = isActive (beginPhase inl_act) :: Activation -> Bool
|
|
| 1614 | + is_active :: Activation -> Bool
|
|
| 1615 | + is_active = isActive (SimplPhaseRange (beginPhase inl_act) (endPhase inl_act))
|
|
| 1613 | 1616 | -- is_active: inl_act is the activation we are going to put in the new
|
| 1614 | 1617 | -- SPEC rule; so we want to see if it is covered by another rule with
|
| 1615 | 1618 | -- that same activation.
|
| ... | ... | @@ -921,10 +921,8 @@ mkStrWrapperInlinePrag (InlinePragma { inl_inline = fn_inl |
| 921 | 921 | -- The phase /after/ the rule is first active
|
| 922 | 922 | get_rule_phase rule = nextPhase (beginPhase (ruleActivation rule))
|
| 923 | 923 | |
| 924 | -{-
|
|
| 925 | -Note [Demand on the worker]
|
|
| 926 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 927 | - |
|
| 924 | +{- Note [Demand on the worker]
|
|
| 925 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 928 | 926 | If the original function is called once, according to its demand info, then
|
| 929 | 927 | so is the worker. This is important so that the occurrence analyser can
|
| 930 | 928 | attach OneShot annotations to the worker’s lambda binders.
|
| ... | ... | @@ -1902,7 +1902,7 @@ ruleCheckProgram :: RuleOpts -- ^ Rule options |
| 1902 | 1902 | -> (Id -> [CoreRule]) -- ^ Rules for an Id
|
| 1903 | 1903 | -> CoreProgram -- ^ Bindings to check in
|
| 1904 | 1904 | -> SDoc -- ^ Resulting check message
|
| 1905 | -ruleCheckProgram ropts phase rule_pat rules binds
|
|
| 1905 | +ruleCheckProgram ropts curr_phase rule_pat rules binds
|
|
| 1906 | 1906 | | isEmptyBag results
|
| 1907 | 1907 | = text "Rule check results: no rule application sites"
|
| 1908 | 1908 | | otherwise
|
| ... | ... | @@ -1912,9 +1912,9 @@ ruleCheckProgram ropts phase rule_pat rules binds |
| 1912 | 1912 | ]
|
| 1913 | 1913 | where
|
| 1914 | 1914 | line = text (replicate 20 '-')
|
| 1915 | - env = RuleCheckEnv { rc_is_active = isActive phase
|
|
| 1916 | - , rc_id_unf = idUnfolding -- Not quite right
|
|
| 1917 | - -- Should use activeUnfolding
|
|
| 1915 | + is_active = isActiveInPhase curr_phase
|
|
| 1916 | + env = RuleCheckEnv { rc_is_active = is_active
|
|
| 1917 | + , rc_id_unf = whenActiveUnfoldingFun is_active
|
|
| 1918 | 1918 | , rc_pattern = rule_pat
|
| 1919 | 1919 | , rc_rules = rules
|
| 1920 | 1920 | , rc_ropts = ropts
|
| ... | ... | @@ -20,7 +20,7 @@ import GHC.Core.Lint |
| 20 | 20 | import GHC.Core.Lint.Interactive
|
| 21 | 21 | import GHC.Core.Opt.Pipeline.Types
|
| 22 | 22 | import GHC.Core.Opt.Simplify ( SimplifyOpts(..) )
|
| 23 | -import GHC.Core.Opt.Simplify.Env ( SimplMode(..) )
|
|
| 23 | +import GHC.Core.Opt.Simplify.Env ( SimplMode(..), SimplPhase(..) )
|
|
| 24 | 24 | import GHC.Core.Opt.Monad
|
| 25 | 25 | import GHC.Core.Coercion
|
| 26 | 26 | |
| ... | ... | @@ -114,9 +114,9 @@ initLintPassResultConfig dflags extra_vars pass = LintPassResultConfig |
| 114 | 114 | showLintWarnings :: CoreToDo -> Bool
|
| 115 | 115 | -- Disable Lint warnings on the first simplifier pass, because
|
| 116 | 116 | -- there may be some INLINE knots still tied, which is tiresomely noisy
|
| 117 | -showLintWarnings (CoreDoSimplify cfg) = case sm_phase (so_mode cfg) of
|
|
| 118 | - InitialPhase -> False
|
|
| 119 | - _ -> True
|
|
| 117 | +showLintWarnings (CoreDoSimplify cfg)
|
|
| 118 | + | SimplPhase InitialPhase <- sm_phase (so_mode cfg)
|
|
| 119 | + = False
|
|
| 120 | 120 | showLintWarnings _ = True
|
| 121 | 121 | |
| 122 | 122 | perPassFlags :: DynFlags -> CoreToDo -> LintFlags
|
| ... | ... | @@ -10,7 +10,7 @@ import GHC.Prelude |
| 10 | 10 | import GHC.Core.Rules ( RuleBase )
|
| 11 | 11 | import GHC.Core.Opt.Pipeline.Types ( CoreToDo(..) )
|
| 12 | 12 | import GHC.Core.Opt.Simplify ( SimplifyExprOpts(..), SimplifyOpts(..) )
|
| 13 | -import GHC.Core.Opt.Simplify.Env ( FloatEnable(..), SimplMode(..) )
|
|
| 13 | +import GHC.Core.Opt.Simplify.Env ( FloatEnable(..), SimplMode(..), SimplPhase(..) )
|
|
| 14 | 14 | import GHC.Core.Opt.Simplify.Monad ( TopEnvConfig(..) )
|
| 15 | 15 | |
| 16 | 16 | import GHC.Driver.Config ( initOptCoercionOpts )
|
| ... | ... | @@ -59,7 +59,7 @@ initSimplifyOpts dflags extra_vars iterations mode hpt_rule_base = let |
| 59 | 59 | initSimplMode :: DynFlags -> CompilerPhase -> String -> SimplMode
|
| 60 | 60 | initSimplMode dflags phase name = SimplMode
|
| 61 | 61 | { sm_names = [name]
|
| 62 | - , sm_phase = phase
|
|
| 62 | + , sm_phase = SimplPhase phase
|
|
| 63 | 63 | , sm_rules = gopt Opt_EnableRewriteRules dflags
|
| 64 | 64 | , sm_eta_expand = gopt Opt_DoLambdaEtaExpansion dflags
|
| 65 | 65 | , sm_cast_swizzle = True
|
| ... | ... | @@ -734,13 +734,14 @@ instance NoAnn AnnSpecSig where |
| 734 | 734 | data ActivationAnn
|
| 735 | 735 | = ActivationAnn {
|
| 736 | 736 | aa_openc :: EpToken "[",
|
| 737 | + aa_phase :: SourceText,
|
|
| 737 | 738 | aa_closec :: EpToken "]",
|
| 738 | 739 | aa_tilde :: Maybe (EpToken "~"),
|
| 739 | 740 | aa_val :: Maybe EpaLocation
|
| 740 | 741 | } deriving (Data, Eq)
|
| 741 | 742 | |
| 742 | 743 | instance NoAnn ActivationAnn where
|
| 743 | - noAnn = ActivationAnn noAnn noAnn noAnn noAnn
|
|
| 744 | + noAnn = ActivationAnn noAnn NoSourceText noAnn noAnn noAnn
|
|
| 744 | 745 | |
| 745 | 746 | |
| 746 | 747 | -- | Optional namespace specifier for fixity signatures,
|
| ... | ... | @@ -1189,11 +1189,11 @@ repRuleMatch ConLike = dataCon conLikeDataConName |
| 1189 | 1189 | repRuleMatch FunLike = dataCon funLikeDataConName
|
| 1190 | 1190 | |
| 1191 | 1191 | repPhases :: Activation -> MetaM (Core TH.Phases)
|
| 1192 | -repPhases (ActiveBefore _ i) = do { MkC arg <- coreIntLit i
|
|
| 1193 | - ; dataCon' beforePhaseDataConName [arg] }
|
|
| 1194 | -repPhases (ActiveAfter _ i) = do { MkC arg <- coreIntLit i
|
|
| 1195 | - ; dataCon' fromPhaseDataConName [arg] }
|
|
| 1196 | -repPhases _ = dataCon allPhasesDataConName
|
|
| 1192 | +repPhases (ActiveBefore i) = do { MkC arg <- coreIntLit i
|
|
| 1193 | + ; dataCon' beforePhaseDataConName [arg] }
|
|
| 1194 | +repPhases (ActiveAfter i) = do { MkC arg <- coreIntLit i
|
|
| 1195 | + ; dataCon' fromPhaseDataConName [arg] }
|
|
| 1196 | +repPhases _ = dataCon allPhasesDataConName
|
|
| 1197 | 1197 | |
| 1198 | 1198 | rep_complete_sig :: [LocatedN Name]
|
| 1199 | 1199 | -> Maybe (LocatedN Name)
|
| ... | ... | @@ -1949,7 +1949,7 @@ rule :: { LRuleDecl GhcPs } |
| 1949 | 1949 | , rd_bndrs = ruleBndrsOrDef $3
|
| 1950 | 1950 | , rd_lhs = $4, rd_rhs = $6 }) }
|
| 1951 | 1951 | |
| 1952 | --- Rules can be specified to be NeverActive, unlike inline/specialize pragmas
|
|
| 1952 | +-- Rules can be specified to be never active, unlike inline/specialize pragmas
|
|
| 1953 | 1953 | rule_activation :: { (ActivationAnn, Maybe Activation) }
|
| 1954 | 1954 | -- See Note [%shift: rule_activation -> {- empty -}]
|
| 1955 | 1955 | : {- empty -} %shift { (noAnn, Nothing) }
|
| ... | ... | @@ -1973,14 +1973,14 @@ rule_activation_marker :: { (Maybe (EpToken "~")) } |
| 1973 | 1973 | |
| 1974 | 1974 | rule_explicit_activation :: { ( ActivationAnn
|
| 1975 | 1975 | , Activation) } -- In brackets
|
| 1976 | - : '[' INTEGER ']' { ( ActivationAnn (epTok $1) (epTok $3) Nothing (Just (glR $2))
|
|
| 1977 | - , ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) }
|
|
| 1976 | + : '[' INTEGER ']' { ( ActivationAnn (epTok $1) (getINTEGERs $2) (epTok $3) Nothing (Just (glR $2))
|
|
| 1977 | + , ActiveAfter (fromInteger (il_value (getINTEGER $2)))) }
|
|
| 1978 | 1978 | | '[' rule_activation_marker INTEGER ']'
|
| 1979 | - { ( ActivationAnn (epTok $1) (epTok $4) $2 (Just (glR $3))
|
|
| 1980 | - , ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) }
|
|
| 1979 | + { ( ActivationAnn (epTok $1) (getINTEGERs $3) (epTok $4) $2 (Just (glR $3))
|
|
| 1980 | + , ActiveBefore (fromInteger (il_value (getINTEGER $3)))) }
|
|
| 1981 | 1981 | | '[' rule_activation_marker ']'
|
| 1982 | - { ( ActivationAnn (epTok $1) (epTok $3) $2 Nothing
|
|
| 1983 | - , NeverActive) }
|
|
| 1982 | + { ( ActivationAnn (epTok $1) NoSourceText (epTok $3) $2 Nothing
|
|
| 1983 | + , NeverActive ) }
|
|
| 1984 | 1984 | |
| 1985 | 1985 | rule_foralls :: { Maybe (RuleBndrs GhcPs) }
|
| 1986 | 1986 | : 'forall' rule_vars '.' 'forall' rule_vars '.'
|
| ... | ... | @@ -2825,11 +2825,11 @@ activation :: { (ActivationAnn,Maybe Activation) } |
| 2825 | 2825 | | explicit_activation { (fst $1,Just (snd $1)) }
|
| 2826 | 2826 | |
| 2827 | 2827 | explicit_activation :: { (ActivationAnn, Activation) } -- In brackets
|
| 2828 | - : '[' INTEGER ']' { (ActivationAnn (epTok $1) (epTok $3) Nothing (Just (glR $2))
|
|
| 2829 | - ,ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) }
|
|
| 2828 | + : '[' INTEGER ']' { (ActivationAnn (epTok $1) (getINTEGERs $2) (epTok $3) Nothing (Just (glR $2))
|
|
| 2829 | + ,ActiveAfter (fromInteger (il_value (getINTEGER $2)))) }
|
|
| 2830 | 2830 | | '[' rule_activation_marker INTEGER ']'
|
| 2831 | - { (ActivationAnn (epTok $1) (epTok $4) $2 (Just (glR $3))
|
|
| 2832 | - ,ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) }
|
|
| 2831 | + { (ActivationAnn (epTok $1) (getINTEGERs $3) (epTok $4) $2 (Just (glR $3))
|
|
| 2832 | + ,ActiveBefore (fromInteger (il_value (getINTEGER $3)))) }
|
|
| 2833 | 2833 | |
| 2834 | 2834 | -----------------------------------------------------------------------------
|
| 2835 | 2835 | -- Expressions
|
| ... | ... | @@ -44,7 +44,6 @@ import GHC.Iface.Env ( newGlobalBinder ) |
| 44 | 44 | |
| 45 | 45 | import GHC.Types.Name hiding ( varName )
|
| 46 | 46 | import GHC.Types.Name.Reader
|
| 47 | -import GHC.Types.SourceText
|
|
| 48 | 47 | import GHC.Types.Fixity
|
| 49 | 48 | import GHC.Types.Basic
|
| 50 | 49 | import GHC.Types.SrcLoc
|
| ... | ... | @@ -379,7 +378,7 @@ mkBindsRep dflags gk loc dit@(DerivInstTys{dit_rep_tc = tycon}) = (binds, sigs) |
| 379 | 378 | max_fields = maximum $ 0 :| map dataConSourceArity datacons
|
| 380 | 379 | |
| 381 | 380 | inline1 f = L loc'' . InlineSig noAnn (L loc' f)
|
| 382 | - $ alwaysInlinePragma { inl_act = ActiveAfter NoSourceText 1 }
|
|
| 381 | + $ alwaysInlinePragma { inl_act = ActiveAfter 1 }
|
|
| 383 | 382 | |
| 384 | 383 | -- The topmost M1 (the datatype metadata) has the exact same type
|
| 385 | 384 | -- across all cases of a from/to definition, and can be factored out
|
| ... | ... | @@ -998,8 +998,8 @@ cvtRuleMatch TH.FunLike = Hs.FunLike |
| 998 | 998 | |
| 999 | 999 | cvtPhases :: TH.Phases -> Activation -> Activation
|
| 1000 | 1000 | cvtPhases AllPhases dflt = dflt
|
| 1001 | -cvtPhases (FromPhase i) _ = ActiveAfter NoSourceText i
|
|
| 1002 | -cvtPhases (BeforePhase i) _ = ActiveBefore NoSourceText i
|
|
| 1001 | +cvtPhases (FromPhase i) _ = ActiveAfter i
|
|
| 1002 | +cvtPhases (BeforePhase i) _ = ActiveBefore i
|
|
| 1003 | 1003 | |
| 1004 | 1004 | cvtRuleBndr :: TH.RuleBndr -> CvtM (Hs.LRuleBndr GhcPs)
|
| 1005 | 1005 | cvtRuleBndr (RuleVar n)
|
| ... | ... | @@ -84,11 +84,13 @@ module GHC.Types.Basic ( |
| 84 | 84 | DefMethSpec(..),
|
| 85 | 85 | SwapFlag(..), flipSwap, unSwap, notSwapped, isSwapped, pickSwap,
|
| 86 | 86 | |
| 87 | - CompilerPhase(..), PhaseNum, beginPhase, nextPhase, laterPhase,
|
|
| 87 | + CompilerPhase(..),
|
|
| 88 | + PhaseNum, nextPhase, laterPhase,
|
|
| 88 | 89 | |
| 89 | - Activation(..), isActive, competesWith,
|
|
| 90 | + Activation(..), isActiveInPhase, competesWith,
|
|
| 90 | 91 | isNeverActive, isAlwaysActive, activeInFinalPhase, activeInInitialPhase,
|
| 91 | 92 | activateAfterInitial, activateDuringFinal, activeAfter,
|
| 93 | + beginPhase, endPhase, laterThanPhase,
|
|
| 92 | 94 | |
| 93 | 95 | RuleMatchInfo(..), isConLike, isFunLike,
|
| 94 | 96 | InlineSpec(..), noUserInlineSpec,
|
| ... | ... | @@ -1464,52 +1466,76 @@ The CompilerPhase says which phase the simplifier is running in: |
| 1464 | 1466 | The phase sequencing is done by GHC.Opt.Simplify.Driver
|
| 1465 | 1467 | -}
|
| 1466 | 1468 | |
| 1467 | --- | Phase Number
|
|
| 1468 | -type PhaseNum = Int -- Compilation phase
|
|
| 1469 | - -- Phases decrease towards zero
|
|
| 1470 | - -- Zero is the last phase
|
|
| 1469 | +-- | Compilation phase number, as can be written by users in INLINE pragmas,
|
|
| 1470 | +-- SPECIALISE pragmas, and RULES.
|
|
| 1471 | +--
|
|
| 1472 | +-- - phases decrease towards zero
|
|
| 1473 | +-- - zero is the last phase
|
|
| 1474 | +--
|
|
| 1475 | +-- Does not include GHC internal "initial" and "final" phases; see 'CompilerPhase'.
|
|
| 1476 | +type PhaseNum = Int
|
|
| 1471 | 1477 | |
| 1478 | +-- | Compilation phase number, including the user-specifiable 'PhaseNum'
|
|
| 1479 | +-- and the GHC internal "initial" and "final" phases.
|
|
| 1472 | 1480 | data CompilerPhase
|
| 1473 | - = InitialPhase -- The first phase -- number = infinity!
|
|
| 1474 | - | Phase PhaseNum -- User-specificable phases
|
|
| 1475 | - | FinalPhase -- The last phase -- number = -infinity!
|
|
| 1476 | - deriving Eq
|
|
| 1481 | + = InitialPhase -- ^ The first phase; number = infinity!
|
|
| 1482 | + | Phase PhaseNum -- ^ User-specifiable phases
|
|
| 1483 | + | FinalPhase -- ^ The last phase; number = -infinity!
|
|
| 1484 | + deriving (Eq, Data)
|
|
| 1477 | 1485 | |
| 1478 | 1486 | instance Outputable CompilerPhase where
|
| 1479 | 1487 | ppr (Phase n) = int n
|
| 1480 | - ppr InitialPhase = text "InitialPhase"
|
|
| 1481 | - ppr FinalPhase = text "FinalPhase"
|
|
| 1488 | + ppr InitialPhase = text "initial"
|
|
| 1489 | + ppr FinalPhase = text "final"
|
|
| 1482 | 1490 | |
| 1483 | --- See Note [Pragma source text]
|
|
| 1491 | +-- | An activation is a range of phases throughout which something is active
|
|
| 1492 | +-- (like an INLINE pragma, SPECIALISE pragma, or RULE).
|
|
| 1484 | 1493 | data Activation
|
| 1485 | 1494 | = AlwaysActive
|
| 1486 | - | ActiveBefore SourceText PhaseNum -- Active only *strictly before* this phase
|
|
| 1487 | - | ActiveAfter SourceText PhaseNum -- Active in this phase and later
|
|
| 1488 | - | FinalActive -- Active in final phase only
|
|
| 1495 | + -- | Active only *strictly before* this phase
|
|
| 1496 | + | ActiveBefore PhaseNum
|
|
| 1497 | + -- | Active in this phase and later phases
|
|
| 1498 | + | ActiveAfter PhaseNum
|
|
| 1499 | + -- | Active in the final phase only
|
|
| 1500 | + | FinalActive
|
|
| 1489 | 1501 | | NeverActive
|
| 1490 | 1502 | deriving( Eq, Data )
|
| 1491 | 1503 | -- Eq used in comparing rules in GHC.Hs.Decls
|
| 1492 | 1504 | |
| 1493 | 1505 | beginPhase :: Activation -> CompilerPhase
|
| 1494 | --- First phase in which the Activation is active
|
|
| 1495 | --- or FinalPhase if it is never active
|
|
| 1506 | +-- ^ First phase in which the 'Activation' is active,
|
|
| 1507 | +-- or 'FinalPhase' if it is never active
|
|
| 1496 | 1508 | beginPhase AlwaysActive = InitialPhase
|
| 1497 | 1509 | beginPhase (ActiveBefore {}) = InitialPhase
|
| 1498 | -beginPhase (ActiveAfter _ n) = Phase n
|
|
| 1510 | +beginPhase (ActiveAfter n) = Phase n
|
|
| 1499 | 1511 | beginPhase FinalActive = FinalPhase
|
| 1500 | 1512 | beginPhase NeverActive = FinalPhase
|
| 1501 | 1513 | |
| 1514 | +endPhase :: Activation -> CompilerPhase
|
|
| 1515 | +-- ^ Last phase in which the 'Activation' is active,
|
|
| 1516 | +-- or 'InitialPhase' if it is never active
|
|
| 1517 | +endPhase AlwaysActive = FinalPhase
|
|
| 1518 | +endPhase (ActiveBefore n) =
|
|
| 1519 | + if nextPhase InitialPhase == Phase n
|
|
| 1520 | + then InitialPhase
|
|
| 1521 | + else Phase $ n + 1
|
|
| 1522 | +endPhase (ActiveAfter {}) = FinalPhase
|
|
| 1523 | +endPhase FinalActive = FinalPhase
|
|
| 1524 | +endPhase NeverActive = InitialPhase
|
|
| 1525 | + |
|
| 1502 | 1526 | activeAfter :: CompilerPhase -> Activation
|
| 1503 | --- (activeAfter p) makes an Activation that is active in phase p and after
|
|
| 1504 | --- Invariant: beginPhase (activeAfter p) = p
|
|
| 1527 | +-- ^ @activeAfter p@ makes an 'Activation' that is active in phase @p@ and after
|
|
| 1528 | +--
|
|
| 1529 | +-- Invariant: @beginPhase (activeAfter p) = p@
|
|
| 1505 | 1530 | activeAfter InitialPhase = AlwaysActive
|
| 1506 | -activeAfter (Phase n) = ActiveAfter NoSourceText n
|
|
| 1531 | +activeAfter (Phase n) = ActiveAfter n
|
|
| 1507 | 1532 | activeAfter FinalPhase = FinalActive
|
| 1508 | 1533 | |
| 1509 | 1534 | nextPhase :: CompilerPhase -> CompilerPhase
|
| 1510 | --- Tells you the next phase after this one
|
|
| 1511 | --- Currently we have just phases [2,1,0,FinalPhase,FinalPhase,...]
|
|
| 1512 | --- Where FinalPhase means GHC's internal simplification steps
|
|
| 1535 | +-- ^ Tells you the next phase after this one
|
|
| 1536 | +--
|
|
| 1537 | +-- Currently we have just phases @[2,1,0,FinalPhase,FinalPhase,...]@,
|
|
| 1538 | +-- where FinalPhase means GHC's internal simplification steps
|
|
| 1513 | 1539 | -- after all rules have run
|
| 1514 | 1540 | nextPhase InitialPhase = Phase 2
|
| 1515 | 1541 | nextPhase (Phase 0) = FinalPhase
|
| ... | ... | @@ -1517,37 +1543,45 @@ nextPhase (Phase n) = Phase (n-1) |
| 1517 | 1543 | nextPhase FinalPhase = FinalPhase
|
| 1518 | 1544 | |
| 1519 | 1545 | laterPhase :: CompilerPhase -> CompilerPhase -> CompilerPhase
|
| 1520 | --- Returns the later of two phases
|
|
| 1546 | +-- ^ Returns the later of two phases
|
|
| 1521 | 1547 | laterPhase (Phase n1) (Phase n2) = Phase (n1 `min` n2)
|
| 1522 | 1548 | laterPhase InitialPhase p2 = p2
|
| 1523 | 1549 | laterPhase FinalPhase _ = FinalPhase
|
| 1524 | 1550 | laterPhase p1 InitialPhase = p1
|
| 1525 | 1551 | laterPhase _ FinalPhase = FinalPhase
|
| 1526 | 1552 | |
| 1553 | +-- | @p1 `laterThanOrEqualPhase` p2@ computes whether @p1@ happens (strictly)
|
|
| 1554 | +-- after @p2@.
|
|
| 1555 | +laterThanPhase :: CompilerPhase -> CompilerPhase -> Bool
|
|
| 1556 | +p1 `laterThanPhase` p2 = toNum p1 < toNum p2
|
|
| 1557 | + where
|
|
| 1558 | + toNum :: CompilerPhase -> Int
|
|
| 1559 | + toNum InitialPhase = maxBound
|
|
| 1560 | + toNum (Phase i) = i
|
|
| 1561 | + toNum FinalPhase = minBound
|
|
| 1562 | + |
|
| 1527 | 1563 | activateAfterInitial :: Activation
|
| 1528 | --- Active in the first phase after the initial phase
|
|
| 1564 | +-- ^ Active in the first phase after the initial phase
|
|
| 1529 | 1565 | activateAfterInitial = activeAfter (nextPhase InitialPhase)
|
| 1530 | 1566 | |
| 1531 | 1567 | activateDuringFinal :: Activation
|
| 1532 | --- Active in the final simplification phase (which is repeated)
|
|
| 1568 | +-- ^ Active in the final simplification phase (which is repeated)
|
|
| 1533 | 1569 | activateDuringFinal = FinalActive
|
| 1534 | 1570 | |
| 1535 | -isActive :: CompilerPhase -> Activation -> Bool
|
|
| 1536 | -isActive InitialPhase act = activeInInitialPhase act
|
|
| 1537 | -isActive (Phase p) act = activeInPhase p act
|
|
| 1538 | -isActive FinalPhase act = activeInFinalPhase act
|
|
| 1571 | +isActiveInPhase :: CompilerPhase -> Activation -> Bool
|
|
| 1572 | +isActiveInPhase InitialPhase act = activeInInitialPhase act
|
|
| 1573 | +isActiveInPhase (Phase p) act = activeInPhase p act
|
|
| 1574 | +isActiveInPhase FinalPhase act = activeInFinalPhase act
|
|
| 1539 | 1575 | |
| 1540 | 1576 | activeInInitialPhase :: Activation -> Bool
|
| 1541 | -activeInInitialPhase AlwaysActive = True
|
|
| 1542 | -activeInInitialPhase (ActiveBefore {}) = True
|
|
| 1543 | -activeInInitialPhase _ = False
|
|
| 1577 | +activeInInitialPhase act = beginPhase act == InitialPhase
|
|
| 1544 | 1578 | |
| 1545 | 1579 | activeInPhase :: PhaseNum -> Activation -> Bool
|
| 1546 | -activeInPhase _ AlwaysActive = True
|
|
| 1547 | -activeInPhase _ NeverActive = False
|
|
| 1548 | -activeInPhase _ FinalActive = False
|
|
| 1549 | -activeInPhase p (ActiveAfter _ n) = p <= n
|
|
| 1550 | -activeInPhase p (ActiveBefore _ n) = p > n
|
|
| 1580 | +activeInPhase _ AlwaysActive = True
|
|
| 1581 | +activeInPhase _ NeverActive = False
|
|
| 1582 | +activeInPhase _ FinalActive = False
|
|
| 1583 | +activeInPhase p (ActiveAfter n) = p <= n
|
|
| 1584 | +activeInPhase p (ActiveBefore n) = p > n
|
|
| 1551 | 1585 | |
| 1552 | 1586 | activeInFinalPhase :: Activation -> Bool
|
| 1553 | 1587 | activeInFinalPhase AlwaysActive = True
|
| ... | ... | @@ -1562,25 +1596,19 @@ isNeverActive _ = False |
| 1562 | 1596 | isAlwaysActive AlwaysActive = True
|
| 1563 | 1597 | isAlwaysActive _ = False
|
| 1564 | 1598 | |
| 1565 | -competesWith :: Activation -> Activation -> Bool
|
|
| 1599 | +-- | @act1 `competesWith` act2@ returns whether @act1@ is active in the phase
|
|
| 1600 | +-- when @act2@ __becomes__ active.
|
|
| 1601 | +--
|
|
| 1602 | +-- This answers the question: might @act1@ fire first?
|
|
| 1603 | +--
|
|
| 1604 | +-- NB: this is not the same as computing whether @act1@ and @act2@ are
|
|
| 1605 | +-- ever active at the same time.
|
|
| 1606 | +--
|
|
| 1566 | 1607 | -- See Note [Competing activations]
|
| 1567 | -competesWith AlwaysActive _ = True
|
|
| 1568 | - |
|
| 1569 | -competesWith NeverActive _ = False
|
|
| 1570 | -competesWith _ NeverActive = False
|
|
| 1571 | - |
|
| 1572 | -competesWith FinalActive FinalActive = True
|
|
| 1573 | -competesWith FinalActive _ = False
|
|
| 1574 | - |
|
| 1575 | -competesWith (ActiveBefore {}) AlwaysActive = True
|
|
| 1576 | -competesWith (ActiveBefore {}) FinalActive = False
|
|
| 1577 | -competesWith (ActiveBefore {}) (ActiveBefore {}) = True
|
|
| 1578 | -competesWith (ActiveBefore _ a) (ActiveAfter _ b) = a < b
|
|
| 1579 | - |
|
| 1580 | -competesWith (ActiveAfter {}) AlwaysActive = False
|
|
| 1581 | -competesWith (ActiveAfter {}) FinalActive = True
|
|
| 1582 | -competesWith (ActiveAfter {}) (ActiveBefore {}) = False
|
|
| 1583 | -competesWith (ActiveAfter _ a) (ActiveAfter _ b) = a >= b
|
|
| 1608 | +competesWith :: Activation -> Activation -> Bool
|
|
| 1609 | +competesWith NeverActive _ = False
|
|
| 1610 | +competesWith _ NeverActive = False -- See Wrinkle [Never active rules]
|
|
| 1611 | +competesWith act1 act2 = isActiveInPhase (beginPhase act2) act1
|
|
| 1584 | 1612 | |
| 1585 | 1613 | {- Note [Competing activations]
|
| 1586 | 1614 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1595,8 +1623,20 @@ It's too conservative to ensure that the two are never simultaneously |
| 1595 | 1623 | active. For example, a rule might be always active, and an inlining
|
| 1596 | 1624 | might switch on in phase 2. We could switch off the rule, but it does
|
| 1597 | 1625 | no harm.
|
| 1598 | --}
|
|
| 1599 | 1626 | |
| 1627 | + Wrinkle [Never active rules]
|
|
| 1628 | + |
|
| 1629 | + Rules can be declared as "never active" by users, using the syntax:
|
|
| 1630 | + |
|
| 1631 | + {-# RULE "blah" [~] ... #-}
|
|
| 1632 | + |
|
| 1633 | + (This feature exists solely for compiler plugins, by making it possible
|
|
| 1634 | + to define a RULE that is never run by GHC, but is nevertheless parsed,
|
|
| 1635 | + typechecked etc, so that it is available to the plugin.)
|
|
| 1636 | + |
|
| 1637 | + We should not warn about competing rules, so make sure that 'competesWith'
|
|
| 1638 | + always returns 'False' when its second argument is 'NeverActive'.
|
|
| 1639 | +-}
|
|
| 1600 | 1640 | |
| 1601 | 1641 | {- *********************************************************************
|
| 1602 | 1642 | * *
|
| ... | ... | @@ -1855,26 +1895,36 @@ setInlinePragmaRuleMatchInfo :: InlinePragma -> RuleMatchInfo -> InlinePragma |
| 1855 | 1895 | setInlinePragmaRuleMatchInfo prag info = prag { inl_rule = info }
|
| 1856 | 1896 | |
| 1857 | 1897 | instance Outputable Activation where
|
| 1858 | - ppr AlwaysActive = empty
|
|
| 1859 | - ppr NeverActive = brackets (text "~")
|
|
| 1860 | - ppr (ActiveBefore _ n) = brackets (char '~' <> int n)
|
|
| 1861 | - ppr (ActiveAfter _ n) = brackets (int n)
|
|
| 1862 | - ppr FinalActive = text "[final]"
|
|
| 1898 | + ppr AlwaysActive = empty
|
|
| 1899 | + ppr NeverActive = brackets (text "~")
|
|
| 1900 | + ppr (ActiveBefore n) = brackets (char '~' <> int n)
|
|
| 1901 | + ppr (ActiveAfter n) = brackets (int n)
|
|
| 1902 | + ppr FinalActive = text "[final]"
|
|
| 1903 | + |
|
| 1904 | +instance Binary CompilerPhase where
|
|
| 1905 | + put_ bh InitialPhase = putByte bh 0
|
|
| 1906 | + put_ bh (Phase i) = do { putByte bh 1; put_ bh i }
|
|
| 1907 | + put_ bh FinalPhase = putByte bh 2
|
|
| 1908 | + |
|
| 1909 | + get bh = do
|
|
| 1910 | + h <- getByte bh
|
|
| 1911 | + case h of
|
|
| 1912 | + 0 -> return InitialPhase
|
|
| 1913 | + 1 -> do { p <- get bh; return (Phase p) }
|
|
| 1914 | + _ -> return FinalPhase
|
|
| 1863 | 1915 | |
| 1864 | 1916 | instance Binary Activation where
|
| 1865 | 1917 | put_ bh NeverActive =
|
| 1866 | 1918 | putByte bh 0
|
| 1867 | - put_ bh FinalActive =
|
|
| 1919 | + put_ bh FinalActive = do
|
|
| 1868 | 1920 | putByte bh 1
|
| 1869 | 1921 | put_ bh AlwaysActive =
|
| 1870 | 1922 | putByte bh 2
|
| 1871 | - put_ bh (ActiveBefore src aa) = do
|
|
| 1923 | + put_ bh (ActiveBefore aa) = do
|
|
| 1872 | 1924 | putByte bh 3
|
| 1873 | - put_ bh src
|
|
| 1874 | 1925 | put_ bh aa
|
| 1875 | - put_ bh (ActiveAfter src ab) = do
|
|
| 1926 | + put_ bh (ActiveAfter ab) = do
|
|
| 1876 | 1927 | putByte bh 4
|
| 1877 | - put_ bh src
|
|
| 1878 | 1928 | put_ bh ab
|
| 1879 | 1929 | get bh = do
|
| 1880 | 1930 | h <- getByte bh
|
| ... | ... | @@ -1882,19 +1932,21 @@ instance Binary Activation where |
| 1882 | 1932 | 0 -> return NeverActive
|
| 1883 | 1933 | 1 -> return FinalActive
|
| 1884 | 1934 | 2 -> return AlwaysActive
|
| 1885 | - 3 -> do src <- get bh
|
|
| 1886 | - aa <- get bh
|
|
| 1887 | - return (ActiveBefore src aa)
|
|
| 1888 | - _ -> do src <- get bh
|
|
| 1889 | - ab <- get bh
|
|
| 1890 | - return (ActiveAfter src ab)
|
|
| 1891 | - |
|
| 1935 | + 3 -> do aa <- get bh
|
|
| 1936 | + return (ActiveBefore aa)
|
|
| 1937 | + _ -> do ab <- get bh
|
|
| 1938 | + return (ActiveAfter ab)
|
|
| 1939 | +instance NFData CompilerPhase where
|
|
| 1940 | + rnf = \case
|
|
| 1941 | + InitialPhase -> ()
|
|
| 1942 | + FinalPhase -> ()
|
|
| 1943 | + Phase i -> rnf i
|
|
| 1892 | 1944 | instance NFData Activation where
|
| 1893 | 1945 | rnf = \case
|
| 1894 | 1946 | AlwaysActive -> ()
|
| 1895 | 1947 | NeverActive -> ()
|
| 1896 | - ActiveBefore src aa -> rnf src `seq` rnf aa
|
|
| 1897 | - ActiveAfter src ab -> rnf src `seq` rnf ab
|
|
| 1948 | + ActiveBefore aa -> rnf aa
|
|
| 1949 | + ActiveAfter ab -> rnf ab
|
|
| 1898 | 1950 | FinalActive -> ()
|
| 1899 | 1951 | |
| 1900 | 1952 | instance Outputable RuleMatchInfo where
|
| ... | ... | @@ -67,7 +67,6 @@ import GHC.Core.Class |
| 67 | 67 | import GHC.Core.DataCon
|
| 68 | 68 | |
| 69 | 69 | import GHC.Types.Literal
|
| 70 | -import GHC.Types.SourceText
|
|
| 71 | 70 | import GHC.Types.RepType ( countFunRepArgs, typePrimRep )
|
| 72 | 71 | import GHC.Types.Name.Set
|
| 73 | 72 | import GHC.Types.Name
|
| ... | ... | @@ -1926,8 +1925,7 @@ seqId = pcRepPolyId seqName ty concs info |
| 1926 | 1925 | `setArityInfo` arity
|
| 1927 | 1926 | |
| 1928 | 1927 | inline_prag
|
| 1929 | - = alwaysInlinePragma `setInlinePragmaActivation` ActiveAfter
|
|
| 1930 | - NoSourceText 0
|
|
| 1928 | + = alwaysInlinePragma `setInlinePragmaActivation` ActiveAfter 0
|
|
| 1931 | 1929 | -- Make 'seq' not inline-always, so that simpleOptExpr
|
| 1932 | 1930 | -- (see GHC.Core.Subst.simple_app) won't inline 'seq' on the
|
| 1933 | 1931 | -- LHS of rules. That way we can have rules for 'seq';
|
| ... | ... | @@ -1869,172 +1869,6 @@ instance Binary ModuleName where |
| 1869 | 1869 | put_ bh (ModuleName fs) = put_ bh fs
|
| 1870 | 1870 | get bh = do fs <- get bh; return (ModuleName fs)
|
| 1871 | 1871 | |
| 1872 | --- instance Binary TupleSort where
|
|
| 1873 | --- put_ bh BoxedTuple = putByte bh 0
|
|
| 1874 | --- put_ bh UnboxedTuple = putByte bh 1
|
|
| 1875 | --- put_ bh ConstraintTuple = putByte bh 2
|
|
| 1876 | --- get bh = do
|
|
| 1877 | --- h <- getByte bh
|
|
| 1878 | --- case h of
|
|
| 1879 | --- 0 -> do return BoxedTuple
|
|
| 1880 | --- 1 -> do return UnboxedTuple
|
|
| 1881 | --- _ -> do return ConstraintTuple
|
|
| 1882 | - |
|
| 1883 | --- instance Binary Activation where
|
|
| 1884 | --- put_ bh NeverActive = do
|
|
| 1885 | --- putByte bh 0
|
|
| 1886 | --- put_ bh FinalActive = do
|
|
| 1887 | --- putByte bh 1
|
|
| 1888 | --- put_ bh AlwaysActive = do
|
|
| 1889 | --- putByte bh 2
|
|
| 1890 | --- put_ bh (ActiveBefore src aa) = do
|
|
| 1891 | --- putByte bh 3
|
|
| 1892 | --- put_ bh src
|
|
| 1893 | --- put_ bh aa
|
|
| 1894 | --- put_ bh (ActiveAfter src ab) = do
|
|
| 1895 | --- putByte bh 4
|
|
| 1896 | --- put_ bh src
|
|
| 1897 | --- put_ bh ab
|
|
| 1898 | --- get bh = do
|
|
| 1899 | --- h <- getByte bh
|
|
| 1900 | --- case h of
|
|
| 1901 | --- 0 -> do return NeverActive
|
|
| 1902 | --- 1 -> do return FinalActive
|
|
| 1903 | --- 2 -> do return AlwaysActive
|
|
| 1904 | --- 3 -> do src <- get bh
|
|
| 1905 | --- aa <- get bh
|
|
| 1906 | --- return (ActiveBefore src aa)
|
|
| 1907 | --- _ -> do src <- get bh
|
|
| 1908 | --- ab <- get bh
|
|
| 1909 | --- return (ActiveAfter src ab)
|
|
| 1910 | - |
|
| 1911 | --- instance Binary InlinePragma where
|
|
| 1912 | --- put_ bh (InlinePragma s a b c d) = do
|
|
| 1913 | --- put_ bh s
|
|
| 1914 | --- put_ bh a
|
|
| 1915 | --- put_ bh b
|
|
| 1916 | --- put_ bh c
|
|
| 1917 | --- put_ bh d
|
|
| 1918 | - |
|
| 1919 | --- get bh = do
|
|
| 1920 | --- s <- get bh
|
|
| 1921 | --- a <- get bh
|
|
| 1922 | --- b <- get bh
|
|
| 1923 | --- c <- get bh
|
|
| 1924 | --- d <- get bh
|
|
| 1925 | --- return (InlinePragma s a b c d)
|
|
| 1926 | - |
|
| 1927 | --- instance Binary RuleMatchInfo where
|
|
| 1928 | --- put_ bh FunLike = putByte bh 0
|
|
| 1929 | --- put_ bh ConLike = putByte bh 1
|
|
| 1930 | --- get bh = do
|
|
| 1931 | --- h <- getByte bh
|
|
| 1932 | --- if h == 1 then return ConLike
|
|
| 1933 | --- else return FunLike
|
|
| 1934 | - |
|
| 1935 | --- instance Binary InlineSpec where
|
|
| 1936 | --- put_ bh NoUserInlinePrag = putByte bh 0
|
|
| 1937 | --- put_ bh Inline = putByte bh 1
|
|
| 1938 | --- put_ bh Inlinable = putByte bh 2
|
|
| 1939 | --- put_ bh NoInline = putByte bh 3
|
|
| 1940 | - |
|
| 1941 | --- get bh = do h <- getByte bh
|
|
| 1942 | --- case h of
|
|
| 1943 | --- 0 -> return NoUserInlinePrag
|
|
| 1944 | --- 1 -> return Inline
|
|
| 1945 | --- 2 -> return Inlinable
|
|
| 1946 | --- _ -> return NoInline
|
|
| 1947 | - |
|
| 1948 | --- instance Binary RecFlag where
|
|
| 1949 | --- put_ bh Recursive = do
|
|
| 1950 | --- putByte bh 0
|
|
| 1951 | --- put_ bh NonRecursive = do
|
|
| 1952 | --- putByte bh 1
|
|
| 1953 | --- get bh = do
|
|
| 1954 | --- h <- getByte bh
|
|
| 1955 | --- case h of
|
|
| 1956 | --- 0 -> do return Recursive
|
|
| 1957 | --- _ -> do return NonRecursive
|
|
| 1958 | - |
|
| 1959 | --- instance Binary OverlapMode where
|
|
| 1960 | --- put_ bh (NoOverlap s) = putByte bh 0 >> put_ bh s
|
|
| 1961 | --- put_ bh (Overlaps s) = putByte bh 1 >> put_ bh s
|
|
| 1962 | --- put_ bh (Incoherent s) = putByte bh 2 >> put_ bh s
|
|
| 1963 | --- put_ bh (Overlapping s) = putByte bh 3 >> put_ bh s
|
|
| 1964 | --- put_ bh (Overlappable s) = putByte bh 4 >> put_ bh s
|
|
| 1965 | --- get bh = do
|
|
| 1966 | --- h <- getByte bh
|
|
| 1967 | --- case h of
|
|
| 1968 | --- 0 -> (get bh) >>= \s -> return $ NoOverlap s
|
|
| 1969 | --- 1 -> (get bh) >>= \s -> return $ Overlaps s
|
|
| 1970 | --- 2 -> (get bh) >>= \s -> return $ Incoherent s
|
|
| 1971 | --- 3 -> (get bh) >>= \s -> return $ Overlapping s
|
|
| 1972 | --- 4 -> (get bh) >>= \s -> return $ Overlappable s
|
|
| 1973 | --- _ -> panic ("get OverlapMode" ++ show h)
|
|
| 1974 | - |
|
| 1975 | - |
|
| 1976 | --- instance Binary OverlapFlag where
|
|
| 1977 | --- put_ bh flag = do put_ bh (overlapMode flag)
|
|
| 1978 | --- put_ bh (isSafeOverlap flag)
|
|
| 1979 | --- get bh = do
|
|
| 1980 | --- h <- get bh
|
|
| 1981 | --- b <- get bh
|
|
| 1982 | --- return OverlapFlag { overlapMode = h, isSafeOverlap = b }
|
|
| 1983 | - |
|
| 1984 | --- instance Binary FixityDirection where
|
|
| 1985 | --- put_ bh InfixL = do
|
|
| 1986 | --- putByte bh 0
|
|
| 1987 | --- put_ bh InfixR = do
|
|
| 1988 | --- putByte bh 1
|
|
| 1989 | --- put_ bh InfixN = do
|
|
| 1990 | --- putByte bh 2
|
|
| 1991 | --- get bh = do
|
|
| 1992 | --- h <- getByte bh
|
|
| 1993 | --- case h of
|
|
| 1994 | --- 0 -> do return InfixL
|
|
| 1995 | --- 1 -> do return InfixR
|
|
| 1996 | --- _ -> do return InfixN
|
|
| 1997 | - |
|
| 1998 | --- instance Binary Fixity where
|
|
| 1999 | --- put_ bh (Fixity src aa ab) = do
|
|
| 2000 | --- put_ bh src
|
|
| 2001 | --- put_ bh aa
|
|
| 2002 | --- put_ bh ab
|
|
| 2003 | --- get bh = do
|
|
| 2004 | --- src <- get bh
|
|
| 2005 | --- aa <- get bh
|
|
| 2006 | --- ab <- get bh
|
|
| 2007 | --- return (Fixity src aa ab)
|
|
| 2008 | - |
|
| 2009 | --- instance Binary WarningTxt where
|
|
| 2010 | --- put_ bh (WarningTxt s w) = do
|
|
| 2011 | --- putByte bh 0
|
|
| 2012 | --- put_ bh s
|
|
| 2013 | --- put_ bh w
|
|
| 2014 | --- put_ bh (DeprecatedTxt s d) = do
|
|
| 2015 | --- putByte bh 1
|
|
| 2016 | --- put_ bh s
|
|
| 2017 | --- put_ bh d
|
|
| 2018 | - |
|
| 2019 | --- get bh = do
|
|
| 2020 | --- h <- getByte bh
|
|
| 2021 | --- case h of
|
|
| 2022 | --- 0 -> do s <- get bh
|
|
| 2023 | --- w <- get bh
|
|
| 2024 | --- return (WarningTxt s w)
|
|
| 2025 | --- _ -> do s <- get bh
|
|
| 2026 | --- d <- get bh
|
|
| 2027 | --- return (DeprecatedTxt s d)
|
|
| 2028 | - |
|
| 2029 | --- instance Binary StringLiteral where
|
|
| 2030 | --- put_ bh (StringLiteral st fs _) = do
|
|
| 2031 | --- put_ bh st
|
|
| 2032 | --- put_ bh fs
|
|
| 2033 | --- get bh = do
|
|
| 2034 | --- st <- get bh
|
|
| 2035 | --- fs <- get bh
|
|
| 2036 | --- return (StringLiteral st fs Nothing)
|
|
| 2037 | - |
|
| 2038 | 1872 | newtype BinLocated a = BinLocated { unBinLocated :: Located a }
|
| 2039 | 1873 | |
| 2040 | 1874 | instance Binary a => Binary (BinLocated a) where
|
| ... | ... | @@ -5,4 +5,4 @@ |
| 5 | 5 | # cradle: {bios: {program: "./hadrian/hie-bios.bat"}}
|
| 6 | 6 | #
|
| 7 | 7 | # The format is documented here - https://github.com/mpickering/hie-bios
|
| 8 | -cradle: {bios: {program: "./hadrian/hie-bios"}} |
|
| 8 | +cradle: {bios: {program: "./hadrian/hie-bios.bat"}} |
| 1 | 1 | Rule fired: Class op foldr (BUILTIN)
|
| 2 | 2 | Rule fired: Class op return (BUILTIN)
|
| 3 | 3 | Rule fired: unpack (GHC.Internal.Base)
|
| 4 | +Rule fired: repeat (GHC.Internal.List)
|
|
| 5 | +Rule fired: take (GHC.Internal.List)
|
|
| 6 | +Rule fired: fold/build (GHC.Internal.Base)
|
|
| 4 | 7 | Rule fired: fold/build (GHC.Internal.Base)
|
| 5 | 8 | Rule fired: Class op >> (BUILTIN)
|
| 6 | 9 | Rule fired: SPEC/T4007 sequence__c @IO @_ @_ (T4007)
|
| ... | ... | @@ -5,4 +5,5 @@ Rule fired: Class op + (BUILTIN) |
| 5 | 5 | Rule fired: +# (BUILTIN)
|
| 6 | 6 | Rule fired: Class op foldr (BUILTIN)
|
| 7 | 7 | Rule fired: Class op enumFromTo (BUILTIN)
|
| 8 | +Rule fired: eftInt (GHC.Internal.Enum)
|
|
| 8 | 9 | Rule fired: fold/build (GHC.Internal.Base) |
| ... | ... | @@ -6,9 +6,11 @@ Rule fired: USPEC $fShowList @Int (GHC.Internal.Show) |
| 6 | 6 | Rule fired: Class op >> (BUILTIN)
|
| 7 | 7 | Rule fired: USPEC plusTwoRec @Int (T15445a)
|
| 8 | 8 | Rule fired: Class op enumFromTo (BUILTIN)
|
| 9 | +Rule fired: eftInt (GHC.Internal.Enum)
|
|
| 9 | 10 | Rule fired: Class op show (BUILTIN)
|
| 10 | 11 | Rule fired: USPEC plusTwoRec @Int (T15445a)
|
| 11 | 12 | Rule fired: Class op enumFromTo (BUILTIN)
|
| 13 | +Rule fired: eftInt (GHC.Internal.Enum)
|
|
| 12 | 14 | Rule fired: Class op show (BUILTIN)
|
| 13 | 15 | Rule fired: eftIntList (GHC.Internal.Enum)
|
| 14 | 16 | Rule fired: ># (BUILTIN)
|
| 1 | +module T26323b where
|
|
| 2 | + |
|
| 3 | +f :: Int -> Int
|
|
| 4 | +f _ = 0
|
|
| 5 | +{-# NOINLINE f #-}
|
|
| 6 | + |
|
| 7 | +g :: Int -> Int
|
|
| 8 | +g _ = 1
|
|
| 9 | +{-# NOINLINE g #-}
|
|
| 10 | + |
|
| 11 | +h :: Int -> Int
|
|
| 12 | +h _ = 2
|
|
| 13 | +{-# NOINLINE h #-}
|
|
| 14 | + |
|
| 15 | +-- These two RULES loop, but that's OK because they are never active
|
|
| 16 | +-- at the same time.
|
|
| 17 | +{-# RULES "t1" [1] forall x. g x = f x #-}
|
|
| 18 | +{-# RULES "t2" [~1] forall x. f x = g x #-}
|
|
| 19 | + |
|
| 20 | +-- Make sure we don't fire "t1" and "t2" in a loop in the RHS of a never-active rule.
|
|
| 21 | +{-# RULES "t" [~] forall x. h x = f x #-}
|
|
| 22 | + |
|
| 23 | +test :: Int
|
|
| 24 | +test = f 4 + g 5 + h 6 |
| ... | ... | @@ -537,6 +537,7 @@ test('T25389', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dno-typeab |
| 537 | 537 | test('T24359a', normal, compile, ['-O -ddump-rules'])
|
| 538 | 538 | test('T24606', [grep_errmsg(r'fAlternativeRWST')], compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-idinfo -dsuppress-coercions -dsuppress-coercion-types'])
|
| 539 | 539 | test('T25713', [grep_errmsg('W:::')], compile, ['-O -ddump-simpl'])
|
| 540 | +test('T26323b', normal, compile, ['-O'])
|
|
| 540 | 541 | |
| 541 | 542 | test('T25883', normal, compile_grep_core, [''])
|
| 542 | 543 | test('T25883b', normal, compile_grep_core, [''])
|
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +f :: Int -> Int
|
|
| 4 | +f x = g x
|
|
| 5 | +{-# INLINE [1] f #-}
|
|
| 6 | + |
|
| 7 | +g :: Int -> Int
|
|
| 8 | +g x = 0
|
|
| 9 | +{-# NOINLINE g #-}
|
|
| 10 | + |
|
| 11 | +h :: Int -> Int
|
|
| 12 | +h _ = 1
|
|
| 13 | +{-# NOINLINE h #-}
|
|
| 14 | + |
|
| 15 | +{-# RULES "r1" [2] forall x. g x = h x #-}
|
|
| 16 | +{-# RULES "r2" [~1] forall x. h x = 2 #-}
|
|
| 17 | + |
|
| 18 | +test :: Int
|
|
| 19 | +test = f 3
|
|
| 20 | + |
|
| 21 | +main :: IO ()
|
|
| 22 | +main = print test
|
|
| 23 | + -- we should get
|
|
| 24 | + --
|
|
| 25 | + -- f 3
|
|
| 26 | + -- ==> inline in phase 1
|
|
| 27 | + -- g 3
|
|
| 28 | + -- ==> use 'r1' in phase 1
|
|
| 29 | + -- h 3
|
|
| 30 | + -- = 1
|
|
| 31 | + --
|
|
| 32 | + -- Here rule 'r2' should never fire, so we SHOULD NOT rewrite 'h 3' to '2'. |
| 1 | +1 |
| ... | ... | @@ -93,6 +93,7 @@ test('T17151', [], multimod_compile_and_run, ['T17151', '']) |
| 93 | 93 | test('T18012', normal, compile_and_run, [''])
|
| 94 | 94 | test('T17744', normal, compile_and_run, [''])
|
| 95 | 95 | test('T18638', normal, compile_and_run, [''])
|
| 96 | +test('T26323', normal, compile_and_run, ['-O'])
|
|
| 96 | 97 | test('NumConstantFolding8', normal, compile_and_run, [''])
|
| 97 | 98 | test('NumConstantFolding16', normal, compile_and_run, [''])
|
| 98 | 99 | test('NumConstantFolding32', normal, compile_and_run, [''])
|
| ... | ... | @@ -2010,25 +2010,27 @@ instance ExactPrint (RuleDecl GhcPs) where |
| 2010 | 2010 | |
| 2011 | 2011 | markActivation :: (Monad m, Monoid w)
|
| 2012 | 2012 | => ActivationAnn -> Activation -> EP w m ActivationAnn
|
| 2013 | -markActivation (ActivationAnn o c t v) act = do
|
|
| 2013 | +markActivation (ActivationAnn o src c t v) act = do
|
|
| 2014 | 2014 | case act of
|
| 2015 | - ActiveBefore src phase -> do
|
|
| 2015 | + ActiveBefore phase -> do
|
|
| 2016 | 2016 | o' <- markEpToken o -- '['
|
| 2017 | 2017 | t' <- mapM markEpToken t -- ~
|
| 2018 | 2018 | v' <- mapM (\val -> printStringAtAA val (toSourceTextWithSuffix src (show phase) "")) v
|
| 2019 | 2019 | c' <- markEpToken c -- ']'
|
| 2020 | - return (ActivationAnn o' c' t' v')
|
|
| 2021 | - ActiveAfter src phase -> do
|
|
| 2020 | + return (ActivationAnn o' src c' t' v')
|
|
| 2021 | + ActiveAfter phase -> do
|
|
| 2022 | 2022 | o' <- markEpToken o -- '['
|
| 2023 | 2023 | v' <- mapM (\val -> printStringAtAA val (toSourceTextWithSuffix src (show phase) "")) v
|
| 2024 | 2024 | c' <- markEpToken c -- ']'
|
| 2025 | - return (ActivationAnn o' c' t v')
|
|
| 2025 | + return (ActivationAnn o' src c' t v')
|
|
| 2026 | 2026 | NeverActive -> do
|
| 2027 | 2027 | o' <- markEpToken o -- '['
|
| 2028 | 2028 | t' <- mapM markEpToken t -- ~
|
| 2029 | 2029 | c' <- markEpToken c -- ']'
|
| 2030 | - return (ActivationAnn o' c' t' v)
|
|
| 2031 | - _ -> return (ActivationAnn o c t v)
|
|
| 2030 | + return (ActivationAnn o' src c' t' v)
|
|
| 2031 | + |
|
| 2032 | + -- Other activations don't have corresponding source syntax
|
|
| 2033 | + _ -> return (ActivationAnn o src c t v)
|
|
| 2032 | 2034 | |
| 2033 | 2035 | -- ---------------------------------------------------------------------
|
| 2034 | 2036 |