Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC
Commits:
-
86d4cd86
by Simon Peyton Jones at 2025-12-31T10:22:11+00:00
8 changed files:
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Driver/DynFlags.hs
Changes:
| ... | ... | @@ -42,13 +42,32 @@ import Control.Monad ( zipWithM ) |
| 42 | 42 | %* *
|
| 43 | 43 | %************************************************************************
|
| 44 | 44 | |
| 45 | +Note [Coercion optimisation]
|
|
| 46 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 45 | 47 | This module does coercion optimisation. See the paper
|
| 46 | - |
|
| 47 | 48 | Evidence normalization in Systtem FV (RTA'13)
|
| 48 | 49 | https://simon.peytonjones.org/evidence-normalization/
|
| 49 | - |
|
| 50 | 50 | The paper is also in the GHC repo, in docs/opt-coercion.
|
| 51 | 51 | |
| 52 | +However, although powerful and occasionally very effective, coercion optimisation
|
|
| 53 | +can be very expensive (#26679). So we apply it sparingly:
|
|
| 54 | + |
|
| 55 | +* In the Simplifier, function `rebuild_go`, we use `isReflexiveCo` (which
|
|
| 56 | + computes the type of the coercion) to eliminate reflexive coercion, just
|
|
| 57 | + before we build a cast (e |> co).
|
|
| 58 | + |
|
| 59 | + (More precisely, we use `isReflexiveCoIgnoringMultiplicity.)
|
|
| 60 | + |
|
| 61 | +* We have a whole pass, `optCoProgram` that runs the coercion optimiser on all
|
|
| 62 | + the coercions in the program.
|
|
| 63 | + |
|
| 64 | + - We run it once in all optimisation levels
|
|
| 65 | + (see GHC.Driver.DynFlags.optLevelFlags)
|
|
| 66 | + |
|
| 67 | + - We run it early in the optimisation pipeline
|
|
| 68 | + (see GHC.Core.Opt.Pipeline.getCoreToDo).
|
|
| 69 | + |
|
| 70 | + |
|
| 52 | 71 | Note [Optimising coercion optimisation]
|
| 53 | 72 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 54 | 73 | Looking up a coercion's role or kind is linear in the size of the
|
| ... | ... | @@ -227,6 +227,7 @@ getCoreToDo dflags hpt_rule_base extra_vars |
| 227 | 227 | -- Optimise coercions
|
| 228 | 228 | -- With -O do this after one run of the Simplifier.
|
| 229 | 229 | -- Without -O, just take what the desugarer produced
|
| 230 | + -- See Note [Coercion optimisation] in GHC.Core.Coercion.Opt
|
|
| 230 | 231 | runWhen do_co_opt CoreOptCoercion,
|
| 231 | 232 | |
| 232 | 233 | if full_laziness then
|
| ... | ... | @@ -161,15 +161,16 @@ following table: |
| 161 | 161 | |
| 162 | 162 | Note [Inline depth]
|
| 163 | 163 | ~~~~~~~~~~~~~~~~~~~
|
| 164 | +The seInlineDepth tells us how deep in inlining we are.
|
|
| 165 | + |
|
| 164 | 166 | When we inline an /already-simplified/ unfolding, we
|
| 165 | 167 | * Zap the substitution environment; the inlined thing is an OutExpr
|
| 166 | 168 | * Bump the seInlineDepth in the SimplEnv
|
| 167 | 169 | Both these tasks are done in zapSubstEnv.
|
| 168 | 170 | |
| 169 | -The seInlineDepth tells us how deep in inlining we are. Currently,
|
|
| 170 | -seInlineDepth is used for just one purpose: when we encounter a
|
|
| 171 | -coercion we don't apply optCoercion to it if seInlineDepth>0.
|
|
| 172 | -Reason: it has already been optimised once, no point in doing so again.
|
|
| 171 | +Currently, `seInlineDepth` is entirely unused! (It was previously used to avoid
|
|
| 172 | +repeatedly optimising coercions.) But it's cheap to maintain and might prove
|
|
| 173 | +useful, so I have no removed it.
|
|
| 173 | 174 | -}
|
| 174 | 175 | |
| 175 | 176 | data SimplEnv
|
| ... | ... | @@ -27,7 +27,6 @@ import GHC.Core.Make ( FloatBind, mkImpossibleExpr, castBottomExpr ) |
| 27 | 27 | import qualified GHC.Core.Make
|
| 28 | 28 | import GHC.Core.Coercion hiding ( substCo, substCoVar )
|
| 29 | 29 | import GHC.Core.Reduction
|
| 30 | -import GHC.Core.Coercion.Opt ( optCoercion )
|
|
| 31 | 30 | import GHC.Core.FamInstEnv ( FamInstEnv, topNormaliseType_maybe )
|
| 32 | 31 | import GHC.Core.DataCon
|
| 33 | 32 | import GHC.Core.Opt.Stats ( Tick(..) )
|
| ... | ... | @@ -1358,16 +1357,8 @@ simplCoercionF env co cont |
| 1358 | 1357 | |
| 1359 | 1358 | simplCoercion :: SimplEnv -> InCoercion -> SimplM OutCoercion
|
| 1360 | 1359 | simplCoercion env co
|
| 1361 | - = do { let opt_co | reSimplifying env = substCo env co
|
|
| 1362 | - | otherwise = optCoercion opts subst co
|
|
| 1363 | - -- If (reSimplifying env) is True we have already simplified
|
|
| 1364 | - -- this coercion once, and we don't want do so again; doing
|
|
| 1365 | - -- so repeatedly risks non-linear behaviour
|
|
| 1366 | - -- See Note [Inline depth] in GHC.Core.Opt.Simplify.Env
|
|
| 1367 | - ; seqCo opt_co `seq` return opt_co }
|
|
| 1368 | - where
|
|
| 1369 | - subst = getTCvSubst env
|
|
| 1370 | - opts = seOptCoercionOpts env
|
|
| 1360 | + = do { let out_co = substCo env co
|
|
| 1361 | + ; seqCo out_co `seq` return out_co }
|
|
| 1371 | 1362 | |
| 1372 | 1363 | -----------------------------------
|
| 1373 | 1364 | -- | Push a TickIt context outwards past applications and cases, as
|
| ... | ... | @@ -1538,15 +1529,13 @@ rebuild_go env expr cont |
| 1538 | 1529 | case cont of
|
| 1539 | 1530 | Stop {} -> return (emptyFloats env, expr)
|
| 1540 | 1531 | TickIt t cont -> rebuild_go env (mkTick t expr) cont
|
| 1541 | - CastIt { sc_co = co, sc_opt = opt, sc_cont = cont }
|
|
| 1532 | + CastIt { sc_co = co, sc_cont = cont }
|
|
| 1542 | 1533 | | isReflexiveCoIgnoringMultiplicity co
|
| 1543 | 1534 | -- ignoring multiplicity: c.f. GHC.Core.Coercion.Opt.opt_univ
|
| 1544 | 1535 | -> rebuild_go env expr cont
|
| 1545 | 1536 | | otherwise
|
| 1546 | - -> rebuild_go env (mkCast expr co') cont
|
|
| 1537 | + -> rebuild_go env (mkCast expr co) cont
|
|
| 1547 | 1538 | -- NB: mkCast implements the (Coercion co |> g) optimisation
|
| 1548 | - where
|
|
| 1549 | - co' = optOutCoercion env co opt
|
|
| 1550 | 1539 | |
| 1551 | 1540 | Select { sc_bndr = bndr, sc_alts = alts, sc_env = se, sc_cont = cont }
|
| 1552 | 1541 | -> rebuildCase (se `setInScopeFromE` env) expr bndr alts cont
|
| ... | ... | @@ -1645,45 +1634,9 @@ isReflexiveCo |
| 1645 | 1634 | |
| 1646 | 1635 | In investigating this I saw missed opportunities for on-the-fly
|
| 1647 | 1636 | coercion shrinkage. See #15090.
|
| 1648 | - |
|
| 1649 | -Note [Avoid re-simplifying coercions]
|
|
| 1650 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1651 | -In some benchmarks (with deeply nested cases) we successively push
|
|
| 1652 | -casts onto the SimplCont. We don't want to call the coercion optimiser
|
|
| 1653 | -on each successive composition -- that's at least quadratic. So:
|
|
| 1654 | - |
|
| 1655 | -* The CastIt constructor in SimplCont has a `sc_opt :: Bool` flag to
|
|
| 1656 | - record whether the coercion optimiser has been applied to the coercion.
|
|
| 1657 | - |
|
| 1658 | -* In `simplCast`, when we see (Cast e co), we simplify `co` to get
|
|
| 1659 | - an OutCoercion, and built a CastIt with sc_opt=True.
|
|
| 1660 | - |
|
| 1661 | - Actually not quite: if we are simplifying the result of inlining an
|
|
| 1662 | - unfolding (seInlineDepth > 0), then instead of /optimising/ it again,
|
|
| 1663 | - just /substitute/ which is cheaper. See `simplCoercion`.
|
|
| 1664 | - |
|
| 1665 | -* In `addCoerce` (in `simplCast`) if we combine this new coercion with
|
|
| 1666 | - an existing once, we build a CastIt for (co1 ; co2) with sc_opt=False.
|
|
| 1667 | - |
|
| 1668 | -* When unpacking a CastIt, in `rebuildCall` and `rebuild`, we optimise
|
|
| 1669 | - the (presumably composed) coercion if sc_opt=False; this is done
|
|
| 1670 | - by `optOutCoercion`.
|
|
| 1671 | - |
|
| 1672 | -* When duplicating a continuation in `mkDupableContWithDmds`, before
|
|
| 1673 | - duplicating a CastIt, optimise the coercion. Otherwise we'll end up
|
|
| 1674 | - optimising it separately in the duplicate copies.
|
|
| 1675 | 1637 | -}
|
| 1676 | 1638 | |
| 1677 | 1639 | |
| 1678 | -optOutCoercion :: SimplEnvIS -> OutCoercion -> Bool -> OutCoercion
|
|
| 1679 | --- See Note [Avoid re-simplifying coercions]
|
|
| 1680 | -optOutCoercion env co already_optimised
|
|
| 1681 | - | already_optimised = co -- See Note [Avoid re-simplifying coercions]
|
|
| 1682 | - | otherwise = optCoercion opts empty_subst co
|
|
| 1683 | - where
|
|
| 1684 | - empty_subst = mkEmptySubst (seInScope env)
|
|
| 1685 | - opts = seOptCoercionOpts env
|
|
| 1686 | - |
|
| 1687 | 1640 | simplCast :: SimplEnv -> InExpr -> InCoercion -> SimplCont
|
| 1688 | 1641 | -> SimplM (SimplFloats, OutExpr)
|
| 1689 | 1642 | simplCast env body co0 cont0
|
| ... | ... | @@ -1691,27 +1644,25 @@ simplCast env body co0 cont0 |
| 1691 | 1644 | ; cont1 <- {-#SCC "simplCast-addCoerce" #-}
|
| 1692 | 1645 | if isReflCo co1
|
| 1693 | 1646 | then return cont0 -- See Note [Optimising reflexivity]
|
| 1694 | - else addCoerce co1 True cont0
|
|
| 1695 | - -- True <=> co1 is optimised
|
|
| 1647 | + else addCoerce co1 cont0
|
|
| 1696 | 1648 | ; {-#SCC "simplCast-simplExprF" #-} simplExprF env body cont1 }
|
| 1697 | 1649 | where
|
| 1698 | - |
|
| 1699 | 1650 | -- If the first parameter is MRefl, then simplifying revealed a
|
| 1700 | 1651 | -- reflexive coercion. Omit.
|
| 1701 | - addCoerceM :: MOutCoercion -> Bool -> SimplCont -> SimplM SimplCont
|
|
| 1702 | - addCoerceM MRefl _ cont = return cont
|
|
| 1703 | - addCoerceM (MCo co) opt cont = addCoerce co opt cont
|
|
| 1652 | + addCoerceM :: MOutCoercion -> SimplCont -> SimplM SimplCont
|
|
| 1653 | + addCoerceM MRefl cont = return cont
|
|
| 1654 | + addCoerceM (MCo co) cont = addCoerce co cont
|
|
| 1704 | 1655 | |
| 1705 | - addCoerce :: OutCoercion -> Bool -> SimplCont -> SimplM SimplCont
|
|
| 1706 | - addCoerce co1 _ (CastIt { sc_co = co2, sc_cont = cont }) -- See Note [Optimising reflexivity]
|
|
| 1707 | - = addCoerce (mkTransCo co1 co2) False cont
|
|
| 1656 | + addCoerce :: OutCoercion -> SimplCont -> SimplM SimplCont
|
|
| 1657 | + addCoerce co1 (CastIt { sc_co = co2, sc_cont = cont }) -- See Note [Optimising reflexivity]
|
|
| 1658 | + = addCoerce (mkTransCo co1 co2) cont
|
|
| 1708 | 1659 | -- False: (mkTransCo co1 co2) is not fully optimised
|
| 1709 | 1660 | -- See Note [Avoid re-simplifying coercions]
|
| 1710 | 1661 | |
| 1711 | - addCoerce co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
|
|
| 1662 | + addCoerce co (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
|
|
| 1712 | 1663 | | Just (arg_ty', m_co') <- pushCoTyArg co arg_ty
|
| 1713 | 1664 | = {-#SCC "addCoerce-pushCoTyArg" #-}
|
| 1714 | - do { tail' <- addCoerceM m_co' co_is_opt tail
|
|
| 1665 | + do { tail' <- addCoerceM m_co' tail
|
|
| 1715 | 1666 | ; return (ApplyToTy { sc_arg_ty = arg_ty'
|
| 1716 | 1667 | , sc_cont = tail'
|
| 1717 | 1668 | , sc_hole_ty = coercionLKind co }) }
|
| ... | ... | @@ -1721,15 +1672,12 @@ simplCast env body co0 cont0 |
| 1721 | 1672 | -- where co :: (s1->s2) ~ (t1->t2)
|
| 1722 | 1673 | -- co1 :: t1 ~ s1
|
| 1723 | 1674 | -- co2 :: s2 ~ t2
|
| 1724 | - addCoerce co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
|
|
| 1725 | - , sc_dup = dup, sc_cont = tail
|
|
| 1726 | - , sc_hole_ty = fun_ty })
|
|
| 1727 | - | not co_is_opt -- pushCoValArg duplicates the coercion, so optimise first
|
|
| 1728 | - = addCoerce (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
|
|
| 1729 | - |
|
| 1675 | + addCoerce co cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
|
|
| 1676 | + , sc_dup = dup, sc_cont = tail
|
|
| 1677 | + , sc_hole_ty = fun_ty })
|
|
| 1730 | 1678 | | Just (m_co1, m_co2) <- pushCoValArg co
|
| 1731 | 1679 | = {-#SCC "addCoerce-pushCoValArg" #-}
|
| 1732 | - do { tail' <- addCoerceM m_co2 co_is_opt tail
|
|
| 1680 | + do { tail' <- addCoerceM m_co2 tail
|
|
| 1733 | 1681 | ; case m_co1 of {
|
| 1734 | 1682 | MRefl -> return (cont { sc_cont = tail'
|
| 1735 | 1683 | , sc_hole_ty = coercionLKind co }) ;
|
| ... | ... | @@ -1748,11 +1696,11 @@ simplCast env body co0 cont0 |
| 1748 | 1696 | , sc_cont = tail'
|
| 1749 | 1697 | , sc_hole_ty = coercionLKind co }) } } }
|
| 1750 | 1698 | |
| 1751 | - addCoerce co co_is_opt cont
|
|
| 1699 | + addCoerce co cont
|
|
| 1752 | 1700 | | isReflCo co = return cont -- Having this at the end makes a huge
|
| 1753 | 1701 | -- difference in T12227, for some reason
|
| 1754 | 1702 | -- See Note [Optimising reflexivity]
|
| 1755 | - | otherwise = return (CastIt { sc_co = co, sc_opt = co_is_opt, sc_cont = cont })
|
|
| 1703 | + | otherwise = return (CastIt { sc_co = co, sc_cont = cont })
|
|
| 1756 | 1704 | |
| 1757 | 1705 | simplLazyArg :: SimplEnvIS -- ^ Used only for its InScopeSet
|
| 1758 | 1706 | -> DupFlag
|
| ... | ... | @@ -3877,11 +3825,9 @@ mkDupableContWithDmds env _ cont |
| 3877 | 3825 | |
| 3878 | 3826 | mkDupableContWithDmds _ _ (Stop {}) = panic "mkDupableCont" -- Handled by previous eqn
|
| 3879 | 3827 | |
| 3880 | -mkDupableContWithDmds env dmds (CastIt { sc_co = co, sc_opt = opt, sc_cont = cont })
|
|
| 3828 | +mkDupableContWithDmds env dmds (CastIt { sc_co = co, sc_cont = cont })
|
|
| 3881 | 3829 | = do { (floats, cont') <- mkDupableContWithDmds env dmds cont
|
| 3882 | - ; return (floats, CastIt { sc_co = optOutCoercion env co opt
|
|
| 3883 | - , sc_opt = True, sc_cont = cont' }) }
|
|
| 3884 | - -- optOutCoercion: see Note [Avoid re-simplifying coercions]
|
|
| 3830 | + ; return (floats, CastIt { sc_co = co, sc_cont = cont' }) }
|
|
| 3885 | 3831 | |
| 3886 | 3832 | -- Duplicating ticks for now, not sure if this is good or not
|
| 3887 | 3833 | mkDupableContWithDmds env dmds (TickIt t cont)
|
| ... | ... | @@ -164,9 +164,6 @@ data SimplCont |
| 164 | 164 | | CastIt -- (CastIt co K)[e] = K[ e `cast` co ]
|
| 165 | 165 | { sc_co :: OutCoercion -- The coercion simplified
|
| 166 | 166 | -- Invariant: never an identity coercion
|
| 167 | - , sc_opt :: Bool -- True <=> sc_co has had optCoercion applied to it
|
|
| 168 | - -- See Note [Avoid re-simplifying coercions]
|
|
| 169 | - -- in GHC.Core.Opt.Simplify.Iteration
|
|
| 170 | 167 | , sc_cont :: SimplCont }
|
| 171 | 168 | |
| 172 | 169 | | ApplyToVal -- (ApplyToVal arg K)[e] = K[ e arg ]
|
| ... | ... | @@ -30,7 +30,6 @@ import GHC.Core.Unfold.Make |
| 30 | 30 | import GHC.Core.Make ( FloatBind(..), mkWildValBinder )
|
| 31 | 31 | import GHC.Core.Opt.OccurAnal( occurAnalyseExpr, occurAnalysePgm, zapLambdaBndrs )
|
| 32 | 32 | import GHC.Core.DataCon
|
| 33 | -import GHC.Core.Coercion.Opt ( optCoercion, OptCoercionOpts (..) )
|
|
| 34 | 33 | import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
|
| 35 | 34 | , isInScope, substTyVarBndr, cloneTyVarBndr )
|
| 36 | 35 | import GHC.Core.Predicate( isCoVarType )
|
| ... | ... | @@ -113,7 +112,6 @@ See ticket #25790 |
| 113 | 112 | -- | Simple optimiser options
|
| 114 | 113 | data SimpleOpts = SimpleOpts
|
| 115 | 114 | { so_uf_opts :: !UnfoldingOpts -- ^ Unfolding options
|
| 116 | - , so_co_opts :: !OptCoercionOpts -- ^ Coercion optimiser options
|
|
| 117 | 115 | , so_eta_red :: !Bool -- ^ Eta reduction on?
|
| 118 | 116 | , so_inline :: !Bool -- ^ False <=> do no inlining whatsoever,
|
| 119 | 117 | -- even for trivial or used-once things
|
| ... | ... | @@ -123,7 +121,6 @@ data SimpleOpts = SimpleOpts |
| 123 | 121 | defaultSimpleOpts :: SimpleOpts
|
| 124 | 122 | defaultSimpleOpts = SimpleOpts
|
| 125 | 123 | { so_uf_opts = defaultUnfoldingOpts
|
| 126 | - , so_co_opts = OptCoercionOpts { optCoercionEnabled = False }
|
|
| 127 | 124 | , so_eta_red = False
|
| 128 | 125 | , so_inline = True
|
| 129 | 126 | }
|
| ... | ... | @@ -288,7 +285,7 @@ simple_opt_expr env expr = go expr |
| 288 | 285 | go e@(Lam {}) = simple_app env e []
|
| 289 | 286 | |
| 290 | 287 | go (Type ty) = Type (substTyUnchecked subst ty)
|
| 291 | - go (Coercion co) = Coercion (go_co co)
|
|
| 288 | + go (Coercion co) = Coercion (simple_opt_co env co)
|
|
| 292 | 289 | go (Lit lit) = Lit lit
|
| 293 | 290 | go (Tick tickish e) = mkTick (substTickish subst tickish) (go e)
|
| 294 | 291 | go (Let bind body) = case simple_opt_bind env bind NotTopLevel of
|
| ... | ... | @@ -323,15 +320,15 @@ simple_opt_expr env expr = go expr |
| 323 | 320 | e' = go e
|
| 324 | 321 | (env', b') = subst_opt_bndr env b
|
| 325 | 322 | |
| 326 | - ----------------------
|
|
| 327 | - go_co co = optCoercion (so_co_opts (soe_opts env)) subst co
|
|
| 328 | - |
|
| 329 | 323 | ----------------------
|
| 330 | 324 | go_alt env (Alt con bndrs rhs)
|
| 331 | 325 | = Alt con bndrs' (simple_opt_expr env' rhs)
|
| 332 | 326 | where
|
| 333 | 327 | (env', bndrs') = subst_opt_bndrs env bndrs
|
| 334 | 328 | |
| 329 | +simple_opt_co :: SimpleOptEnv -> InCoercion -> OutCoercion
|
|
| 330 | +simple_opt_co env co = substCo (soe_subst env) co
|
|
| 331 | + |
|
| 335 | 332 | mk_cast :: CoreExpr -> CoercionR -> CoreExpr
|
| 336 | 333 | -- Like GHC.Core.Utils.mkCast, but does a full reflexivity check.
|
| 337 | 334 | -- mkCast doesn't do that because the Simplifier does (in simplCast)
|
| ... | ... | @@ -471,7 +468,7 @@ add_cast env co1 as |
| 471 | 468 | CastIt co2:rest -> CastIt (co1' `mkTransCo` co2):rest
|
| 472 | 469 | _ -> CastIt co1':as
|
| 473 | 470 | where
|
| 474 | - co1' = optCoercion (so_co_opts (soe_opts env)) (soe_subst env) co1
|
|
| 471 | + co1' = simple_opt_co env co1
|
|
| 475 | 472 | |
| 476 | 473 | rebuild_app :: HasDebugCallStack
|
| 477 | 474 | => SimpleOptEnv -> OutExpr -> [SimpleContItem] -> OutExpr
|
| ... | ... | @@ -606,7 +603,7 @@ simple_bind_pair env@(SOE { soe_inl = inl_env, soe_subst = subst, soe_opts = opt |
| 606 | 603 | (env { soe_subst = extendTvSubst subst in_bndr out_ty }, Nothing)
|
| 607 | 604 | |
| 608 | 605 | | Coercion co <- in_rhs
|
| 609 | - , let out_co = optCoercion (so_co_opts (soe_opts env)) (soe_subst rhs_env) co
|
|
| 606 | + , let out_co = simple_opt_co rhs_env co
|
|
| 610 | 607 | = assert (isCoVar in_bndr)
|
| 611 | 608 | (env { soe_subst = extendCvSubst subst in_bndr out_co }, Nothing)
|
| 612 | 609 |
| ... | ... | @@ -24,7 +24,6 @@ initOptCoercionOpts dflags = OptCoercionOpts |
| 24 | 24 | initSimpleOpts :: DynFlags -> SimpleOpts
|
| 25 | 25 | initSimpleOpts dflags = SimpleOpts
|
| 26 | 26 | { so_uf_opts = unfoldingOpts dflags
|
| 27 | - , so_co_opts = initOptCoercionOpts dflags
|
|
| 28 | 27 | , so_eta_red = gopt Opt_DoEtaReduction dflags
|
| 29 | 28 | , so_inline = True
|
| 30 | 29 | }
|
| ... | ... | @@ -1236,7 +1236,7 @@ optLevelFlags -- see Note [Documenting optimisation flags] |
| 1236 | 1236 | , ([1,2], Opt_DoCleverArgEtaExpansion) -- See Note [Eta expansion of arguments in CorePrep]
|
| 1237 | 1237 | , ([0,1,2], Opt_DoEtaReduction) -- See Note [Eta-reduction in -O0]
|
| 1238 | 1238 | , ([0,1,2], Opt_ProfManualCcs )
|
| 1239 | - , ([0,1,2], Opt_OptCoercion )
|
|
| 1239 | + , ([0,1,2], Opt_OptCoercion ) -- See Note [Coercion optimisation] in GHC.Core.Coercion.Opt
|
|
| 1240 | 1240 | , ([2], Opt_DictsStrict)
|
| 1241 | 1241 | |
| 1242 | 1242 | , ([0], Opt_IgnoreInterfacePragmas)
|