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 |