Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC
Commits:
-
c1cde247
by Simon Peyton Jones at 2025-12-16T16:38:48+00:00
10 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
Changes:
| ... | ... | @@ -69,7 +69,8 @@ module GHC.Core.Coercion ( |
| 69 | 69 | |
| 70 | 70 | isReflKindCo,isReflKindMCo,
|
| 71 | 71 | isReflCo, isReflCo_maybe,
|
| 72 | - isReflexiveMCo, isReflexiveCo, isReflexiveCo_maybe,
|
|
| 72 | + isReflexiveMCo, isReflexiveCo,
|
|
| 73 | + isReflexiveCoIgnoringMultiplicity,
|
|
| 73 | 74 | isReflCoVar_maybe, mkGReflLeftMCo, mkGReflRightMCo,
|
| 74 | 75 | mkCoherenceRightMCo,
|
| 75 | 76 | |
| ... | ... | @@ -665,7 +666,9 @@ isReflCoVar_maybe cv |
| 665 | 666 | -- See Note [KindCoercion] in GHC.Core.TyCo.Rep
|
| 666 | 667 | isKindCo :: Coercion -> Bool
|
| 667 | 668 | isKindCo co
|
| 668 | - = role == Nominal && isLiftedTypeKind kk1 && isLiftedTypeKind kk2
|
|
| 669 | + = role == Nominal
|
|
| 670 | + && definitelyLiftedType kk1
|
|
| 671 | + && definitelyLiftedType kk2
|
|
| 669 | 672 | where
|
| 670 | 673 | (Pair kk1 kk2, role) = coercionKindRole co
|
| 671 | 674 | |
| ... | ... | @@ -679,8 +682,14 @@ isKindCo co |
| 679 | 682 | -- so we return True
|
| 680 | 683 | -- See Note [KindCoercion] in GHC.Core.TyCo.Rep
|
| 681 | 684 | isReflKindCo :: HasDebugCallStack => KindCoercion -> Bool
|
| 682 | -isReflKindCo co@(GRefl {}) = assertPpr (isKindCo co) (ppr co) $
|
|
| 685 | +isReflKindCo co@(GRefl {}) = assertPpr (isKindCo co) (ppr co $$ ppr kk1 $$ ppr kk2
|
|
| 686 | + $$ ppr (isLiftedTypeKind kk1)
|
|
| 687 | + $$ ppr (isLiftedTypeKind kk2)
|
|
| 688 | + $$ ppr (role == Nominal)
|
|
| 689 | + $$ ppr (isKindCo co))
|
|
| 683 | 690 | True
|
| 691 | + where
|
|
| 692 | + (Pair kk1 kk2, role) = coercionKindRole co
|
|
| 684 | 693 | isReflKindCo (Refl{}) = True -- Refl ty == GRefl N ty MRefl
|
| 685 | 694 | isReflKindCo _ = False
|
| 686 | 695 | |
| ... | ... | @@ -700,7 +709,7 @@ isReflCo _ = False |
| 700 | 709 | |
| 701 | 710 | -- | Returns the type coerced if this coercion is reflexive. Guaranteed
|
| 702 | 711 | -- to work very quickly. Sometimes a coercion can be reflexive, but not
|
| 703 | --- obviously so. c.f. 'isReflexiveCo_maybe'
|
|
| 712 | +-- obviously so.
|
|
| 704 | 713 | isReflCo_maybe :: Coercion -> Maybe (Type, Role)
|
| 705 | 714 | isReflCo_maybe (Refl ty) = Just (ty, Nominal)
|
| 706 | 715 | isReflCo_maybe (GRefl r ty mco) | isReflKindMCo mco = Just (ty, r)
|
| ... | ... | @@ -709,27 +718,26 @@ isReflCo_maybe _ = Nothing |
| 709 | 718 | -- | Slowly checks if the coercion is reflexive. Don't call this in a loop,
|
| 710 | 719 | -- as it walks over the entire coercion.
|
| 711 | 720 | isReflexiveCo :: Coercion -> Bool
|
| 712 | -isReflexiveCo (Refl {}) = True
|
|
| 713 | -isReflexiveCo (GRefl _ _ mco) = isReflKindMCo mco
|
|
| 714 | -isReflexiveCo (SymCo co) = isReflexiveCo co
|
|
| 715 | -isReflexiveCo co = coercionLKind co `eqType` coercionRKind co
|
|
| 721 | +isReflexiveCo co
|
|
| 722 | + = case co of
|
|
| 723 | + Refl {} -> True
|
|
| 724 | + GRefl _ _ mco -> isReflKindMCo mco
|
|
| 725 | + SymCo co -> isReflexiveCo co
|
|
| 726 | + _ -> coercionLKind co `eqType` coercionRKind co
|
|
| 727 | + |
|
| 728 | +-- | Just like isReflexiveCo but ignores multiplicity
|
|
| 729 | +isReflexiveCoIgnoringMultiplicity :: Coercion -> Bool
|
|
| 730 | +isReflexiveCoIgnoringMultiplicity co
|
|
| 731 | + = case co of
|
|
| 732 | + Refl {} -> True
|
|
| 733 | + GRefl _ _ mco -> isReflKindMCo mco
|
|
| 734 | + SymCo co -> isReflexiveCoIgnoringMultiplicity co
|
|
| 735 | + _ -> coercionLKind co `eqTypeIgnoringMultiplicity` coercionRKind co
|
|
| 716 | 736 | |
| 717 | 737 | isReflexiveMCo :: MCoercion -> Bool
|
| 718 | 738 | isReflexiveMCo MRefl = True
|
| 719 | 739 | isReflexiveMCo (MCo co) = isReflexiveCo co
|
| 720 | 740 | |
| 721 | --- | Extracts the coerced type from a reflexive coercion. This potentially
|
|
| 722 | --- walks over the entire coercion, so avoid doing this in a loop.
|
|
| 723 | -isReflexiveCo_maybe :: Coercion -> Maybe (Type, Role)
|
|
| 724 | -isReflexiveCo_maybe (Refl ty) = Just (ty, Nominal)
|
|
| 725 | -isReflexiveCo_maybe (GRefl r ty mco) | isReflKindMCo mco = Just (ty, r)
|
|
| 726 | -isReflexiveCo_maybe co
|
|
| 727 | - | ty1 `eqType` ty2
|
|
| 728 | - = Just (ty1, r)
|
|
| 729 | - | otherwise
|
|
| 730 | - = Nothing
|
|
| 731 | - where (Pair ty1 ty2, r) = coercionKindRole co
|
|
| 732 | - |
|
| 733 | 741 | forAllCoKindCo :: TyCoVar -> KindMCoercion -> KindCoercion
|
| 734 | 742 | -- Get the kind coercion from a ForAllCo
|
| 735 | 743 | forAllCoKindCo _ (MCo co) = co
|
| 1 | 1 | -- (c) The University of Glasgow 2006
|
| 2 | - |
|
| 3 | 2 | {-# LANGUAGE CPP #-}
|
| 4 | 3 | |
| 5 | 4 | module GHC.Core.Coercion.Opt
|
| 6 | - ( optCoercion
|
|
| 5 | + ( optCoProgram, optCoercion
|
|
| 7 | 6 | , OptCoercionOpts (..)
|
| 8 | 7 | )
|
| 9 | 8 | where
|
| ... | ... | @@ -12,6 +11,7 @@ import GHC.Prelude |
| 12 | 11 | |
| 13 | 12 | import GHC.Tc.Utils.TcType ( exactTyCoVarsOfType )
|
| 14 | 13 | |
| 14 | +import GHC.Core
|
|
| 15 | 15 | import GHC.Core.TyCo.Rep
|
| 16 | 16 | import GHC.Core.TyCo.Subst
|
| 17 | 17 | import GHC.Core.TyCo.Compare( eqForAllVis, eqTypeIgnoringMultiplicity )
|
| ... | ... | @@ -164,6 +164,54 @@ We use the following invariants: |
| 164 | 164 | to the little bits being substituted.
|
| 165 | 165 | -}
|
| 166 | 166 | |
| 167 | +{- **********************************************************************
|
|
| 168 | +%* *
|
|
| 169 | + optCoercionPgm
|
|
| 170 | +%* *
|
|
| 171 | +%********************************************************************* -}
|
|
| 172 | + |
|
| 173 | +optCoProgram :: CoreProgram -> CoreProgram
|
|
| 174 | +optCoProgram binds
|
|
| 175 | + = map go binds
|
|
| 176 | + where
|
|
| 177 | + go (NonRec b r) = NonRec b (optCoExpr in_scope r)
|
|
| 178 | + go (Rec prs) = Rec (mapSnd (optCoExpr in_scope) prs)
|
|
| 179 | + in_scope = mkInScopeSetList (bindersOfBinds binds)
|
|
| 180 | + -- Put all top-level binders into scope; it is possible to have
|
|
| 181 | + -- forward references. See Note [Glomming] in GHC.Core.Opt.OccurAnal
|
|
| 182 | + |
|
| 183 | +optCoExpr :: InScopeSet -> CoreExpr -> CoreExpr
|
|
| 184 | +optCoExpr _ e@(Var {}) = e
|
|
| 185 | +optCoExpr _ e@(Lit {}) = e
|
|
| 186 | +optCoExpr _ e@(Type {}) = e
|
|
| 187 | +optCoExpr is (App e1 e2) = App (optCoExpr is e1) (optCoExpr is e2)
|
|
| 188 | +optCoExpr is (Lam b e) = Lam b (optCoExpr (is `extendInScopeSet` b) e)
|
|
| 189 | +optCoExpr is (Coercion co) = Coercion (optCo is co)
|
|
| 190 | +optCoExpr is (Cast e co) = Cast (optCoExpr is e) (optCo is co)
|
|
| 191 | +optCoExpr is (Tick t e) = Tick t (optCoExpr is e)
|
|
| 192 | +optCoExpr is (Let (NonRec b r) e) = Let (NonRec b (optCoExpr is r))
|
|
| 193 | + (optCoExpr (is `extendInScopeSet` b) e)
|
|
| 194 | +optCoExpr is (Let (Rec prs) e) = Let (Rec (mapSnd (optCoExpr is') prs))
|
|
| 195 | + (optCoExpr is' e)
|
|
| 196 | + where
|
|
| 197 | + is' = is `extendInScopeSetList` map fst prs
|
|
| 198 | +optCoExpr is (Case e b ty alts) = Case (optCoExpr is e) b ty
|
|
| 199 | + (map (optCoAlt (is `extendInScopeSet` b)) alts)
|
|
| 200 | + |
|
| 201 | +optCo :: InScopeSet -> Coercion -> Coercion
|
|
| 202 | +optCo is co = optCoercion' (mkEmptySubst is) co
|
|
| 203 | + |
|
| 204 | +optCoAlt :: InScopeSet -> CoreAlt -> CoreAlt
|
|
| 205 | +optCoAlt is (Alt k bs e)
|
|
| 206 | + = Alt k bs (optCoExpr (is `extendInScopeSetList` bs) e)
|
|
| 207 | + |
|
| 208 | + |
|
| 209 | +{- **********************************************************************
|
|
| 210 | +%* *
|
|
| 211 | + optCoercion
|
|
| 212 | +%* *
|
|
| 213 | +%********************************************************************* -}
|
|
| 214 | + |
|
| 167 | 215 | -- | Coercion optimisation options
|
| 168 | 216 | newtype OptCoercionOpts = OptCoercionOpts
|
| 169 | 217 | { optCoercionEnabled :: Bool -- ^ Enable coercion optimisation (reduce its size)
|
| ... | ... | @@ -624,7 +672,7 @@ opt_univ env sym prov deps role ty1 ty2 |
| 624 | 672 | in
|
| 625 | 673 | -- We only Lint multiplicities in the output of the typechecker, as
|
| 626 | 674 | -- described in Note [Linting linearity] in GHC.Core.Lint. This means
|
| 627 | - -- we can use 'eqTypeIgnoringMultiplicity' instea of 'eqType' below.
|
|
| 675 | + -- we can use 'eqTypeIgnoringMultiplicity' instead of 'eqType' below.
|
|
| 628 | 676 | --
|
| 629 | 677 | -- In particular, this gets rid of 'SubMultProv' coercions that were
|
| 630 | 678 | -- introduced for typechecking multiplicities of data constructors, as
|
| ... | ... | @@ -24,6 +24,7 @@ import GHC.Platform.Ways ( hasWay, Way(WayProf) ) |
| 24 | 24 | import GHC.Core
|
| 25 | 25 | import GHC.Core.SimpleOpt (simpleOptPgm)
|
| 26 | 26 | import GHC.Core.Opt.CSE ( cseProgram )
|
| 27 | +import GHC.Core.Coercion.Opt ( optCoProgram )
|
|
| 27 | 28 | import GHC.Core.Rules ( RuleBase, ruleCheckProgram, getRules )
|
| 28 | 29 | import GHC.Core.Ppr ( pprCoreBindings, pprRules )
|
| 29 | 30 | import GHC.Core.Utils ( dumpIdInfoOfProgram )
|
| ... | ... | @@ -134,6 +135,7 @@ getCoreToDo dflags hpt_rule_base extra_vars |
| 134 | 135 | strictness = gopt Opt_Strictness dflags
|
| 135 | 136 | full_laziness = gopt Opt_FullLaziness dflags
|
| 136 | 137 | do_specialise = gopt Opt_Specialise dflags
|
| 138 | + do_co_opt = gopt Opt_OptCoercion dflags
|
|
| 137 | 139 | do_float_in = gopt Opt_FloatIn dflags
|
| 138 | 140 | cse = gopt Opt_CSE dflags
|
| 139 | 141 | spec_constr = gopt Opt_SpecConstr dflags
|
| ... | ... | @@ -146,7 +148,6 @@ getCoreToDo dflags hpt_rule_base extra_vars |
| 146 | 148 | static_ptrs = xopt LangExt.StaticPointers dflags
|
| 147 | 149 | profiling = ways dflags `hasWay` WayProf
|
| 148 | 150 | |
| 149 | - do_presimplify = do_specialise -- TODO: any other optimizations benefit from pre-simplification?
|
|
| 150 | 151 | do_simpl3 = const_fold || rules_on -- TODO: any other optimizations benefit from three-phase simplification?
|
| 151 | 152 | |
| 152 | 153 | maybe_rule_check phase = runMaybe rule_check (CoreDoRuleCheck phase)
|
| ... | ... | @@ -215,12 +216,14 @@ getCoreToDo dflags hpt_rule_base extra_vars |
| 215 | 216 | -- after this before anything else
|
| 216 | 217 | runWhen static_args (CoreDoPasses [ simpl_gently, CoreDoStaticArgs ]),
|
| 217 | 218 | |
| 218 | - -- initial simplify: mk specialiser happy: minimum effort please
|
|
| 219 | - runWhen do_presimplify simpl_gently,
|
|
| 220 | - |
|
| 219 | + -- Initial simplify: make specialiser happy and/or optimise coercions:
|
|
| 220 | + -- minimum effort please
|
|
| 221 | 221 | -- Specialisation is best done before full laziness
|
| 222 | 222 | -- so that overloaded functions have all their dictionary lambdas manifest
|
| 223 | - runWhen do_specialise CoreDoSpecialising,
|
|
| 223 | + runWhen (do_specialise || do_co_opt) $
|
|
| 224 | + CoreDoPasses [ simpl_gently
|
|
| 225 | + , runWhen do_co_opt CoreOptCoercion
|
|
| 226 | + , runWhen do_specialise CoreDoSpecialising ],
|
|
| 224 | 227 | |
| 225 | 228 | if full_laziness then
|
| 226 | 229 | CoreDoFloatOutwards $ FloatOutSwitches
|
| ... | ... | @@ -496,6 +499,9 @@ doCorePass pass guts = do |
| 496 | 499 | CoreCSE -> {-# SCC "CommonSubExpr" #-}
|
| 497 | 500 | updateBinds cseProgram
|
| 498 | 501 | |
| 502 | + CoreOptCoercion -> {-# SCC "OptCoercion" #-}
|
|
| 503 | + updateBinds optCoProgram
|
|
| 504 | + |
|
| 499 | 505 | CoreLiberateCase -> {-# SCC "LiberateCase" #-}
|
| 500 | 506 | updateBinds (liberateCase (initLiberateCaseOpts dflags))
|
| 501 | 507 |
| ... | ... | @@ -52,6 +52,7 @@ data CoreToDo -- These are diff core-to-core passes, |
| 52 | 52 | | CoreDoSpecialising
|
| 53 | 53 | | CoreDoSpecConstr
|
| 54 | 54 | | CoreCSE
|
| 55 | + | CoreOptCoercion -- Run the coercion optimiser
|
|
| 55 | 56 | | CoreDoRuleCheck CompilerPhase String -- Check for non-application of rules
|
| 56 | 57 | -- matching this string
|
| 57 | 58 | | CoreDoNothing -- Useful when building up
|
| ... | ... | @@ -81,6 +82,7 @@ instance Outputable CoreToDo where |
| 81 | 82 | ppr CoreDoSpecialising = text "Specialise"
|
| 82 | 83 | ppr CoreDoSpecConstr = text "SpecConstr"
|
| 83 | 84 | ppr CoreCSE = text "Common sub-expression"
|
| 85 | + ppr CoreOptCoercion = text "Optimise coercions"
|
|
| 84 | 86 | ppr CoreDesugar = text "Desugar (before optimization)"
|
| 85 | 87 | ppr CoreDesugarOpt = text "Desugar (after optimization)"
|
| 86 | 88 | ppr CoreTidy = text "Tidy Core"
|
| ... | ... | @@ -1531,8 +1531,11 @@ rebuild_go env expr cont |
| 1531 | 1531 | Stop {} -> return (emptyFloats env, expr)
|
| 1532 | 1532 | TickIt t cont -> rebuild_go env (mkTick t expr) cont
|
| 1533 | 1533 | CastIt { sc_co = co, sc_opt = opt, sc_cont = cont }
|
| 1534 | - | isReflexiveCo co -> rebuild_go env expr cont
|
|
| 1535 | - | otherwise -> rebuild_go env (mkCast expr co') cont
|
|
| 1534 | + | isReflexiveCoIgnoringMultiplicity co
|
|
| 1535 | + -- ignoring multiplicity: c.f. GHC.Core.Coercion.Opt.opt_univ
|
|
| 1536 | + -> rebuild_go env expr cont
|
|
| 1537 | + | otherwise
|
|
| 1538 | + -> rebuild_go env (mkCast expr co') cont
|
|
| 1536 | 1539 | -- NB: mkCast implements the (Coercion co |> g) optimisation
|
| 1537 | 1540 | where
|
| 1538 | 1541 | co' = optOutCoercion env co opt
|
| ... | ... | @@ -17,7 +17,7 @@ import GHCi.Message (EvalOpts(..)) |
| 17 | 17 | -- | Initialise coercion optimiser configuration from DynFlags
|
| 18 | 18 | initOptCoercionOpts :: DynFlags -> OptCoercionOpts
|
| 19 | 19 | initOptCoercionOpts dflags = OptCoercionOpts
|
| 20 | - { optCoercionEnabled = not (hasNoOptCoercion dflags)
|
|
| 20 | + { optCoercionEnabled = gopt Opt_OptCoercion dflags
|
|
| 21 | 21 | }
|
| 22 | 22 | |
| 23 | 23 | -- | Initialise Simple optimiser configuration from DynFlags
|
| ... | ... | @@ -77,6 +77,7 @@ initEndPassConfig dflags extra_vars name_ppr_ctx pass = EndPassConfig |
| 77 | 77 | coreDumpFlag :: CoreToDo -> Maybe DumpFlag
|
| 78 | 78 | coreDumpFlag (CoreDoSimplify {}) = Just Opt_D_verbose_core2core
|
| 79 | 79 | coreDumpFlag (CoreDoPluginPass {}) = Just Opt_D_verbose_core2core
|
| 80 | +coreDumpFlag (CoreOptCoercion {}) = Just Opt_D_verbose_core2core
|
|
| 80 | 81 | coreDumpFlag CoreDoFloatInwards = Just Opt_D_dump_float_in
|
| 81 | 82 | coreDumpFlag (CoreDoFloatOutwards {}) = Just Opt_D_dump_float_out
|
| 82 | 83 | coreDumpFlag CoreLiberateCase = Just Opt_D_dump_liberate_case
|
| ... | ... | @@ -996,7 +996,7 @@ hasNoStateHack :: DynFlags -> Bool |
| 996 | 996 | hasNoStateHack = gopt Opt_G_NoStateHack
|
| 997 | 997 | |
| 998 | 998 | hasNoOptCoercion :: DynFlags -> Bool
|
| 999 | -hasNoOptCoercion = gopt Opt_G_NoOptCoercion
|
|
| 999 | +hasNoOptCoercion flags = not (gopt Opt_OptCoercion flags)
|
|
| 1000 | 1000 | |
| 1001 | 1001 | -- | Test whether a 'DumpFlag' is set
|
| 1002 | 1002 | dopt :: DumpFlag -> DynFlags -> Bool
|
| ... | ... | @@ -1237,6 +1237,7 @@ optLevelFlags -- see Note [Documenting optimisation flags] |
| 1237 | 1237 | , ([1,2], Opt_DoCleverArgEtaExpansion) -- See Note [Eta expansion of arguments in CorePrep]
|
| 1238 | 1238 | , ([0,1,2], Opt_DoEtaReduction) -- See Note [Eta-reduction in -O0]
|
| 1239 | 1239 | , ([0,1,2], Opt_ProfManualCcs )
|
| 1240 | + , ([0,1,2], Opt_OptCoercion )
|
|
| 1240 | 1241 | , ([2], Opt_DictsStrict)
|
| 1241 | 1242 | |
| 1242 | 1243 | , ([0], Opt_IgnoreInterfacePragmas)
|
| ... | ... | @@ -641,6 +641,7 @@ data GeneralFlag |
| 641 | 641 | | Opt_InlineGenerics
|
| 642 | 642 | | Opt_InlineGenericsAggressively
|
| 643 | 643 | | Opt_StaticArgumentTransformation
|
| 644 | + | Opt_OptCoercion
|
|
| 644 | 645 | | Opt_CSE
|
| 645 | 646 | | Opt_StgCSE
|
| 646 | 647 | | Opt_StgLiftLams
|
| ... | ... | @@ -887,7 +888,6 @@ data GeneralFlag |
| 887 | 888 | | Opt_PluginTrustworthy
|
| 888 | 889 | |
| 889 | 890 | | Opt_G_NoStateHack
|
| 890 | - | Opt_G_NoOptCoercion
|
|
| 891 | 891 | deriving (Eq, Show, Enum)
|
| 892 | 892 | |
| 893 | 893 | -- | The set of flags which affect optimisation for the purposes of
|
| ... | ... | @@ -910,6 +910,7 @@ optimisationFlags = EnumSet.fromList |
| 910 | 910 | , Opt_CrossModuleSpecialise
|
| 911 | 911 | , Opt_StaticArgumentTransformation
|
| 912 | 912 | , Opt_PolymorphicSpecialisation
|
| 913 | + , Opt_OptCoercion
|
|
| 913 | 914 | , Opt_CSE
|
| 914 | 915 | , Opt_StgCSE
|
| 915 | 916 | , Opt_StgLiftLams
|
| ... | ... | @@ -1328,8 +1328,6 @@ dynamic_flags_deps = [ |
| 1328 | 1328 | (NoArg (setGeneralFlag Opt_NoHsMain))
|
| 1329 | 1329 | , make_ord_flag defGhcFlag "fno-state-hack"
|
| 1330 | 1330 | (NoArg (setGeneralFlag Opt_G_NoStateHack))
|
| 1331 | - , make_ord_flag defGhcFlag "fno-opt-coercion"
|
|
| 1332 | - (NoArg (setGeneralFlag Opt_G_NoOptCoercion))
|
|
| 1333 | 1331 | , make_ord_flag defGhcFlag "with-rtsopts"
|
| 1334 | 1332 | (HasArg setRtsOpts)
|
| 1335 | 1333 | , make_ord_flag defGhcFlag "rtsopts"
|
| ... | ... | @@ -2477,6 +2475,7 @@ fFlagsDeps = [ |
| 2477 | 2475 | flagSpec "cmm-elim-common-blocks" Opt_CmmElimCommonBlocks,
|
| 2478 | 2476 | flagSpec "cmm-sink" Opt_CmmSink,
|
| 2479 | 2477 | flagSpec "cmm-static-pred" Opt_CmmStaticPred,
|
| 2478 | + flagSpec "opt-coercion" Opt_OptCoercion,
|
|
| 2480 | 2479 | flagSpec "cse" Opt_CSE,
|
| 2481 | 2480 | flagSpec "stg-cse" Opt_StgCSE,
|
| 2482 | 2481 | flagSpec "stg-lift-lams" Opt_StgLiftLams,
|