Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC

Commits:

18 changed files:

Changes:

  • compiler/GHC/Builtin/PrimOps.hs
    ... ... @@ -435,12 +435,12 @@ follows, in decreasing order of permissiveness:
    435 435
         NoEffect, we may float such an invalid call out of a dead branch
    
    436 436
         and speculatively evaluate it.
    
    437 437
     
    
    438
    -    In particular, we cannot safely rewrite such an invalid call to a
    
    439
    -    runtime error; we must emit code that produces a valid Word32#.
    
    440
    -    (If we're lucky, Core Lint may complain that the result of such a
    
    441
    -    rewrite violates the let-can-float invariant (#16742), but the
    
    442
    -    rewrite is always wrong!)  See also Note [Guarding against silly shifts]
    
    443
    -    in GHC.Core.Opt.ConstantFold.
    
    438
    +    In particular, we cannot safely rewrite such an invalid call to a runtime
    
    439
    +    error; we must emit code that produces a valid Word32#.  (If we're lucky,
    
    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
    
    442
    +    is always wrong!)  See also Note [Guarding against silly shifts] in
    
    443
    +    GHC.Core.Opt.ConstantFold.
    
    444 444
     
    
    445 445
         Marking uncheckedShiftLWord32# as CanFail instead of NoEffect
    
    446 446
         would give us the freedom to rewrite such invalid calls to runtime
    
    ... ... @@ -578,12 +578,12 @@ Several predicates on primops test this flag:
    578 578
         where it is guarded by exprOkToDiscard, which in turn checks
    
    579 579
         primOpOkToDiscard.
    
    580 580
     
    
    581
    -  * The "no-float-out" thing is achieved by ensuring that we never
    
    582
    -    let-bind a saturated primop application unless it has NoEffect.
    
    583
    -    The RHS of a let-binding (which can float in and out freely)
    
    584
    -    satisfies exprOkForSpeculation; this is the let-can-float
    
    585
    -    invariant.  And exprOkForSpeculation is false of a saturated
    
    586
    -    primop application unless it has NoEffect.
    
    581
    +  * The "no-float-out" thing is achieved by ensuring that we never let-bind a
    
    582
    +    saturated primop application unless it has NoEffect.  The RHS of a
    
    583
    +    let-binding (which can float in and out freely) satisfies
    
    584
    +    exprOkForSpeculation; this is Note [Core binding invariants: nested non-rec].
    
    585
    +    And exprOkForSpeculation is false of a saturated primop application unless it
    
    586
    +    has NoEffect.
    
    587 587
     
    
    588 588
       * So primops that aren't NoEffect will appear only as the
    
    589 589
         scrutinees of cases, and that's why the FloatIn pass is capable
    

  • compiler/GHC/Core.hs
    ... ... @@ -188,8 +188,7 @@ These data types are the heart of the compiler
    188 188
     --    this corresponds to allocating a thunk for the things
    
    189 189
     --    bound and then executing the sub-expression.
    
    190 190
     --
    
    191
    ---    See Note [Core letrec invariant]
    
    192
    ---    See Note [Core let-can-float invariant]
    
    191
    +--    See Note [Core binding invariants]
    
    193 192
     --    See Note [Representation polymorphism invariants]
    
    194 193
     --    See Note [Core type and coercion invariant]
    
    195 194
     --
    
    ... ... @@ -393,25 +392,37 @@ extremely difficult to GUARANTEE it:
    393 392
     
    
    394 393
     * See Note [Shadowing in SpecConstr] in GHC.Core.Opt.SpecContr
    
    395 394
     
    
    396
    -Note [Core letrec invariant]
    
    397
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    398
    -The Core letrec invariant:
    
    395
    +Note [Core binding invariants]
    
    396
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    397
    +A core binding, `CoreBind`, obeys these invariants:
    
    399 398
     
    
    400
    -  The right hand sides of all /top-level/ or /recursive/
    
    401
    -  bindings must be of lifted type
    
    399
    +* For /top level/ or /recursive/ bindings,
    
    400
    +  see Note [Top-level binding invariants]
    
    402 401
     
    
    403
    -See "Type#type_classification" in GHC.Core.Type
    
    404
    -for the meaning of "lifted" vs. "unlifted".
    
    402
    +* For /nested/ (not top-level) /non-recursive/ bindings,
    
    403
    +  see Note [Nested binding invariants]
    
    404
    +
    
    405
    +Note [Top-level binding invariants]
    
    406
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    407
    +A /top-level/ or /recursive/ binding must
    
    405 408
     
    
    406
    -For the non-top-level, non-recursive case see
    
    407
    -Note [Core let-can-float invariant].
    
    409
    +  * be of lifted type
    
    410
    +OR
    
    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).
    
    408 417
     
    
    409
    -At top level, however, there are two exceptions to this rule:
    
    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!)
    
    410 421
     
    
    411
    -(TL1) A top-level binding is allowed to bind primitive string literal,
    
    412
    -      (which is unlifted).  See Note [Core top-level string literals].
    
    422
    +See "Type#type_classification" in GHC.Core.Type
    
    423
    +for the meaning of "lifted" vs. "unlifted".
    
    413 424
     
    
    414
    -(TL2) In Core, we generate a top-level binding for every non-newtype data
    
    425
    +(TL1) In Core, we generate a top-level binding for every non-newtype data
    
    415 426
     constructor worker or wrapper
    
    416 427
           e.g.   data T = MkT Int
    
    417 428
           we generate
    
    ... ... @@ -428,16 +439,17 @@ constructor worker or wrapper
    428 439
                  S1 = S1
    
    429 440
           We allow this top-level unlifted binding to exist.
    
    430 441
     
    
    431
    -Note [Core let-can-float invariant]
    
    432
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    433
    -The let-can-float invariant:
    
    434
    -
    
    435
    -    The right hand side of a /non-top-level/, /non-recursive/ binding
    
    436
    -    may be of unlifted type, but only if
    
    437
    -    the expression is ok-for-speculation
    
    438
    -    or the 'Let' is for a join point.
    
    442
    +Note [Nested binding invariants]
    
    443
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    444
    +A /non-top-level/, /non-recursive/ binding must
    
    445
    +  * Be a join point; see Note [Invariants on join points]
    
    446
    +OR
    
    447
    +  * Be of lifted type
    
    448
    +OR
    
    449
    +  * Have a RHS that is ok-for-speculation
    
    439 450
     
    
    440
    -    (For top-level or recursive lets see Note [Core letrec invariant].)
    
    451
    +NB: this only applies to /non-recursive/ bindings.  For recursive
    
    452
    +(or top-level) bindings see Note [Top-level binding invariants].
    
    441 453
     
    
    442 454
     This means that the let can be floated around
    
    443 455
     without difficulty. For example, this is OK:
    
    ... ... @@ -454,14 +466,14 @@ In this situation you should use @case@ rather than a @let@. The function
    454 466
     alternatively use 'GHC.Core.Make.mkCoreLet' rather than this constructor directly,
    
    455 467
     which will generate a @case@ if necessary
    
    456 468
     
    
    457
    -The let-can-float invariant is initially enforced by mkCoreLet in GHC.Core.Make.
    
    469
    +The Core binding invariants are initially enforced by mkCoreLet in GHC.Core.Make.
    
    458 470
     
    
    459 471
     Historical Note [The let/app invariant]
    
    460 472
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    461
    -Before 2022 GHC used the "let/app invariant", which applied the let-can-float rules
    
    462
    -to the argument of an application, as well as to the RHS of a let.  This made some
    
    463
    -kind of sense, because 'let' can always be encoded as application:
    
    464
    -   let x=rhs in b   =    (\x.b) rhs
    
    473
    +Before 2022 GHC used the "let/app invariant", which applied
    
    474
    +Note [Nested binding invariants] to the argument of an application,
    
    475
    +as well as to the RHS of a let.  This made some kind of sense, because 'let' can
    
    476
    +always be encoded as application: let x=rhs in b = (\x.b) rhs
    
    465 477
     
    
    466 478
     But the let/app invariant got in the way of RULES; see #19313.  For example
    
    467 479
       up :: Int# -> Int#
    
    ... ... @@ -472,7 +484,7 @@ Indeed RULES is a big reason that GHC doesn't use ANF, where the argument of an
    472 484
     application is always a variable or a constant.  To allow RULES to work nicely
    
    473 485
     we need to allow lots of things in the arguments of a call.
    
    474 486
     
    
    475
    -TL;DR: we relaxed the let/app invariant to become the let-can-float invariant.
    
    487
    +TL;DR: we relaxed the let/app invariant to focus just on /bindings/.
    
    476 488
     
    
    477 489
     Note [Core top-level string literals]
    
    478 490
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -631,13 +643,33 @@ checked by Core Lint.
    631 643
     
    
    632 644
     Note [Core type and coercion invariant]
    
    633 645
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    634
    -We allow a /non-recursive/, /non-top-level/ let to bind type and
    
    635
    -coercion variables.  These can be very convenient for postponing type
    
    636
    -substitutions until the next run of the simplifier.
    
    646
    +We allow `let` to bind type and coercion variables.
    
    647
    +
    
    648
    +* A type or coercion binding is always /non-recursive/
    
    649
    +
    
    650
    +* A type binding cannot be top level (yet) but a coercion binding
    
    651
    +  can be top-level.
    
    637 652
     
    
    638 653
     * A type variable binding must have a RHS of (Type ty)
    
    639 654
     
    
    640 655
     * A coercion variable binding must have a RHS of (Coercion co)
    
    656
    +  See Note [Coercion bindings]
    
    657
    +
    
    658
    +
    
    659
    +Note [Coercion bindings]
    
    660
    +~~~~~~~~~~~~~~~~~~~~~~~~
    
    661
    +We allow non-recursive let-bindings for coercion variables, CoVars,
    
    662
    +of type (t1 ~r# t2).
    
    663
    +
    
    664
    +The /main motivation/ is to support sharing:
    
    665
    +   let g::T a ~# b
    
    666
    +       g = Coercion <some big coercion?
    
    667
    +   in ...g..g..g...
    
    668
    +If we simply duplicate `g` at every occurrence site, we can bloat the
    
    669
    +size of the program, increasing both compile time and .hi-file sizes.
    
    670
    +
    
    671
    +* A  coercion binding always has a RHS of (Coercion co).
    
    672
    +  See Note [Core type and coercion invariants].
    
    641 673
     
    
    642 674
       It is possible to have terms that return a coercion, but we use
    
    643 675
       case-binding for those; e.g.
    
    ... ... @@ -650,6 +682,15 @@ substitutions until the next run of the simplifier.
    650 682
       Note [Equality superclasses in quantified constraints]
    
    651 683
       in GHC.Tc.Solver.Dict
    
    652 684
     
    
    685
    +* Coercion bindings can be top level.  And a top-level coercion binding can be
    
    686
    +  exported, and hence must:
    
    687
    +   * Have a GlobalId.
    
    688
    +   * Appear as a declaration in an interface file
    
    689
    +  That means that a coercion might mention a CoVar that is an imported GlobalId.
    
    690
    +  Just as for Core expressions, the free variable finder for Coercions can
    
    691
    +  ignore GlobalIds.
    
    692
    +
    
    693
    +
    
    653 694
     Note [Representation polymorphism invariants]
    
    654 695
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    655 696
     GHC allows us to abstract over calling conventions using **representation polymorphism**.
    
    ... ... @@ -846,7 +887,7 @@ Join points must follow these invariants:
    846 887
     However, join points have simpler invariants in other ways
    
    847 888
     
    
    848 889
       5. A join point can have an unboxed type without the RHS being
    
    849
    -     ok-for-speculation (i.e. drop the let-can-float invariant)
    
    890
    +     ok-for-speculation; see 
    
    850 891
          e.g.  let j :: Int# = factorial x in ...
    
    851 892
     
    
    852 893
       6. The RHS of join point is not required to have a fixed runtime representation,
    
    ... ... @@ -2053,8 +2094,8 @@ mkDoubleLitDouble :: Double -> Expr b
    2053 2094
     mkDoubleLit       d = Lit (mkLitDouble d)
    
    2054 2095
     mkDoubleLitDouble d = Lit (mkLitDouble (toRational d))
    
    2055 2096
     
    
    2056
    --- | Bind all supplied binding groups over an expression in a nested let expression. Assumes
    
    2057
    --- that the rhs satisfies the let-can-float invariant.  Prefer to use
    
    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
    
    2058 2099
     -- 'GHC.Core.Make.mkCoreLets' if possible, which does guarantee the invariant
    
    2059 2100
     mkLets        :: [Bind b] -> Expr b -> Expr b
    
    2060 2101
     -- | Bind all supplied binders over an expression in a nested lambda expression. Prefer to
    

  • compiler/GHC/Core/Coercion/Opt.hs
    ... ... @@ -46,7 +46,7 @@ Note [Coercion optimisation]
    46 46
     This module does coercion optimisation.  The purpose is to reduce the size
    
    47 47
     of the coercions that the compiler carries around -- they are just proofs,
    
    48 48
     and serve no runtime need. So the purpose of coercion optimisation is simply
    
    49
    -to shrink coercions and thereby reduce compile time.
    
    49
    +to shrink coercions and thereby reduce compile time and .hi file sizes.
    
    50 50
     
    
    51 51
     See the paper
    
    52 52
        Evidence normalization in Systtem FV (RTA'13)
    
    ... ... @@ -57,7 +57,7 @@ However, although powerful and occasionally very effective, coercion
    57 57
     optimisation can itself be very expensive (#26679).  So we apply it sparingly:
    
    58 58
     
    
    59 59
     * In the Simplifier, function `rebuild_go`, we use `isReflexiveCo` (which
    
    60
    -  computes the type of the coercion) to eliminate reflexive coercion, just
    
    60
    +  computes the type of the coercion) to eliminate reflexive coercions, just
    
    61 61
       before we build a cast (e |> co).
    
    62 62
     
    
    63 63
       (More precisely, we use `isReflexiveCoIgnoringMultiplicity;
    
    ... ... @@ -196,6 +196,10 @@ We use the following invariants:
    196 196
     %********************************************************************* -}
    
    197 197
     
    
    198 198
     optCoProgram :: CoreProgram -> CoreProgram
    
    199
    +-- Apply optCoercion to all coercions in /expressions/
    
    200
    +-- There may also be coercions in /types/ but we `optCoProgram` doesn't
    
    201
    +-- look at them; they are typically fewer and smaller, and it doesn't seem
    
    202
    +-- worth the cost of traversing and rebuilding all the types in the program.
    
    199 203
     optCoProgram binds
    
    200 204
       = map go binds
    
    201 205
       where
    
    ... ... @@ -237,7 +241,24 @@ optCoAlt is (Alt k bs e)
    237 241
     %*                                                                      *
    
    238 242
     %********************************************************************* -}
    
    239 243
     
    
    244
    +{- Note [optCoRefl]
    
    245
    +~~~~~~~~~~~~~~~~~~~~
    
    246
    +`optCoRefl` is an experimental cheap-and-cheerful version of `optCoercion`.
    
    247
    +
    
    248
    +* It focuses entirely on chains of TransCo, thus
    
    249
    +      co1 ; co2 ; co3 ; ... ; con
    
    250
    +
    
    251
    +* It looks for sub-sequences in this chain that are Refl, based on their
    
    252
    +  types.  The clever business is all in `gobble`, which springs into action
    
    253
    +  when we find a `TransCo`.
    
    254
    +
    
    255
    +* It can sometimes do a bit more than `optCoercion`. It'll eliminate /any/
    
    256
    +  subsequence of co1..con that is reflexive, whereas `optCoercion` just works
    
    257
    +  left-to-right, and won't spot (co1 ; co2 ; sym co2)
    
    258
    +-}
    
    259
    +
    
    240 260
     optCoRefl :: Coercion -> Coercion
    
    261
    +-- See Note [optCoRefl]
    
    241 262
     optCoRefl in_co
    
    242 263
     #ifdef DEBUG
    
    243 264
       -- Debug check that optCoRefl doesn't change the type
    

  • compiler/GHC/Core/Lint.hs
    ... ... @@ -586,8 +586,7 @@ lintLetBind top_lvl rec_flag binder rhs rhs_ty
    586 586
            ; checkL (not (isCoVar binder) || isCoArg rhs)
    
    587 587
                     (mkLetErr binder rhs)
    
    588 588
     
    
    589
    -        -- Check the let-can-float invariant
    
    590
    -        -- See Note [Core let-can-float invariant] in GHC.Core
    
    589
    +       -- Check Note [Core binding invariants] in GHC.Core
    
    591 590
            ; checkL (bindingIsOk top_lvl rec_flag binder binder_ty rhs) $
    
    592 591
              mkLetErr binder rhs
    
    593 592
     
    
    ... ... @@ -647,6 +646,7 @@ lintLetBind top_lvl rec_flag binder rhs rhs_ty
    647 646
             -- the unfolding is a SimplifiableCoreExpr. Give up for now.
    
    648 647
     
    
    649 648
     bindingIsOk :: TopLevelFlag -> RecFlag -> OutId -> OutType -> CoreExpr -> Bool
    
    649
    +-- Checks the invariants of Note [Core binding invariants] in GHC.Core
    
    650 650
     bindingIsOk top_lvl rec_flag binder binder_ty rhs
    
    651 651
       | isCoVar binder
    
    652 652
       = isCoArg rhs
    

  • compiler/GHC/Core/Make.hs
    ... ... @@ -112,8 +112,9 @@ sortQuantVars vs = sorted_tcvs ++ ids
    112 112
     -- | Bind a binding group over an expression, using a @let@ or @case@ as
    
    113 113
     -- appropriate (see "GHC.Core#let_can_float_invariant")
    
    114 114
     mkCoreLet :: HasDebugCallStack => CoreBind -> CoreExpr -> CoreExpr
    
    115
    -mkCoreLet (NonRec bndr rhs) body        -- See Note [Core let-can-float invariant]
    
    116
    -  = bindNonRec bndr rhs body
    
    115
    +mkCoreLet (NonRec bndr rhs) body
    
    116
    +  = -- See Note [Core binding invariants: nested non-rec]
    
    117
    +    bindNonRec bndr rhs body
    
    117 118
     mkCoreLet bind body
    
    118 119
       = Let bind body
    
    119 120
     
    

  • compiler/GHC/Core/Opt/CSE.hs
    ... ... @@ -288,8 +288,8 @@ all trivial expressions. Consider
    288 288
        case x |> co of (y::Array# Int) { ... }
    
    289 289
     
    
    290 290
     We do not want to extend the substitution with (y -> x |> co); since y
    
    291
    -is of unlifted type, this would destroy the let-can-float invariant if
    
    292
    -(x |> co) was not ok-for-speculation.
    
    291
    +is of unlifted type, this would destroy Note [Nested binding invariants]
    
    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
    
    295 295
     expression, and x's type is also unlifted, presumably.  Well, maybe
    

  • compiler/GHC/Core/Opt/ConstantFold.hs
    ... ... @@ -1606,11 +1606,11 @@ as follows:
    1606 1606
         let x = I# (error "invalid shift")
    
    1607 1607
         in ...
    
    1608 1608
     
    
    1609
    -This was originally done in the fix to #16449 but this breaks the
    
    1610
    -let-can-float invariant (see Note [Core let-can-float invariant] in
    
    1611
    -GHC.Core) as noted in #16742.  For the reasons discussed under
    
    1612
    -"NoEffect" in Note [Classifying primop effects] (in GHC.Builtin.PrimOps)
    
    1613
    -there is no safe way to rewrite the argument of I# such that it bottoms.
    
    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
    
    1611
    +reasons discussed under "NoEffect" in Note [Classifying primop effects] (in
    
    1612
    +GHC.Builtin.PrimOps) there is no safe way to rewrite the argument of I# such
    
    1613
    +that it bottoms.
    
    1614 1614
     
    
    1615 1615
     Consequently we instead take advantage of the fact that the result of a
    
    1616 1616
     large shift is unspecified (see associated documentation in primops.txt.pp)
    
    ... ... @@ -2177,15 +2177,15 @@ 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 the let-can-float invariant (see Note [Core
    
    2181
    -let-can-float invariant] in GHC.Core), GHC is too conservative with some bignum
    
    2182
    -operations and they don't match rules. For example:
    
    2180
    +now. The reason is that due to Note [Nested binding invariants] in GHC.Core,
    
    2181
    +GHC is too conservative with some bignum operations and they don't match rules.
    
    2182
    +For example:
    
    2183 2183
     
    
    2184 2184
       case integerAdd 1 x of r { _ -> integerAdd 1 r }
    
    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 the let-can-float invariant (it doesn't know if `integerAdd`
    
    2188
    +because of Note [Nested binding invariants] (it doesn't know if `integerAdd`
    
    2189 2189
     terminates).
    
    2190 2190
     
    
    2191 2191
     In the built-in rule for `integerAdd` we can access the unfolding of `r` and we
    

  • compiler/GHC/Core/Opt/FloatIn.hs
    ... ... @@ -665,7 +665,8 @@ 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 let-can-float invariant, see Note [noFloatInto considerations]
    
    668
    +  = True  -- Preserve Note [Nested binding invariants],
    
    669
    +          -- see Note [noFloatInto considerations]
    
    669 670
     
    
    670 671
       | otherwise
    
    671 672
       = noFloatIntoArg rhs
    
    ... ... @@ -690,7 +691,7 @@ When do we want to float bindings into
    690 691
        - noFloatIntoArg: the argument of a function application
    
    691 692
     
    
    692 693
     Definitely don't float into RHS if it has unlifted type;
    
    693
    -that would destroy the let-can-float invariant.
    
    694
    +that would destroy Note [Nested binding invariants].
    
    694 695
     
    
    695 696
     * Wrinkle 1: do not float in if
    
    696 697
          (a) any non-one-shot value lambdas
    

  • compiler/GHC/Core/Opt/SetLevels.hs
    ... ... @@ -1003,12 +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
    
    1007
    -longer obeys the let-can-float invariant.  But (a /# 3) is ok-for-spec
    
    1008
    -due to a special hack that says division operators can't fail
    
    1009
    -when the denominator is definitely non-zero.  And yet that
    
    1010
    -same expression says False to exprIsCheap.  Simplest way to
    
    1011
    -guarantee the let-can-float invariant is to use the same function!
    
    1006
    +because the let binding no longer obeys Note [Nested binding invariants].
    
    1007
    +But (a /# 3) is ok-for-spec due to a special hack that says division operators
    
    1008
    +can't fail when the denominator is definitely non-zero.  And yet that same
    
    1009
    +expression says False to exprIsCheap.  Simplest way to guarantee
    
    1010
    +Note [Nested binding invariants] is to use the same function!
    
    1012 1011
     
    
    1013 1012
     If an expression is okay for speculation, we could also float it out
    
    1014 1013
     *without* boxing and unboxing, since evaluating it early is okay.
    

  • compiler/GHC/Core/Opt/Simplify/Env.hs
    ... ... @@ -749,8 +749,8 @@ 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 let-can-float invariant
    
    753
    -  NonRec x# (f y)       FltCareful  -- Might diverge; does not satisfy let-can-float invariant
    
    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]
    
    754 754
     -}
    
    755 755
     
    
    756 756
     data LetFloats = LetFloats (OrdList OutBind) FloatFlag
    
    ... ... @@ -763,7 +763,7 @@ data FloatFlag
    763 763
       = FltLifted   -- All bindings are lifted and lazy *or*
    
    764 764
                     --     consist of a single primitive string literal
    
    765 765
                     -- Hence ok to float to top level, or recursive
    
    766
    -                -- NB: consequence: all bindings satisfy let-can-float invariant
    
    766
    +                -- NB: consequence: all bindings satisfy Note [Nested binding invariants]
    
    767 767
     
    
    768 768
       | FltOkSpec   -- All bindings are FltLifted *or*
    
    769 769
                     --      strict (perhaps because unlifted,
    
    ... ... @@ -772,12 +772,12 @@ data FloatFlag
    772 772
                     -- Hence ok to float out of the RHS
    
    773 773
                     -- of a lazy non-recursive let binding
    
    774 774
                     -- (but not to top level, or into a rec group)
    
    775
    -                -- NB: consequence: all bindings satisfy let-can-float invariant
    
    775
    +                -- NB: consequence: all bindings satisfy Note [Nested binding invariants]
    
    776 776
     
    
    777 777
       | FltCareful  -- At least one binding is strict (or unlifted)
    
    778 778
                     --      and not guaranteed cheap
    
    779 779
                     -- Do not float these bindings out of a lazy let!
    
    780
    -                -- NB: some bindings may not satisfy let-can-float
    
    780
    +                -- NB: some bindings may not satisfy Note [Nested binding invariants]
    
    781 781
     
    
    782 782
     instance Outputable LetFloats where
    
    783 783
       ppr (LetFloats binds ff) = ppr ff $$ ppr (fromOL binds)
    
    ... ... @@ -962,8 +962,8 @@ wrapFloats (SimplFloats { sfLetFloats = LetFloats bs flag
    962 962
          -- Note: Always safe to put the joins on the inside
    
    963 963
          -- since the values can't refer to them
    
    964 964
       where
    
    965
    -    mk_let | FltCareful <- flag = mkCoreLet -- need to enforce let-can-float-invariant
    
    966
    -           | otherwise          = Let       -- let-can-float invariant hold
    
    965
    +    mk_let | FltCareful <- flag = mkCoreLet -- Need to enforce Note [Nested binding invariants]
    
    966
    +           | otherwise          = Let       -- Note [Nested binding invariants] holds
    
    967 967
     
    
    968 968
     wrapJoinFloatsX :: SimplFloats -> OutExpr -> (SimplFloats, OutExpr)
    
    969 969
     -- Wrap the sfJoinFloats of the env around the expression,
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -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 the let-can-float invariant
    
    318
    +-- Precondition: rhs obeys Note [Nested 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 the let-can-float invariant
    
    400
    +-- Precondition: rhs satisfies Note [Nested 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 the let-can-float invariant
    
    953
    +-- Precondition: rhs obeys Note [Nested 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 the let-can-float invariant, it's ok to
    
    1293
    +    -- Because of Note [Nested 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
    -                                   -- (the let-can-float invariant may not be satisfied)
    
    1597
    +                                   -- (Note [Nested 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 the let-can-float-invariant
    
    1603
    +  , needsCaseBindingL arg_levity rhs -- Enforcing Note [Nested 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 the let-can-float invariant
    
    1890
    +-- from_what=FromLet => the RHS satisfies Note [Nested 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
    
    ... ... @@ -1910,7 +1910,7 @@ simplNonRecE env from_what bndr (rhs, rhs_se) body cont
    1910 1910
         is_strict_bind = case from_what of
    
    1911 1911
            FromBeta Unlifted -> True
    
    1912 1912
            -- If we are coming from a beta-reduction (FromBeta) we must
    
    1913
    -       -- establish the let-can-float invariant, so go via StrictBind
    
    1913
    +       -- establish Note [Nested 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 the let-can-float invariant).
    
    2860
    +  (ok-for-spec is needed to satisfy Note [Nested 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 let-can-float invariant
    
    3115
    +             -- hence satisfies Note [Nested binding invariants]
    
    3116 3116
              ; (floats2, expr') <- simplExprF env' rhs cont
    
    3117 3117
              ; case wfloats of
    
    3118 3118
                  [] -> return (floats1 `addFloats` floats2, expr')
    
    ... ... @@ -3624,11 +3624,11 @@ 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 the let-can-float invariant.  Example
    
    3627
    +then Lint may complain about failing Note [Nested binding invariants].  Example
    
    3628 3628
         case e of b { DEFAULT -> let v = reallyUnsafePtrEquality# b y in ....
    
    3629 3629
                     ; K       -> blah }
    
    3630 3630
     
    
    3631
    -The let-can-float invariant requires that y is evaluated in the call to
    
    3631
    +Note [Nested binding invariants] requires that y is evaluated in the call to
    
    3632 3632
     reallyUnsafePtrEquality#, which it is.  But we still want that to be true if we
    
    3633 3633
     propagate binders to occurrences.
    
    3634 3634
     
    
    ... ... @@ -3732,7 +3732,8 @@ knownCon env scrut dc_floats dc dc_ty_args dc_args bndr bs rhs cont
    3732 3732
                  -- occur in the RHS; and simplAuxBind may therefore discard it.
    
    3733 3733
                  -- Nevertheless we must keep it if the case-binder is alive,
    
    3734 3734
                  -- because it may be used in the con_app.  See Note [knownCon occ info]
    
    3735
    -           ; (floats1, env2) <- simplAuxBind "knownCon" env' b' arg  -- arg satisfies let-can-float invariant
    
    3735
    +             -- NB: arg satisfies Note [Nested binding invariants]
    
    3736
    +           ; (floats1, env2) <- simplAuxBind "knownCon" env' b' arg
    
    3736 3737
                ; (floats2, env3) <- bind_args env2 bs' args
    
    3737 3738
                ; return (floats1 `addFloats` floats2, env3) }
    
    3738 3739
     
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -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 the let-can-float invariant
    
    1495
    --- See Note [Core let-can-float invariant] in GHC.Core
    
    1494
    +-- Precondition: rhs satisfies Note [Nested binding invariants]
    
    1495
    +-- See Note [Nested 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,8 +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 the let-can-float invariant
    
    1642
    --- See Note [Core let-can-float invariant] in GHC.Core
    
    1641
    +-- Precondition: rhs satisfies Note [Nested binding invariants] in GHC.Core
    
    1643 1642
     -- Reason: we don't want to inline single uses, or discard dead bindings,
    
    1644 1643
     --         for unlifted, side-effect-ful bindings
    
    1645 1644
     postInlineUnconditionally env bind_cxt old_bndr bndr rhs
    

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -1944,7 +1944,7 @@ 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 [Core let-can-float invariant] in GHC.Core).
    
    1947
    +Note [Nested binding invariants] in GHC.Core).
    
    1948 1948
     
    
    1949 1949
     
    
    1950 1950
     Note [Specialising Calls]
    

  • compiler/GHC/Core/SimpleOpt.hs
    ... ... @@ -381,7 +381,7 @@ 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 the let-can-float invariant. So simply case-bind it here.
    
    384
    +        -- due to Note [Nested binding invariants]. So simply case-bind it here.
    
    385 385
           , let a' = simple_opt_clo (soeInScope env) a
    
    386 386
           = mkDefaultCase a' b' $ do_beta env' body as
    
    387 387
     
    

  • compiler/GHC/Core/TyCo/FVs.hs
    ... ... @@ -350,7 +350,8 @@ deepTcvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and synon
    350 350
       where
    
    351 351
         do_tcv is v = EndoOS do_it
    
    352 352
           where
    
    353
    -        do_it acc | not (isLocalVar v) = acc
    
    353
    +        do_it acc | not (isLocalVar v) = acc  -- A CoVar can be a GlobalId
    
    354
    +                               -- See Note [Coercion bindings] in GHC.Core
    
    354 355
                       | v `elemVarSet` is  = acc
    
    355 356
                       | v `elemVarSet` acc = acc
    
    356 357
                       | otherwise          = appEndoOS (deep_ty (varType v)) $
    

  • compiler/GHC/Core/TyCo/Subst.hs
    ... ... @@ -1040,7 +1040,7 @@ substTyCoBndr subst (Named (Bndr tv vis)) = (subst', Named (Bndr tv' vis))
    1040 1040
     {- Note [Keeping the substitution empty]
    
    1041 1041
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1042 1042
     A very common situation is where we run over a term doing no cloning,
    
    1043
    -no substitution, nothing.  In that case the TCvSubst till be empty, and
    
    1043
    +no substitution, nothing.  In that case the TCvSubst will be empty, and
    
    1044 1044
     it is /very/ valuable to /keep/ it empty:
    
    1045 1045
     
    
    1046 1046
     * It's wasted effort to build up an identity substitution mapping
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -1813,13 +1813,11 @@ exprIsUnaryClassFun _ = False
    1813 1813
     -- See also Note [Classifying primop effects] in "GHC.Builtin.PrimOps"
    
    1814 1814
     -- and Note [Transformations affected by primop effects].
    
    1815 1815
     --
    
    1816
    --- 'exprOkForSpeculation' is used to define Core's let-can-float
    
    1817
    --- invariant.  (See Note [Core let-can-float invariant] in
    
    1818
    --- "GHC.Core".)  It is therefore frequently called on arguments of
    
    1819
    --- unlifted type, especially via 'needsCaseBinding'.  But it is
    
    1820
    --- sometimes called on expressions of lifted type as well.  For
    
    1821
    --- example, see Note [Speculative evaluation] in "GHC.CoreToStg.Prep".
    
    1822
    -
    
    1816
    +-- 'exprOkForSpeculation' is used in the definition of Note [Nested binding
    
    1817
    +-- invariants]in GHC.Core.  It is therefore frequently called on arguments of
    
    1818
    +-- unlifted type, especially via 'needsCaseBinding'.  But it is sometimes
    
    1819
    +-- called on expressions of lifted type as well.  For example, see
    
    1820
    +-- Note [Speculative evaluation] in "GHC.CoreToStg.Prep".
    
    1823 1821
     
    
    1824 1822
     exprOkForSpeculation, exprOkToDiscard :: CoreExpr -> Bool
    
    1825 1823
     exprOkForSpeculation = expr_ok fun_always_ok primOpOkForSpeculation
    
    ... ... @@ -2044,12 +2042,14 @@ But we restrict it sharply:
    2044 2042
                                                    ; False -> e2 }
    
    2045 2043
                            in ...) ...
    
    2046 2044
     
    
    2047
    -  Does the RHS of v satisfy the let-can-float invariant?  Previously we said
    
    2048
    -  yes, on the grounds that y is evaluated.  But the binder-swap done
    
    2049
    -  by GHC.Core.Opt.SetLevels would transform the inner alternative to
    
    2045
    +  Does the RHS of v satisfy Note [Nested binding invariants]?
    
    2046
    +  Previously we said yes, on the grounds that y is evaluated.  But the
    
    2047
    +  binder-swap done by GHC.Core.Opt.SetLevels would transform the inner
    
    2048
    +  alternative to
    
    2049
    +
    
    2050 2050
          DEFAULT -> ... (let v::Int# = case x of { ... }
    
    2051 2051
                          in ...) ....
    
    2052
    -  which does /not/ satisfy the let-can-float invariant, because x is
    
    2052
    +  which does /not/ satisfy Note [Nested bindings invariants], because x is
    
    2053 2053
       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
    
    ... ... @@ -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 the let-can-float invariant.
    
    2137
    +and then it really, really doesn't obey Note [Nested 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,8 @@ 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 the let-can-float invariant to worry about.
    
    2147
    +it doesn't have the trickiness of Note [Nested binding invariants]
    
    2148
    +to worry about.
    
    2148 2149
     
    
    2149 2150
     ************************************************************************
    
    2150 2151
     *                                                                      *
    

  • compiler/GHC/Stg/Lint.hs
    ... ... @@ -5,9 +5,8 @@ A lint pass to check basic STG invariants:
    5 5
     
    
    6 6
     - Variables should be defined before used.
    
    7 7
     
    
    8
    -- Let bindings should not have unboxed types (unboxed bindings should only
    
    9
    -  appear in case), except when they're join points (see Note [Core let-can-float
    
    10
    -  invariant] and #14117).
    
    8
    +- Let bindings: see Note [Core binding invariants] in GHC.Core.
    
    9
    +  (See #14117).
    
    11 10
     
    
    12 11
     - If linting after unarisation, invariants listed in Note [Post-unarisation
    
    13 12
       invariants].