Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC
Commits:
-
88d60e1d
by Simon Peyton Jones at 2026-01-15T12:56:19+00:00
-
8624f459
by Simon Peyton Jones at 2026-01-15T12:56:36+00:00
-
6e78fe41
by Simon Peyton Jones at 2026-01-15T12:57:16+00:00
18 changed files:
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/CSE.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/FloatIn.hs
- compiler/GHC/Core/Opt/SetLevels.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/Opt/Specialise.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/DynFlags.hs
- testsuite/tests/linear/should_compile/T26332.hs
- testsuite/tests/linear/should_compile/all.T
Changes:
| ... | ... | @@ -438,7 +438,7 @@ follows, in decreasing order of permissiveness: |
| 438 | 438 | In particular, we cannot safely rewrite such an invalid call to a runtime
|
| 439 | 439 | error; we must emit code that produces a valid Word32#. (If we're lucky,
|
| 440 | 440 | Core Lint may complain that the result of such a rewrite violates
|
| 441 | - Note [Core binding invariants: nested non-rec] (#16742), but the rewrite
|
|
| 441 | + Note [Nested non-rec binding invariants] (#16742), but the rewrite
|
|
| 442 | 442 | is always wrong!) See also Note [Guarding against silly shifts] in
|
| 443 | 443 | GHC.Core.Opt.ConstantFold.
|
| 444 | 444 | |
| ... | ... | @@ -581,7 +581,7 @@ Several predicates on primops test this flag: |
| 581 | 581 | * The "no-float-out" thing is achieved by ensuring that we never let-bind a
|
| 582 | 582 | saturated primop application unless it has NoEffect. The RHS of a
|
| 583 | 583 | let-binding (which can float in and out freely) satisfies
|
| 584 | - exprOkForSpeculation; this is Note [Core binding invariants: nested non-rec].
|
|
| 584 | + exprOkForSpeculation; this is Note [Nested non-rec binding invariants].
|
|
| 585 | 585 | And exprOkForSpeculation is false of a saturated primop application unless it
|
| 586 | 586 | has NoEffect.
|
| 587 | 587 |
| ... | ... | @@ -397,27 +397,27 @@ Note [Core binding invariants] |
| 397 | 397 | A core binding, `CoreBind`, obeys these invariants:
|
| 398 | 398 | |
| 399 | 399 | * For /top level/ or /recursive/ bindings,
|
| 400 | - see Note [Top-level binding invariants]
|
|
| 400 | + see Note [Top/rec binding invariants]
|
|
| 401 | 401 | |
| 402 | 402 | * For /nested/ (not top-level) /non-recursive/ bindings,
|
| 403 | - see Note [Nested binding invariants]
|
|
| 403 | + see Note [Nested non-rec binding invariants]
|
|
| 404 | 404 | |
| 405 | -Note [Top-level binding invariants]
|
|
| 406 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 405 | +Note [Top/rec binding invariants]
|
|
| 406 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 407 | 407 | A /top-level/ or /recursive/ binding must
|
| 408 | 408 | |
| 409 | - * be of lifted type
|
|
| 410 | -OR
|
|
| 409 | + * be of lifted type, OR
|
|
| 410 | + |
|
| 411 | 411 | * have a RHS that is a primitive string literal
|
| 412 | - (see Note [Core top-level string literals], or
|
|
| 413 | -OR
|
|
| 414 | - * have a rhs that is (Coercion co)
|
|
| 415 | -OR
|
|
| 416 | - * be a worker or wrapper for an unlifted non-newtype data constructor; see (TL1).
|
|
| 412 | + (see Note [Core top-level string literals], OR
|
|
| 413 | + |
|
| 414 | + * have a rhs that is (Coercion co), OR
|
|
| 415 | + |
|
| 416 | + * be a worker or wrapper for an unlifted non-newtype
|
|
| 417 | + data constructor; see (TL1).
|
|
| 417 | 418 | |
| 418 | -For the non-top-level, non-recursive case see Note [Nested binding invariants].
|
|
| 419 | -(NB: this Note applies to recursive as well as top-level bindings, but I wanted
|
|
| 420 | -a short title!)
|
|
| 419 | +For the non-top-level, non-recursive case
|
|
| 420 | +see Note [Nested non-rec binding invariants].
|
|
| 421 | 421 | |
| 422 | 422 | See "Type#type_classification" in GHC.Core.Type
|
| 423 | 423 | for the meaning of "lifted" vs. "unlifted".
|
| ... | ... | @@ -439,8 +439,8 @@ constructor worker or wrapper |
| 439 | 439 | S1 = S1
|
| 440 | 440 | We allow this top-level unlifted binding to exist.
|
| 441 | 441 | |
| 442 | -Note [Nested binding invariants]
|
|
| 443 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 442 | +Note [Nested non-rec binding invariants]
|
|
| 443 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 444 | 444 | A /non-top-level/, /non-recursive/ binding must
|
| 445 | 445 | * Be a join point; see Note [Invariants on join points]
|
| 446 | 446 | OR
|
| ... | ... | @@ -471,7 +471,7 @@ The Core binding invariants are initially enforced by mkCoreLet in GHC.Core.Make |
| 471 | 471 | Historical Note [The let/app invariant]
|
| 472 | 472 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 473 | 473 | Before 2022 GHC used the "let/app invariant", which applied
|
| 474 | -Note [Nested binding invariants] to the argument of an application,
|
|
| 474 | +Note [Nested non-rec binding invariants] to the argument of an application,
|
|
| 475 | 475 | as well as to the RHS of a let. This made some kind of sense, because 'let' can
|
| 476 | 476 | always be encoded as application: let x=rhs in b = (\x.b) rhs
|
| 477 | 477 | |
| ... | ... | @@ -641,8 +641,8 @@ checked by Core Lint. |
| 641 | 641 | multiplicity of the corresponding field /scaled by the multiplicity of the
|
| 642 | 642 | case binder/. Checked in lintCoreAlt.
|
| 643 | 643 | |
| 644 | -Note [Core type and coercion invariant]
|
|
| 645 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 644 | +Note [Core type and coercion invariants]
|
|
| 645 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 646 | 646 | We allow `let` to bind type and coercion variables.
|
| 647 | 647 | |
| 648 | 648 | * A type or coercion binding is always /non-recursive/
|
| ... | ... | @@ -887,7 +887,7 @@ Join points must follow these invariants: |
| 887 | 887 | However, join points have simpler invariants in other ways
|
| 888 | 888 | |
| 889 | 889 | 5. A join point can have an unboxed type without the RHS being
|
| 890 | - ok-for-speculation; see
|
|
| 890 | + ok-for-speculation; see
|
|
| 891 | 891 | e.g. let j :: Int# = factorial x in ...
|
| 892 | 892 | |
| 893 | 893 | 6. The RHS of join point is not required to have a fixed runtime representation,
|
| ... | ... | @@ -2095,8 +2095,8 @@ mkDoubleLit d = Lit (mkLitDouble d) |
| 2095 | 2095 | mkDoubleLitDouble d = Lit (mkLitDouble (toRational d))
|
| 2096 | 2096 | |
| 2097 | 2097 | -- | Bind all supplied binding groups over an expression in a nested let expression.
|
| 2098 | --- Assumes that the rhs satisfies Note [Nested binding invariants]. Prefer to use
|
|
| 2099 | --- 'GHC.Core.Make.mkCoreLets' if possible, which does guarantee the invariant
|
|
| 2098 | +-- Assumes that the rhs satisfies Note [Nested non-rec binding invariants].
|
|
| 2099 | +-- Prefer to use 'GHC.Core.Make.mkCoreLets' if possible, which does guarantee the invariant
|
|
| 2100 | 2100 | mkLets :: [Bind b] -> Expr b -> Expr b
|
| 2101 | 2101 | -- | Bind all supplied binders over an expression in a nested lambda expression. Prefer to
|
| 2102 | 2102 | -- use 'GHC.Core.Make.mkCoreLams' if possible
|
| ... | ... | @@ -270,10 +270,12 @@ optCoRefl subst in_co |
| 270 | 270 | = let out_co = opt_co_refl subst in_co
|
| 271 | 271 | (Pair in_l in_r) = coercionKind in_co
|
| 272 | 272 | (Pair out_l out_r) = coercionKind out_co
|
| 273 | - in if (in_l `eqType` out_l) && (in_r `eqType` out_r)
|
|
| 273 | + in_l' = substTy subst in_l
|
|
| 274 | + in_r' = substTy subst in_r
|
|
| 275 | + in if (in_l' `eqType` out_l) && (in_r' `eqType` out_r)
|
|
| 274 | 276 | then out_co
|
| 275 | - else pprTrace "optReflCo" (vcat [ text "in_l:" <+> ppr in_l
|
|
| 276 | - , text "in_r:" <+> ppr in_r
|
|
| 277 | + else pprTrace "optReflCo" (vcat [ text "in_l':" <+> ppr in_l'
|
|
| 278 | + , text "in_r':" <+> ppr in_r'
|
|
| 277 | 279 | , text "out_l:" <+> ppr out_l
|
| 278 | 280 | , text "out_r:" <+> ppr out_r
|
| 279 | 281 | , text "in_co:" <+> ppr in_co
|
| ... | ... | @@ -113,7 +113,7 @@ sortQuantVars vs = sorted_tcvs ++ ids |
| 113 | 113 | -- appropriate (see "GHC.Core#let_can_float_invariant")
|
| 114 | 114 | mkCoreLet :: HasDebugCallStack => CoreBind -> CoreExpr -> CoreExpr
|
| 115 | 115 | mkCoreLet (NonRec bndr rhs) body
|
| 116 | - = -- See Note [Core binding invariants: nested non-rec]
|
|
| 116 | + = -- See Note [Nested non-rec binding invariants]
|
|
| 117 | 117 | bindNonRec bndr rhs body
|
| 118 | 118 | mkCoreLet bind body
|
| 119 | 119 | = Let bind body
|
| ... | ... | @@ -287,8 +287,8 @@ Here is another reason that we do not use SUBSTITUTE for |
| 287 | 287 | all trivial expressions. Consider
|
| 288 | 288 | case x |> co of (y::Array# Int) { ... }
|
| 289 | 289 | |
| 290 | -We do not want to extend the substitution with (y -> x |> co); since y
|
|
| 291 | -is of unlifted type, this would destroy Note [Nested binding invariants]
|
|
| 290 | +We do not want to extend the substitution with (y -> x |> co); since y is of
|
|
| 291 | +unlifted type, this would destroy Note [Nested non-rec binding invariants]
|
|
| 292 | 292 | if (x |> co) was not ok-for-speculation.
|
| 293 | 293 | |
| 294 | 294 | But surely (x |> co) is ok-for-speculation, because it's a trivial
|
| ... | ... | @@ -1607,7 +1607,7 @@ as follows: |
| 1607 | 1607 | in ...
|
| 1608 | 1608 | |
| 1609 | 1609 | This was originally done in the fix to #16449 but this breaks
|
| 1610 | -Note [Nested binding invariants] in GHC.Core, as noted in #16742. For the
|
|
| 1610 | +Note [Nested non-rec binding invariants] in GHC.Core, as noted in #16742. For the
|
|
| 1611 | 1611 | reasons discussed under "NoEffect" in Note [Classifying primop effects] (in
|
| 1612 | 1612 | GHC.Builtin.PrimOps) there is no safe way to rewrite the argument of I# such
|
| 1613 | 1613 | that it bottoms.
|
| ... | ... | @@ -2177,7 +2177,7 @@ BigNat). These rules implement the same kind of constant folding as we have for |
| 2177 | 2177 | Int#/Word#/etc. primops. See builtinBignumRules.
|
| 2178 | 2178 | |
| 2179 | 2179 | These rules are built-in because they can't be expressed as regular rules for
|
| 2180 | -now. The reason is that due to Note [Nested binding invariants] in GHC.Core,
|
|
| 2180 | +now. The reason is that due to Note [Nested non-rec binding invariants] in GHC.Core,
|
|
| 2181 | 2181 | GHC is too conservative with some bignum operations and they don't match rules.
|
| 2182 | 2182 | For example:
|
| 2183 | 2183 | |
| ... | ... | @@ -2185,8 +2185,8 @@ For example: |
| 2185 | 2185 | |
| 2186 | 2186 | doesn't constant-fold into `integerAdd 2 x` with a regular rule. That's because
|
| 2187 | 2187 | GHC never floats in `integerAdd 1 x` to form `integerAdd 1 (integerAdd 1 x)`
|
| 2188 | -because of Note [Nested binding invariants] (it doesn't know if `integerAdd`
|
|
| 2189 | -terminates).
|
|
| 2188 | +because of Note [Nested non-rec binding invariants] (it doesn't know if
|
|
| 2189 | +`integerAdd` terminates).
|
|
| 2190 | 2190 | |
| 2191 | 2191 | In the built-in rule for `integerAdd` we can access the unfolding of `r` and we
|
| 2192 | 2192 | can perform the appropriate substitution.
|
| ... | ... | @@ -665,7 +665,7 @@ noFloatIntoRhs is_rec bndr rhs |
| 665 | 665 | = isRec is_rec -- Joins are one-shot iff non-recursive
|
| 666 | 666 | |
| 667 | 667 | | definitelyUnliftedType (idType bndr)
|
| 668 | - = True -- Preserve Note [Nested binding invariants],
|
|
| 668 | + = True -- Preserve Note [Nested non-rec binding invariants],
|
|
| 669 | 669 | -- see Note [noFloatInto considerations]
|
| 670 | 670 | |
| 671 | 671 | | otherwise
|
| ... | ... | @@ -691,7 +691,7 @@ When do we want to float bindings into |
| 691 | 691 | - noFloatIntoArg: the argument of a function application
|
| 692 | 692 | |
| 693 | 693 | Definitely don't float into RHS if it has unlifted type;
|
| 694 | -that would destroy Note [Nested binding invariants].
|
|
| 694 | +that would destroy Note [Nested non-rec binding invariants].
|
|
| 695 | 695 | |
| 696 | 696 | * Wrinkle 1: do not float in if
|
| 697 | 697 | (a) any non-one-shot value lambdas
|
| ... | ... | @@ -1003,11 +1003,11 @@ Why? Because it's important /not/ to transform |
| 1003 | 1003 | let x = a /# 3
|
| 1004 | 1004 | to
|
| 1005 | 1005 | let x = case bx of I# a -> a /# 3
|
| 1006 | -because the let binding no longer obeys Note [Nested binding invariants].
|
|
| 1006 | +because the let binding no longer obeys Note [Nested non-rec binding invariants].
|
|
| 1007 | 1007 | But (a /# 3) is ok-for-spec due to a special hack that says division operators
|
| 1008 | 1008 | can't fail when the denominator is definitely non-zero. And yet that same
|
| 1009 | 1009 | expression says False to exprIsCheap. Simplest way to guarantee
|
| 1010 | -Note [Nested binding invariants] is to use the same function!
|
|
| 1010 | +Note [Nested non-rec binding invariants] is to use the same function!
|
|
| 1011 | 1011 | |
| 1012 | 1012 | If an expression is okay for speculation, we could also float it out
|
| 1013 | 1013 | *without* boxing and unboxing, since evaluating it early is okay.
|
| ... | ... | @@ -749,8 +749,10 @@ Examples |
| 749 | 749 | NonRec x# (y +# 3) FltOkSpec -- Unboxed, but ok-for-spec'n
|
| 750 | 750 | |
| 751 | 751 | NonRec x* (f y) FltCareful -- Strict binding; might fail or diverge
|
| 752 | - NonRec x# (a /# b) FltCareful -- Might fail; does not satisfy Note [Nested binding invariants]
|
|
| 753 | - NonRec x# (f y) FltCareful -- Might diverge; does not satisfy Note [Nested binding invariants]
|
|
| 752 | + NonRec x# (a /# b) FltCareful -- Might fail; does not satisfy
|
|
| 753 | + -- Note [Nested non-rec binding invariants]
|
|
| 754 | + NonRec x# (f y) FltCareful -- Might diverge; does not satisfy
|
|
| 755 | + -- Note [Nested non-rec binding invariants]
|
|
| 754 | 756 | -}
|
| 755 | 757 | |
| 756 | 758 | data LetFloats = LetFloats (OrdList OutBind) FloatFlag
|
| ... | ... | @@ -763,7 +765,8 @@ data FloatFlag |
| 763 | 765 | = FltLifted -- All bindings are lifted and lazy *or*
|
| 764 | 766 | -- consist of a single primitive string literal
|
| 765 | 767 | -- Hence ok to float to top level, or recursive
|
| 766 | - -- NB: consequence: all bindings satisfy Note [Nested binding invariants]
|
|
| 768 | + -- NB: consequence: all bindings satisfy
|
|
| 769 | + -- Note [Nested non-rec binding invariants]
|
|
| 767 | 770 | |
| 768 | 771 | | FltOkSpec -- All bindings are FltLifted *or*
|
| 769 | 772 | -- strict (perhaps because unlifted,
|
| ... | ... | @@ -772,12 +775,14 @@ data FloatFlag |
| 772 | 775 | -- Hence ok to float out of the RHS
|
| 773 | 776 | -- of a lazy non-recursive let binding
|
| 774 | 777 | -- (but not to top level, or into a rec group)
|
| 775 | - -- NB: consequence: all bindings satisfy Note [Nested binding invariants]
|
|
| 778 | + -- NB: consequence: all bindings satisfy
|
|
| 779 | + -- Note [Nested non-rec binding invariants]
|
|
| 776 | 780 | |
| 777 | 781 | | FltCareful -- At least one binding is strict (or unlifted)
|
| 778 | 782 | -- and not guaranteed cheap
|
| 779 | 783 | -- Do not float these bindings out of a lazy let!
|
| 780 | - -- NB: some bindings may not satisfy Note [Nested binding invariants]
|
|
| 784 | + -- NB: some bindings may not satisfy
|
|
| 785 | + -- Note [Nested non-rec binding invariants]
|
|
| 781 | 786 | |
| 782 | 787 | instance Outputable LetFloats where
|
| 783 | 788 | ppr (LetFloats binds ff) = ppr ff $$ ppr (fromOL binds)
|
| ... | ... | @@ -962,8 +967,10 @@ wrapFloats (SimplFloats { sfLetFloats = LetFloats bs flag |
| 962 | 967 | -- Note: Always safe to put the joins on the inside
|
| 963 | 968 | -- since the values can't refer to them
|
| 964 | 969 | where
|
| 965 | - mk_let | FltCareful <- flag = mkCoreLet -- Need to enforce Note [Nested binding invariants]
|
|
| 966 | - | otherwise = Let -- Note [Nested binding invariants] holds
|
|
| 970 | + mk_let | FltCareful <- flag
|
|
| 971 | + = mkCoreLet -- Need to enforce Note [Nested non-rec binding invariants]
|
|
| 972 | + | otherwise
|
|
| 973 | + = Let -- Note [Nested non-rec binding invariants] holds
|
|
| 967 | 974 | |
| 968 | 975 | wrapJoinFloatsX :: SimplFloats -> OutExpr -> (SimplFloats, OutExpr)
|
| 969 | 976 | -- Wrap the sfJoinFloats of the env around the expression,
|
| ... | ... | @@ -315,7 +315,7 @@ simplLazyBind :: TopLevelFlag -> RecFlag |
| 315 | 315 | -> (InExpr, SimplEnv) -- The RHS and its static environment
|
| 316 | 316 | -> SimplM (SimplFloats, SimplEnv)
|
| 317 | 317 | -- Precondition: Ids only, no TyVars; not a JoinId
|
| 318 | --- Precondition: rhs obeys Note [Nested binding invariants]
|
|
| 318 | +-- Precondition: rhs obeys Note [Nested non-rec binding invariants]
|
|
| 319 | 319 | simplLazyBind top_lvl is_rec (bndr,unf_se) (bndr1,env) (rhs,rhs_se)
|
| 320 | 320 | = assert (isId bndr )
|
| 321 | 321 | assertPpr (not (isJoinId bndr)) (ppr bndr) $
|
| ... | ... | @@ -397,7 +397,7 @@ simplAuxBind :: String |
| 397 | 397 | -- The binder comes from a case expression (case binder or alternative)
|
| 398 | 398 | -- and so does not have rules, unfolding, inline pragmas etc.
|
| 399 | 399 | --
|
| 400 | --- Precondition: rhs satisfies Note [Nested binding invariants]
|
|
| 400 | +-- Precondition: rhs satisfies Note [Nested non-rec binding invariants]
|
|
| 401 | 401 | |
| 402 | 402 | simplAuxBind _str env bndr new_rhs
|
| 403 | 403 | | assertPpr (isId bndr && not (isJoinId bndr)) (ppr bndr) $
|
| ... | ... | @@ -950,7 +950,7 @@ completeBind :: BindContext |
| 950 | 950 | -- * or by adding to the floats in the envt
|
| 951 | 951 | --
|
| 952 | 952 | -- Binder /can/ be a JoinId
|
| 953 | --- Precondition: rhs obeys Note [Nested binding invariants]
|
|
| 953 | +-- Precondition: rhs obeys Note [Nested non-rec binding invariants]
|
|
| 954 | 954 | completeBind bind_cxt (old_bndr, unf_se) (new_bndr, new_rhs, env)
|
| 955 | 955 | | isCoVar old_bndr
|
| 956 | 956 | = case new_rhs of
|
| ... | ... | @@ -1290,7 +1290,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont |
| 1290 | 1290 | ; simplExprF (extendTvSubst env bndr ty') body cont }
|
| 1291 | 1291 | |
| 1292 | 1292 | | Just env' <- preInlineUnconditionally env NotTopLevel bndr rhs env
|
| 1293 | - -- Because of Note [Nested binding invariants], it's ok to
|
|
| 1293 | + -- Because of Note [Nested non-rec binding invariants], it's ok to
|
|
| 1294 | 1294 | -- inline freely, or to drop the binding if it is dead.
|
| 1295 | 1295 | = do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr <+> ppr rhs) $
|
| 1296 | 1296 | tick (PreInlineUnconditionally bndr)
|
| ... | ... | @@ -1594,13 +1594,13 @@ rebuild_go env expr cont |
| 1594 | 1594 | completeBindX :: SimplEnv
|
| 1595 | 1595 | -> FromWhat
|
| 1596 | 1596 | -> InId -> OutExpr -- Non-recursively bind this Id to this (simplified) expression
|
| 1597 | - -- (Note [Nested binding invariants] may not be satisfied)
|
|
| 1597 | + -- (Note [Nested non-rec binding invariants] may not be satisfied)
|
|
| 1598 | 1598 | -> InExpr -- In this body
|
| 1599 | 1599 | -> SimplCont -- Consumed by this continuation
|
| 1600 | 1600 | -> SimplM (SimplFloats, OutExpr)
|
| 1601 | 1601 | completeBindX env from_what bndr rhs body cont
|
| 1602 | 1602 | | FromBeta arg_levity <- from_what
|
| 1603 | - , needsCaseBindingL arg_levity rhs -- Enforcing Note [Nested binding invariants]
|
|
| 1603 | + , needsCaseBindingL arg_levity rhs -- Enforcing Note [Nested non-rec binding invariants]
|
|
| 1604 | 1604 | = do { (env1, bndr1) <- simplNonRecBndr env bndr -- Lambda binders don't have rules
|
| 1605 | 1605 | ; (floats, expr') <- simplNonRecBody env1 from_what body cont
|
| 1606 | 1606 | -- Do not float floats past the Case binder below
|
| ... | ... | @@ -1887,7 +1887,7 @@ simplNonRecE :: HasDebugCallStack |
| 1887 | 1887 | -- It deals with strict bindings, via the StrictBind continuation,
|
| 1888 | 1888 | -- which may abort the whole process.
|
| 1889 | 1889 | --
|
| 1890 | --- from_what=FromLet => the RHS satisfies Note [Nested binding invariants]
|
|
| 1890 | +-- from_what=FromLet => the RHS satisfies Note [Nested non-rec binding invariants]
|
|
| 1891 | 1891 | -- Otherwise it may or may not satisfy it.
|
| 1892 | 1892 | |
| 1893 | 1893 | simplNonRecE env from_what bndr (rhs, rhs_se) body cont
|
| ... | ... | @@ -1909,8 +1909,8 @@ simplNonRecE env from_what bndr (rhs, rhs_se) body cont |
| 1909 | 1909 | where
|
| 1910 | 1910 | is_strict_bind = case from_what of
|
| 1911 | 1911 | FromBeta Unlifted -> True
|
| 1912 | - -- If we are coming from a beta-reduction (FromBeta) we must
|
|
| 1913 | - -- establish Note [Nested binding invariants], so go via StrictBind
|
|
| 1912 | + -- If we are coming from a beta-reduction (FromBeta) we must establish
|
|
| 1913 | + -- Note [Nested non-rec binding invariants], so go via StrictBind
|
|
| 1914 | 1914 | -- If not, the invariant holds already, and it's optional.
|
| 1915 | 1915 | |
| 1916 | 1916 | -- (FromBeta Lifted) or FromLet: look at the demand info
|
| ... | ... | @@ -2857,7 +2857,7 @@ this transformation: |
| 2857 | 2857 | We treat the unlifted and lifted cases separately:
|
| 2858 | 2858 | |
| 2859 | 2859 | * Unlifted case: 'e' satisfies exprOkForSpeculation
|
| 2860 | - (ok-for-spec is needed to satisfy Note [Nested binding invariants].
|
|
| 2860 | + (ok-for-spec is needed to satisfy Note [Nested non-rec binding invariants].
|
|
| 2861 | 2861 | This turns case a +# b of r -> ...r...
|
| 2862 | 2862 | into let r = a +# b in ...r...
|
| 2863 | 2863 | and thence .....(a +# b)....
|
| ... | ... | @@ -3112,7 +3112,7 @@ rebuildCase env scrut case_bndr alts cont |
| 3112 | 3112 | assert (null bs) $
|
| 3113 | 3113 | do { (floats1, env') <- simplAuxBind "rebuildCase" env case_bndr case_bndr_rhs
|
| 3114 | 3114 | -- scrut is a constructor application,
|
| 3115 | - -- hence satisfies Note [Nested binding invariants]
|
|
| 3115 | + -- hence satisfies Note [Nested non-rec binding invariants]
|
|
| 3116 | 3116 | ; (floats2, expr') <- simplExprF env' rhs cont
|
| 3117 | 3117 | ; case wfloats of
|
| 3118 | 3118 | [] -> return (floats1 `addFloats` floats2, expr')
|
| ... | ... | @@ -3624,13 +3624,14 @@ We pin on a (OtherCon []) unfolding to the case-binder of a Case, |
| 3624 | 3624 | even though it'll be over-ridden in every case alternative with a more
|
| 3625 | 3625 | informative unfolding. Why? Because suppose a later, less clever, pass
|
| 3626 | 3626 | simply replaces all occurrences of the case binder with the binder itself;
|
| 3627 | -then Lint may complain about failing Note [Nested binding invariants]. Example
|
|
| 3627 | +then Lint may complain about failing Note [Nested non-rec binding invariants].
|
|
| 3628 | +Example:
|
|
| 3628 | 3629 | case e of b { DEFAULT -> let v = reallyUnsafePtrEquality# b y in ....
|
| 3629 | 3630 | ; K -> blah }
|
| 3630 | 3631 | |
| 3631 | -Note [Nested binding invariants] requires that y is evaluated in the call to
|
|
| 3632 | -reallyUnsafePtrEquality#, which it is. But we still want that to be true if we
|
|
| 3633 | -propagate binders to occurrences.
|
|
| 3632 | +Note [Nested non-rec binding invariants] requires that y is evaluated in the
|
|
| 3633 | +call to reallyUnsafePtrEquality#, which it is. But we still want that to be
|
|
| 3634 | +true if we propagate binders to occurrences.
|
|
| 3634 | 3635 | |
| 3635 | 3636 | This showed up in #13027.
|
| 3636 | 3637 | |
| ... | ... | @@ -3732,7 +3733,7 @@ knownCon env scrut dc_floats dc dc_ty_args dc_args bndr bs rhs cont |
| 3732 | 3733 | -- occur in the RHS; and simplAuxBind may therefore discard it.
|
| 3733 | 3734 | -- Nevertheless we must keep it if the case-binder is alive,
|
| 3734 | 3735 | -- because it may be used in the con_app. See Note [knownCon occ info]
|
| 3735 | - -- NB: arg satisfies Note [Nested binding invariants]
|
|
| 3736 | + -- NB: arg satisfies Note [Nested non-rec binding invariants]
|
|
| 3736 | 3737 | ; (floats1, env2) <- simplAuxBind "knownCon" env' b' arg
|
| 3737 | 3738 | ; (floats2, env3) <- bind_args env2 bs' args
|
| 3738 | 3739 | ; return (floats1 `addFloats` floats2, env3) }
|
| ... | ... | @@ -1491,8 +1491,8 @@ preInlineUnconditionally |
| 1491 | 1491 | :: SimplEnv -> TopLevelFlag -> InId
|
| 1492 | 1492 | -> InExpr -> StaticEnv -- These two go together
|
| 1493 | 1493 | -> Maybe SimplEnv -- Returned env has extended substitution
|
| 1494 | --- Precondition: rhs satisfies Note [Nested binding invariants]
|
|
| 1495 | --- See Note [Nested binding invariants] in GHC.Core
|
|
| 1494 | +-- Precondition: rhs satisfies Note [Nested non-rec binding invariants]
|
|
| 1495 | +-- See Note [Nested non-rec binding invariants] in GHC.Core
|
|
| 1496 | 1496 | -- Reason: we don't want to inline single uses, or discard dead bindings,
|
| 1497 | 1497 | -- for unlifted, side-effect-ful bindings
|
| 1498 | 1498 | preInlineUnconditionally env top_lvl bndr rhs rhs_env
|
| ... | ... | @@ -1638,7 +1638,7 @@ postInlineUnconditionally |
| 1638 | 1638 | -> InId -> OutId -- The binder (*not* a CoVar), including its unfolding
|
| 1639 | 1639 | -> OutExpr
|
| 1640 | 1640 | -> Bool
|
| 1641 | --- Precondition: rhs satisfies Note [Nested binding invariants] in GHC.Core
|
|
| 1641 | +-- Precondition: rhs satisfies Note [Nested non-rec binding invariants] in GHC.Core
|
|
| 1642 | 1642 | -- Reason: we don't want to inline single uses, or discard dead bindings,
|
| 1643 | 1643 | -- for unlifted, side-effect-ful bindings
|
| 1644 | 1644 | postInlineUnconditionally env bind_cxt old_bndr bndr rhs
|
| ... | ... | @@ -1937,14 +1937,14 @@ where |
| 1937 | 1937 | |
| 1938 | 1938 | Left to itself, the specialiser would float the bindings for `x` and `n` to top
|
| 1939 | 1939 | level, so we can specialise `wombat`. But we can't have a top-level ByteArray#
|
| 1940 | -(see Note [Core letrec invariant] in GHC.Core). Boo.
|
|
| 1940 | +(see Note [Top/rec binding invariants] in GHC.Core). Boo.
|
|
| 1941 | 1941 | |
| 1942 | 1942 | This is pretty exotic, so we take a simple way out: in specBind (the NonRec
|
| 1943 | 1943 | case) do not float the binding itself unless it satisfies exprIsTopLevelBindable.
|
| 1944 | 1944 | This is conservative: maybe the RHS of `x` has a free var that would stop it
|
| 1945 | 1945 | floating to top level anyway; but that is hard to spot (since we don't know what
|
| 1946 | 1946 | the non-top-level in-scope binders are) and rare (since the binding must satisfy
|
| 1947 | -Note [Nested binding invariants] in GHC.Core).
|
|
| 1947 | +Note [Nested non-rec binding invariants] in GHC.Core).
|
|
| 1948 | 1948 | |
| 1949 | 1949 | |
| 1950 | 1950 | Note [Specialising Calls]
|
| ... | ... | @@ -381,7 +381,8 @@ simple_app env e0@(Lam {}) as0@(_:_) |
| 381 | 381 | -- See Note [Dark corner with representation polymorphism]
|
| 382 | 382 | needsCaseBinding (idType b') (snd a)
|
| 383 | 383 | -- This arg must not be inlined (side-effects) and cannot be let-bound,
|
| 384 | - -- due to Note [Nested binding invariants]. So simply case-bind it here.
|
|
| 384 | + -- due to Note [Nested non-rec binding invariants].
|
|
| 385 | + -- So simply case-bind it here.
|
|
| 385 | 386 | , let a' = simple_opt_clo (soeInScope env) a
|
| 386 | 387 | = mkDefaultCase a' b' $ do_beta env' body as
|
| 387 | 388 |
| ... | ... | @@ -2042,15 +2042,15 @@ But we restrict it sharply: |
| 2042 | 2042 | ; False -> e2 }
|
| 2043 | 2043 | in ...) ...
|
| 2044 | 2044 | |
| 2045 | - Does the RHS of v satisfy Note [Nested binding invariants]?
|
|
| 2045 | + Does the RHS of v satisfy Note [Nested non-rec binding invariants]?
|
|
| 2046 | 2046 | Previously we said yes, on the grounds that y is evaluated. But the
|
| 2047 | 2047 | binder-swap done by GHC.Core.Opt.SetLevels would transform the inner
|
| 2048 | 2048 | alternative to
|
| 2049 | 2049 | |
| 2050 | 2050 | DEFAULT -> ... (let v::Int# = case x of { ... }
|
| 2051 | 2051 | in ...) ....
|
| 2052 | - which does /not/ satisfy Note [Nested bindings invariants], because x is
|
|
| 2053 | - not evaluated. See Note [Binder-swap during float-out]
|
|
| 2052 | + which does /not/ satisfy Note [Nested non-rec bindings invariants],
|
|
| 2053 | + because x is not evaluated. See Note [Binder-swap during float-out]
|
|
| 2054 | 2054 | in GHC.Core.Opt.SetLevels. To avoid this awkwardness it seems simpler
|
| 2055 | 2055 | to stick to unlifted scrutinees where the issue does not
|
| 2056 | 2056 | arise.
|
| ... | ... | @@ -2134,7 +2134,7 @@ extremely useful for float-out, changes these expressions to |
| 2134 | 2134 | |
| 2135 | 2135 | And now the expression does not obey the let-can-float invariant! Yikes!
|
| 2136 | 2136 | Moreover we really might float (dataToTagLarge# x) outside the case,
|
| 2137 | -and then it really, really doesn't obey Note [Nested binding invariants].
|
|
| 2137 | +and then it really, really doesn't obey Note [Nested non-rec binding invariants].
|
|
| 2138 | 2138 | |
| 2139 | 2139 | The solution is simple: exprOkForSpeculation does not try to take
|
| 2140 | 2140 | advantage of the evaluated-ness of (lifted) variables. And it returns
|
| ... | ... | @@ -2144,7 +2144,7 @@ by marking the relevant primops as "ThrowsException" or |
| 2144 | 2144 | GHC.Builtin.PrimOps.
|
| 2145 | 2145 | |
| 2146 | 2146 | Note that exprIsHNF /can/ and does take advantage of evaluated-ness;
|
| 2147 | -it doesn't have the trickiness of Note [Nested binding invariants]
|
|
| 2147 | +it doesn't have the trickiness of Note [Nested non-rec binding invariants]
|
|
| 2148 | 2148 | to worry about.
|
| 2149 | 2149 | |
| 2150 | 2150 | ************************************************************************
|
| ... | ... | @@ -302,7 +302,7 @@ expose the values: |
| 302 | 302 | see Note [wantFloatLocal].)
|
| 303 | 303 | If `v` is bound at the top-level, we might even float `sat` to top-level;
|
| 304 | 304 | see Note [Floating out of top level bindings].
|
| 305 | -For nested let bindings, we have to keep in mind Note [Core letrec invariant]
|
|
| 305 | +For nested let bindings, we have to keep in mind Note [Core binding invariants],
|
|
| 306 | 306 | and may exploit strict contexts; see Note [wantFloatLocal].
|
| 307 | 307 | |
| 308 | 308 | There are 3 main categories of floats, encoded in the `FloatingBind` type:
|
| ... | ... | @@ -1509,7 +1509,7 @@ Wrinkles: |
| 1509 | 1509 | |
| 1510 | 1510 | (FS1) We detect string literals in `cpeBind Rec{}` and float them out anyway;
|
| 1511 | 1511 | otherwise we'd try to bind a string literal in a letrec, violating
|
| 1512 | - Note [Core letrec invariant]. Since we know that literals don't have
|
|
| 1512 | + Note [Top/rec binding invariants]. Since we know that literals don't have
|
|
| 1513 | 1513 | free variables, we float further.
|
| 1514 | 1514 | Arguably, we could just as well relax the letrec invariant for
|
| 1515 | 1515 | string literals, or anthing that is a value (lifted or not).
|
| ... | ... | @@ -2363,7 +2363,7 @@ Wrinkles: |
| 2363 | 2363 | x = f y r
|
| 2364 | 2364 | y = [x]
|
| 2365 | 2365 | in e
|
| 2366 | - and now we have violated Note [Core letrec invariant].
|
|
| 2366 | + and now we have violated Note [Top/rec binding invariants].
|
|
| 2367 | 2367 | So we preempt this case in `wantFloatLocal`, responding `FloatNone` unless
|
| 2368 | 2368 | all floats are `TopLvlFloatable`.
|
| 2369 | 2369 | -}
|
| ... | ... | @@ -1233,7 +1233,7 @@ optLevelFlags -- see Note [Documenting optimisation flags] |
| 1233 | 1233 | , ([1,2], Opt_DoCleverArgEtaExpansion) -- See Note [Eta expansion of arguments in CorePrep]
|
| 1234 | 1234 | , ([0,1,2], Opt_DoEtaReduction) -- See Note [Eta-reduction in -O0]
|
| 1235 | 1235 | , ([0,1,2], Opt_ProfManualCcs )
|
| 1236 | - , ([0,1,2], Opt_OptCoercion ) -- See Note [Coercion optimisation] in GHC.Core.Coercion.Opt
|
|
| 1236 | + , ([2], Opt_OptCoercion ) -- See Note [Coercion optimisation] in GHC.Core.Coercion.Opt
|
|
| 1237 | 1237 | , ([2], Opt_DictsStrict)
|
| 1238 | 1238 | |
| 1239 | 1239 | , ([0], Opt_IgnoreInterfacePragmas)
|
| ... | ... | @@ -5,6 +5,12 @@ module T26332 where |
| 5 | 5 | |
| 6 | 6 | import Unsafe.Coerce
|
| 7 | 7 | |
| 8 | +-- This function should be accepted by the typechecker, and should be
|
|
| 9 | +-- linear-correct in the output of the desugarer, but will fail
|
|
| 10 | +-- -dlinear-core-lint (which does a linear-lint check after every simplifier
|
|
| 11 | +-- pass. Because the optimiser discards a cast on `f` that only affects
|
|
| 12 | +-- linearity
|
|
| 13 | + |
|
| 8 | 14 | toLinear
|
| 9 | 15 | :: forall a b p q.
|
| 10 | 16 | (a %p-> b) %1-> (a %q-> b)
|
| ... | ... | @@ -42,7 +42,7 @@ test('T19400', unless(compiler_debugged(), skip), compile, ['']) |
| 42 | 42 | test('T20023', normal, compile, [''])
|
| 43 | 43 | test('T22546', normal, compile, [''])
|
| 44 | 44 | test('T23025', normal, compile, ['-dlinear-core-lint'])
|
| 45 | -test('T26332', normal, compile, ['-O -dlinear-core-lint'])
|
|
| 45 | +test('T26332', normal, compile_fail, ['-O'])
|
|
| 46 | 46 | test('LinearRecUpd', normal, compile, [''])
|
| 47 | 47 | test('T23814', normal, compile, [''])
|
| 48 | 48 | test('LinearLet', normal, compile, [''])
|