Simon Peyton Jones pushed to branch wip/case-bndr-unf at Glasgow Haskell Compiler / GHC

Commits:

10 changed files:

Changes:

  • changelog.d/T27962
    1
    +section: compiler
    
    2
    +issues: #27962
    
    3
    +mrs: !16869
    
    4
    +synopsis:
    
    5
    +  Fix a Lint error when using `runRW#` and `coerce` together
    
    6
    +description:
    
    7
    +  Just an internal compiler bug, of long standing.

  • changelog.d/T27963
    1
    +section: compiler
    
    2
    +issues: #27963
    
    3
    +mrs: !16869
    
    4
    +synopsis:
    
    5
    +  Fix a rather obscure interaction of `coerce` and RULES
    
    6
    +description:
    
    7
    +  A `coerce` could prevent a RULE firing.

  • compiler/GHC/Core/Opt/Simplify/Env.hs
    ... ... @@ -28,7 +28,7 @@ module GHC.Core.Opt.Simplify.Env (
    28 28
             SimplEnvIS,  checkSimplEnvIS, pprBadSimplEnvIS,
    
    29 29
     
    
    30 30
             -- * Substitution results
    
    31
    -        SimplSR(..), substId, lookupRecBndr,
    
    31
    +        SimplClo(..), simplCloExpr, substId, lookupRecBndr,
    
    32 32
     
    
    33 33
             -- * Simplifying 'Id' binders
    
    34 34
             simplNonRecBndr, simplNonRecJoinBndr, simplRecBndrs, simplRecJoinBndrs,
    
    ... ... @@ -61,7 +61,7 @@ import GHC.Core.Opt.Simplify.Monad
    61 61
     import GHC.Core.Rules.Config ( RuleOpts(..) )
    
    62 62
     import GHC.Core
    
    63 63
     import GHC.Core.Utils
    
    64
    -import GHC.Core.Subst( substExprSC )
    
    64
    +import GHC.Core.Subst( substExpr )
    
    65 65
     import GHC.Core.Unfold
    
    66 66
     import GHC.Core.TyCo.Subst (emptyIdSubstEnv, mkSubst)
    
    67 67
     import GHC.Core.Multiplicity( Scaled(..), mkMultMul )
    
    ... ... @@ -470,18 +470,26 @@ pprSimplEnv env
    470 470
        ppr_one v | isId v = ppr v <+> ppr (idUnfolding v)
    
    471 471
                  | otherwise = ppr v
    
    472 472
     
    
    473
    -type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
    
    473
    +type SimplIdSubst = IdEnv SimplClo -- IdId |--> OutExpr
    
    474 474
             -- See Note [Extending the IdSubstEnv] in GHC.Core.Subst
    
    475 475
     
    
    476
    --- | A substitution result.
    
    477
    -data SimplSR
    
    476
    +-- | A "closure" used in the Simplifier.  It is used
    
    477
    +--     * as the range of the substitution, 'SimplIdSubst'
    
    478
    +--     * as the argument in an 'ApplyToVal' continuation
    
    479
    +-- Roughly: either an (InExpr, StaticEnv) pair for an
    
    480
    +--                 as-yet-unsimplified expression
    
    481
    +--          or     an OutExpr, for an already-simplified one
    
    482
    +-- It's a bit like thunk: we may "evaluate" the SimplClo in a ApplyToVal
    
    483
    +--   and thereby transform it from `ContEx` to `DoneEx`
    
    484
    +--   This happens in the `ApplyToVal` case of `mkDupableContWithDmds`
    
    485
    +--   See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils
    
    486
    +data SimplClo
    
    478 487
       = DoneEx OutExpr JoinPointHood
    
    479 488
            -- If  x :-> DoneEx e ja   is in the SimplIdSubst
    
    480 489
            -- then replace occurrences of x by e
    
    481 490
            -- and  ja = Just a <=> x is a join-point of arity a
    
    482 491
            -- See Note [Join arity in SimplIdSubst]
    
    483 492
     
    
    484
    -
    
    485 493
       | DoneId OutId
    
    486 494
            -- If  x :-> DoneId v   is in the SimplIdSubst
    
    487 495
            -- then replace occurrences of x by v
    
    ... ... @@ -490,11 +498,11 @@ data SimplSR
    490 498
     
    
    491 499
       | ContEx SimplEnv
    
    492 500
                InExpr
    
    493
    -           MOutCoercion  -- See Note [The sc_cast field of ApplyToVal]
    
    501
    +           MOutCoercion  -- See Note [The MOutCoercion field of ContEx]
    
    494 502
           -- If   x :-> ContEx static_env e mco   is in the SimplISubst
    
    495 503
           -- then replace occurrences of x by (subst static_env e) |> mco
    
    496 504
     
    
    497
    -instance Outputable SimplSR where
    
    505
    +instance Outputable SimplClo where
    
    498 506
       ppr (DoneId v)    = text "DoneId" <+> ppr v
    
    499 507
       ppr (DoneEx e mj) = text "DoneEx" <> pp_mj <+> ppr e
    
    500 508
         where
    
    ... ... @@ -637,7 +645,7 @@ reSimplifying :: SimplEnv -> Bool
    637 645
     reSimplifying (SimplEnv { seInlineDepth = n }) = n>0
    
    638 646
     
    
    639 647
     ---------------------
    
    640
    -extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
    
    648
    +extendIdSubst :: SimplEnv -> Id -> SimplClo -> SimplEnv
    
    641 649
     extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
    
    642 650
       = assertPpr (isId var && not (isCoVar var)) (ppr var) $
    
    643 651
         env { seIdSubst = extendVarEnv subst var res }
    
    ... ... @@ -1032,7 +1040,7 @@ So we want to look up the inner X.g_34 in the substitution, where we'll
    1032 1040
     find that it has been substituted by b.  (Or conceivably cloned.)
    
    1033 1041
     -}
    
    1034 1042
     
    
    1035
    -substId :: SimplEnv -> InId -> SimplSR
    
    1043
    +substId :: SimplEnv -> InId -> SimplClo
    
    1036 1044
     -- Returns DoneEx only on a non-Var expression
    
    1037 1045
     substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
    
    1038 1046
       = case lookupVarEnv ids v of  -- Note [Global Ids in the substitution]
    
    ... ... @@ -1364,15 +1372,18 @@ getTCvSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seCvSubst = cv
    1364 1372
     
    
    1365 1373
     getFullSubst :: InScopeSet -> SimplEnv -> Subst
    
    1366 1374
     getFullSubst in_scope (SimplEnv { seIdSubst = id_env, seTvSubst = tv_env, seCvSubst = cv_env })
    
    1367
    -  = mkSubst in_scope (mapVarEnv to_expr id_env) tv_env cv_env
    
    1375
    +  = mkSubst in_scope (mapVarEnv (simplCloExpr in_scope) id_env) tv_env cv_env
    
    1376
    +
    
    1377
    +simplCloExpr :: InScopeSet -> SimplClo -> OutExpr
    
    1378
    +-- Turn a SimplClo into an OutExpr, by applying the substitution
    
    1379
    +-- (if any) and the pending cast (if any)
    
    1380
    +simplCloExpr _        (DoneEx e _)       = e
    
    1381
    +simplCloExpr _        (DoneId v)         = Var v
    
    1382
    +simplCloExpr in_scope (ContEx env e mco) = mkCastMCo e' mco
    
    1368 1383
       where
    
    1369
    -    to_expr :: SimplSR -> CoreExpr
    
    1370
    -    -- A tiresome impedence-matcher
    
    1371
    -    to_expr (DoneEx e _)       = e
    
    1372
    -    to_expr (DoneId v)         = Var v
    
    1373
    -    to_expr (ContEx env e mco) = mkCastMCo e' mco
    
    1374
    -      where
    
    1375
    -        e' = GHC.Core.Subst.substExprSC (getFullSubst in_scope env) e
    
    1384
    +    e' = GHC.Core.Subst.substExpr (getFullSubst in_scope env) e
    
    1385
    +    -- NB: we use substExpr, not substExprSC: we want to get the benefit of
    
    1386
    +    --     knowing what is evaluated etc, via the in-scope set
    
    1376 1387
     
    
    1377 1388
     substTy :: HasDebugCallStack => SimplEnv -> Type -> Type
    
    1378 1389
     substTy env ty = Type.substTy (getTCvSubst env) ty
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -285,8 +285,8 @@ simplRecOrTopPair :: SimplEnv
    285 285
                       -> SimplM (SimplFloats, SimplEnv)
    
    286 286
     
    
    287 287
     simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
    
    288
    -  | Just env' <- preInlineUnconditionally env (bindContextLevel bind_cxt)
    
    289
    -                                          old_bndr (UnSimplified env) rhs MRefl
    
    288
    +  | Just env' <- preInlineLetUnconditionally env (bindContextLevel bind_cxt)
    
    289
    +                                             old_bndr rhs env
    
    290 290
       = {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
    
    291 291
         simplTrace "SimplBindr:inline-uncond1" (ppr old_bndr) $
    
    292 292
         do { tick (PreInlineUnconditionally old_bndr)
    
    ... ... @@ -1226,17 +1226,8 @@ simplExprF1 env (Tick t expr) cont = {-#SCC "simplTick" #-} simplTick env t exp
    1226 1226
     simplExprF1 env (Coercion co)  cont = {-#SCC "simplCoercionF" #-} simplCoercionF env co cont
    
    1227 1227
     
    
    1228 1228
     simplExprF1 env (Cast body co) cont
    
    1229
    -  = do  { co1 <- {-#SCC "simplCast-simplCoercion" #-}
    
    1230
    -                 simplCoercion env co
    
    1231
    -
    
    1232
    -        ; let cont1 = {-#SCC "simplCast-addCoerce" #-}
    
    1233
    -                      if isReflCo co1
    
    1234
    -                      then cont  -- See Note [Optimising reflexivity]
    
    1235
    -                      else pushCast env co1 cont
    
    1236
    -                           -- True <=> co1 is optimised
    
    1237
    -
    
    1238
    -        ; {-#SCC "simplCast-simplExprF" #-}
    
    1239
    -          simplExprF env body cont1 }
    
    1229
    +  = do  { co1 <- simplCoercion env co
    
    1230
    +        ; simplExprF env body (pushCast env co1 cont) }
    
    1240 1231
     
    
    1241 1232
     simplExprF1 env (App fun arg) cont
    
    1242 1233
       = {-#SCC "simplExprF1-App" #-} case arg of
    
    ... ... @@ -1264,9 +1255,9 @@ simplExprF1 env (App fun arg) cont
    1264 1255
               -- observed the quadratic behavior, so this extra entanglement
    
    1265 1256
               -- seems not worthwhile.
    
    1266 1257
             simplExprF env fun $
    
    1267
    -        ApplyToVal { sc_arg = arg, sc_env = UnSimplified env
    
    1258
    +        ApplyToVal { sc_arg = ContEx env arg MRefl, sc_dup = NoDup
    
    1268 1259
                        , sc_hole_ty = substTy env (exprType fun)
    
    1269
    -                   , sc_cast = MRefl, sc_cont = cont }
    
    1260
    +                   , sc_cont = cont }
    
    1270 1261
     
    
    1271 1262
     simplExprF1 env expr@(Lam {}) cont
    
    1272 1263
       = {-#SCC "simplExprF1-Lam" #-}
    
    ... ... @@ -1301,7 +1292,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont
    1301 1292
         do { ty' <- simplType env ty
    
    1302 1293
            ; simplExprF (extendTvSubst env bndr ty') body cont }
    
    1303 1294
     
    
    1304
    -  | Just env' <- preInlineUnconditionally env NotTopLevel bndr (UnSimplified env) rhs MRefl
    
    1295
    +  | Just env' <- preInlineLetUnconditionally env NotTopLevel bndr rhs env
    
    1305 1296
         -- Because of the let-can-float invariant, it's ok to
    
    1306 1297
         -- inline freely, or to drop the binding if it is dead.
    
    1307 1298
       = do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr) $
    
    ... ... @@ -1637,9 +1628,8 @@ rebuild_go env expr cont
    1637 1628
           ApplyToTy  { sc_arg_ty = ty, sc_cont = cont}
    
    1638 1629
             -> rebuild_go env (App expr (Type ty)) cont
    
    1639 1630
     
    
    1640
    -      ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
    
    1641
    -                 , sc_cont = cont, sc_hole_ty = fun_ty }
    
    1642
    -        -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
    
    1631
    +      ApplyToVal { sc_arg = arg, sc_cont = cont, sc_hole_ty = fun_ty }
    
    1632
    +        -> do { arg' <- simplArg env Nothing fun_ty arg
    
    1643 1633
                   ; rebuild_go env (App expr arg') cont }
    
    1644 1634
     
    
    1645 1635
     completeBindX :: SimplEnv
    
    ... ... @@ -1687,69 +1677,12 @@ completeBindX env from_what bndr rhs body cont
    1687 1677
             ; let all_floats = rhs_floats `addFloats` bind_float `addFloats` body_floats
    
    1688 1678
             ; return ( all_floats, body' ) }
    
    1689 1679
     
    
    1690
    -{-
    
    1691
    -************************************************************************
    
    1680
    +
    
    1681
    +{- *********************************************************************
    
    1692 1682
     *                                                                      *
    
    1693
    -\subsection{Lambdas}
    
    1683
    +                Arguments
    
    1694 1684
     *                                                                      *
    
    1695
    -************************************************************************
    
    1696
    --}
    
    1697
    -
    
    1698
    -{- Note [Optimising reflexivity]
    
    1699
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1700
    -It's important (for compiler performance) to get rid of reflexivity as soon
    
    1701
    -as it appears.  See #11735, #14737, and #15019.
    
    1702
    -
    
    1703
    -In particular, we want to behave well on
    
    1704
    -
    
    1705
    - *  e |> co1 |> co2
    
    1706
    -    where the two happen to cancel out entirely. That is quite common;
    
    1707
    -    e.g. a newtype wrapping and unwrapping cancel.
    
    1708
    -
    
    1709
    -
    
    1710
    - * (f |> co) @t1 @t2 ... @tn x1 .. xm
    
    1711
    -   Here we will use pushCoTyArg and pushCoValArg successively, which
    
    1712
    -   build up SelCo stacks.  Silly to do that if co is reflexive.
    
    1713
    -
    
    1714
    -However, we don't want to call isReflexiveCo too much, because it uses
    
    1715
    -type equality which is expensive on big types (#14737 comment:7).
    
    1716
    -
    
    1717
    -A good compromise (determined experimentally) seems to be to call
    
    1718
    -isReflexiveCo
    
    1719
    - * when composing casts, and
    
    1720
    - * at the end
    
    1721
    -
    
    1722
    -In investigating this I saw missed opportunities for on-the-fly
    
    1723
    -coercion shrinkage. See #15090.
    
    1724
    -
    
    1725
    -Note [Avoid re-simplifying coercions]
    
    1726
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1727
    -In some benchmarks (with deeply nested cases) we successively push
    
    1728
    -casts onto the SimplCont.  We don't want to call the coercion optimiser
    
    1729
    -on each successive composition -- that's at least quadratic.  So:
    
    1730
    -
    
    1731
    -* The CastIt constructor in SimplCont has a `sc_opt :: Bool` flag to
    
    1732
    -  record whether the coercion optimiser has been applied to the coercion.
    
    1733
    -
    
    1734
    -* In `simplCast`, when we see (Cast e co), we simplify `co` to get
    
    1735
    -  an OutCoercion, and built a CastIt with sc_opt=True.
    
    1736
    -
    
    1737
    -  Actually not quite: if we are simplifying the result of inlining an
    
    1738
    -  unfolding (seInlineDepth > 0), then instead of /optimising/ it again,
    
    1739
    -  just /substitute/ which is cheaper.  See `simplCoercion`.
    
    1740
    -
    
    1741
    -* In `pushCast` if we combine this new coercion with an existing one,
    
    1742
    -  we build a CastIt for (co1 ; co2) with sc_opt=False.
    
    1743
    -
    
    1744
    -* When unpacking a CastIt, in `rebuild`, we optimise the (presumably
    
    1745
    -  composed) coercion if sc_opt=False; this is done by `optOutCoercion`.
    
    1746
    -
    
    1747
    -* When duplicating a continuation in `mkDupableContWithDmds`, before
    
    1748
    -  duplicating a CastIt, optimise the coercion. Otherwise we'll end up
    
    1749
    -  optimising it separately in the duplicate copies.
    
    1750
    -
    
    1751
    -* See also Note [The sc_cast field of ApplyToVal] in GHC.Core.Opt.Simplify.Utils.
    
    1752
    --}
    
    1685
    +********************************************************************* -}
    
    1753 1686
     
    
    1754 1687
     simplArg :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1755 1688
              -> Maybe ArgInfo           -- ^ Just <=> This arg `ai` occurs in an app
    
    ... ... @@ -1757,15 +1690,12 @@ simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet
    1757 1690
                                         --   how `f` uses `ai`, affecting the Stop
    
    1758 1691
                                         --   continuation passed to 'simplExprC'
    
    1759 1692
              -> OutType                 -- ^ Type of the function applied to this arg
    
    1760
    -         -> StaticEnv -> CoreExpr   -- ^ Expression with its static envt
    
    1761
    -         -> MOutCoercion            -- Wrap this around the result
    
    1693
    +         -> SimplClo                -- ^ The argument
    
    1762 1694
              -> SimplM OutExpr
    
    1763
    -simplArg _ _ _ (Simplified {}) arg mco
    
    1764
    -  = -- See Note [Avoid repeated simplification]
    
    1765
    -    case mco of
    
    1766
    -       MRefl  -> return arg       -- Vastly common case
    
    1767
    -       MCo co -> return (mkCast arg co)
    
    1768
    -simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco
    
    1695
    +-- See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils
    
    1696
    +simplArg _ _ _ (DoneEx arg _) = return arg  -- See Note [Avoid repeated simplification]
    
    1697
    +simplArg _ _ _ (DoneId v)     = return (Var v)
    
    1698
    +simplArg env mb_arg_info fun_ty (ContEx arg_se arg mco)
    
    1769 1699
       = do { let arg_env' = arg_se `setInScopeFromE` env
    
    1770 1700
                  arg_ty   = funArgTy fun_ty
    
    1771 1701
                  stop     = case mb_arg_info of
    
    ... ... @@ -1774,13 +1704,12 @@ simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco
    1774 1704
                  cont     = addCastMCo mco stop
    
    1775 1705
            ; simplExprC arg_env' arg cont }
    
    1776 1706
     
    
    1777
    -{-
    
    1778
    -************************************************************************
    
    1707
    +
    
    1708
    +{- *********************************************************************
    
    1779 1709
     *                                                                      *
    
    1780
    -\subsection{Lambdas}
    
    1710
    +                Lambdas
    
    1781 1711
     *                                                                      *
    
    1782
    -************************************************************************
    
    1783
    --}
    
    1712
    +********************************************************************* -}
    
    1784 1713
     
    
    1785 1714
     simplNonRecBody :: SimplEnv -> FromWhat
    
    1786 1715
                     -> InExpr -> SimplCont
    
    ... ... @@ -1807,13 +1736,9 @@ simpl_lam env bndr body (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = cont })
    1807 1736
     
    
    1808 1737
     -- Value beta-reduction
    
    1809 1738
     -- This works for /coercion/ lambdas too
    
    1810
    -simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1811
    -                                    , sc_cast = arg_mco, sc_cont = cont
    
    1739
    +simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_cont = cont
    
    1812 1740
                                         , sc_hole_ty = fun_ty})
    
    1813
    -  | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg_se arg arg_mco
    
    1814
    -  , not (needsCaseBindingL arg_levity arg)
    
    1815
    -              -- Ok to test arg::InExpr in needsCaseBinding because
    
    1816
    -              -- exprOkForSpeculation is stable under simplification
    
    1741
    +  | Just env' <- preInlineBetaUnconditionally env arg_levity bndr arg
    
    1817 1742
       = simplTrace "SimplBindr:inline-uncond3"
    
    1818 1743
              (ppr bndr <+> text ":=" <+> ppr arg) $
    
    1819 1744
         do { tick (BetaReduction bndr)
    
    ... ... @@ -1824,14 +1749,14 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
    1824 1749
       = do { tick (BetaReduction bndr)
    
    1825 1750
            ; let from_what = FromBeta arg_levity
    
    1826 1751
     
    
    1827
    -       ; case (arg_se, arg_mco) of
    
    1828
    -           (UnSimplified arg_env, MRefl)
    
    1752
    +       ; case arg of
    
    1753
    +           ContEx arg_env arg_expr MRefl
    
    1829 1754
                  -- Optimisation: when there is no wrapping coercion use simplNonRecE
    
    1830 1755
                  -- so that the clever floating out of let-bindings can take place
    
    1831 1756
                  -- in this round of the Simplifier
    
    1832
    -             -> simplNonRecE env from_what bndr (arg, arg_env) body cont
    
    1757
    +             -> simplNonRecE env from_what bndr (arg_expr, arg_env) body cont
    
    1833 1758
     
    
    1834
    -           _ -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
    
    1759
    +           _ -> do { arg' <- simplArg env Nothing fun_ty arg
    
    1835 1760
                        ; completeBindX env from_what bndr arg' body cont }
    
    1836 1761
            }
    
    1837 1762
       where
    
    ... ... @@ -2295,11 +2220,14 @@ simplOutId env fun cont
    2295 2220
       | fun `hasKey` runRWKey
    
    2296 2221
       , ApplyToTy  { sc_cont = cont1 } <- cont
    
    2297 2222
       , ApplyToTy  { sc_cont = cont2, sc_arg_ty = hole_ty } <- cont1
    
    2298
    -  , ApplyToVal { sc_cont = cont3, sc_arg = arg, sc_cast = arg_mco
    
    2299
    -               , sc_env = arg_se, sc_hole_ty = fun_ty } <- cont2
    
    2223
    +  , ApplyToVal { sc_cont = cont3, sc_arg = arg_clo, sc_hole_ty = fun_ty } <- cont2
    
    2300 2224
       -- Do this even if (contIsStop cont), or if seCaseCase is off.
    
    2301 2225
       -- See Note [No eta-expansion in runRW#]
    
    2302
    -  = do { let (_saf,arg_env) = mkAltEnv env arg_se
    
    2226
    +  = do { let (arg_env, arg, arg_mco)
    
    2227
    +                = case arg_clo of
    
    2228
    +                    ContEx se e mco -> (se `setInScopeFromE` env, e, mco)
    
    2229
    +                    DoneEx e _      -> (env, e,     MRefl)
    
    2230
    +                    DoneId v        -> (env, Var v, MRefl)
    
    2303 2231
     
    
    2304 2232
                  overall_res_ty = contResultType cont3
    
    2305 2233
                  -- hole_ty is the type of the current runRW# application
    
    ... ... @@ -2314,23 +2242,32 @@ simplOutId env fun cont
    2314 2242
            --    * If we don't do this we get a beta-redex every time, so the
    
    2315 2243
            --      simplifier keeps doing more iterations.
    
    2316 2244
            --    * Even more important: see Note [No eta-expansion in runRW#]
    
    2245
    +       --
    
    2246
    +       -- But only if there is no pending cast on the argument (#27962);
    
    2247
    +       -- if there is, the general case below deals with it properly
    
    2317 2248
            ; arg' <- case arg of
    
    2318
    -           Lam s body -> do { (env', s') <- simplBinder arg_env s
    
    2319
    -                            ; body' <- simplExprC env' body inner_cont
    
    2320
    -                            ; return (Lam s' body') }
    
    2321
    -                            -- Important: do not try to eta-expand this lambda
    
    2322
    -                            -- See Note [No eta-expansion in runRW#]
    
    2249
    +           Lam s body
    
    2250
    +             | MRefl <- arg_mco
    
    2251
    +             -> do { (env', s') <- simplBinder arg_env s
    
    2252
    +                   ; body' <- simplExprC env' body inner_cont
    
    2253
    +                   ; return (Lam s' body') }
    
    2254
    +                   -- Important: do not try to eta-expand this lambda
    
    2255
    +                   -- See Note [No eta-expansion in runRW#]
    
    2323 2256
     
    
    2324 2257
                _ -> do { s' <- newId (fsLit "s") ManyTy realWorldStatePrimTy
    
    2325 2258
                        ; let (m,_,_) = splitFunTy fun_ty
    
    2326 2259
                              env'  = arg_env `addNewInScopeIds` [s']
    
    2327 2260
                              hole_ty = mkVisFunTy m realWorldStatePrimTy new_runrw_res_ty
    
    2328 2261
                              cont' = pushCastMCo env' arg_mco $
    
    2329
    -                                 ApplyToVal { sc_arg = Var s', sc_cast = MRefl
    
    2330
    -                                            , sc_env = Simplified OkDup
    
    2262
    +                                 ApplyToVal { sc_arg  = DoneId s'
    
    2263
    +                                            , sc_dup  = dup
    
    2331 2264
                                                 , sc_cont = inner_cont
    
    2332 2265
                                                 , sc_hole_ty = hole_ty }
    
    2333 2266
                                      -- cont' applies to s', then K
    
    2267
    +                         -- The argument (Var s') is small, but inner_cont may not be
    
    2268
    +                         -- dupable; see (AV2) in Note [The argument of ApplyToVal]
    
    2269
    +                         dup | contIsDupable inner_cont = OkDup
    
    2270
    +                             | otherwise                = NoDup
    
    2334 2271
                        ; body' <- simplExprC env' arg cont'
    
    2335 2272
                        ; return (Lam s' body') }
    
    2336 2273
     
    
    ... ... @@ -2397,13 +2334,12 @@ rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_c
    2397 2334
     
    
    2398 2335
     ---------- Simplify value arguments --------------------
    
    2399 2336
     rebuildCall env fun_info
    
    2400
    -            (ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
    
    2401
    -                        , sc_hole_ty = fun_ty, sc_cont = cont })
    
    2402
    -  | UnSimplified arg_env <- arg_se
    
    2337
    +            (ApplyToVal { sc_arg = arg, sc_hole_ty = fun_ty, sc_cont = cont })
    
    2338
    +  | ContEx arg_env arg_expr arg_mco <- arg
    
    2403 2339
       , isStrictArgInfo fun_info  -- Strict arguments
    
    2404 2340
       , seCaseCase env            -- But only when case-of-case is on.
    
    2405 2341
                                   -- See Note [Case-of-case and full laziness]
    
    2406
    -  = simplExprF (arg_env `setInScopeFromE` env) arg $
    
    2342
    +  = simplExprF (arg_env `setInScopeFromE` env) arg_expr $
    
    2407 2343
         addCastMCo arg_mco $
    
    2408 2344
         StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
    
    2409 2345
                   , sc_dup = NoDup
    
    ... ... @@ -2415,7 +2351,7 @@ rebuildCall env fun_info
    2415 2351
       -- There is no benefit (unlike in a let-binding), and we'd
    
    2416 2352
       -- have to be very careful about bogus strictness through
    
    2417 2353
       -- floating a demanded let.
    
    2418
    -  = do  { arg' <- simplArg env (Just fun_info) fun_ty arg_se arg arg_mco
    
    2354
    +  = do  { arg' <- simplArg env (Just fun_info) fun_ty arg
    
    2419 2355
             ; rebuildCall env (addValArgTo fun_info  arg' fun_ty) cont }
    
    2420 2356
     
    
    2421 2357
     ---------- No further useful info, revert to generic rebuild ------------
    
    ... ... @@ -2563,11 +2499,11 @@ Then
    2563 2499
      * We simplify BIG before trying the rule; but the rule does not fire
    
    2564 2500
        (forcing this simplification is why we have the RULE in this example)
    
    2565 2501
      * We inline f = \x. g x, in `simpl_lam`
    
    2566
    - * So if `simpl_lam` did preInlineUnconditionally we get (g BIG)
    
    2502
    + * So if `simpl_lam` did preInlineBetaUnconditionally we get (g BIG)
    
    2567 2503
      * Now if g has a RULE we'll simplify BIG again, and this whole thing can
    
    2568 2504
        iterate.
    
    2569 2505
      * However, if `f` did not have a RULE, so that BIG has /not/ already been
    
    2570
    -   simplified, we /want/ to do preInlineUnconditionally in simpl_lam.
    
    2506
    +   simplified, we /want/ to do preInlineBetaUnconditionally in simpl_lam.
    
    2571 2507
     
    
    2572 2508
     So we go to some effort to avoid repeatedly simplifying the same thing.
    
    2573 2509
     Suppose we are in the Plan (AFTER) case of rule application, for a rule
    
    ... ... @@ -2576,8 +2512,9 @@ and a call
    2576 2512
           f (e1,e2)
    
    2577 2513
     Then:
    
    2578 2514
     
    
    2579
    -* The (sc_env :: StaticEnv) field of ApplyToVal records if the argument
    
    2580
    -  has been evaluated.  See Note [StaticEnv] in GHC.Core.Opt.Simplify.Utils.
    
    2515
    +* The (sc_arg :: SimplClo) field of ApplyToVal records if the argument
    
    2516
    +  has been simplified: it is a DoneEx if so, and a ContEx if not.
    
    2517
    +  See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils.
    
    2581 2518
     
    
    2582 2519
     * The rule fires returning
    
    2583 2520
          RuleMatch { rm_rhs = (\x y. ...x..), rm_args = [ e1, e2 ] }
    
    ... ... @@ -2590,17 +2527,17 @@ Then:
    2590 2527
       is the reason that `RuleMatch` separates the two.
    
    2591 2528
     
    
    2592 2529
     * `fireRuleAFTER` uses `pushOutArgs` to push [ e1, e2 ] back onto the
    
    2593
    -  continuation with sc_env=Simplified NoDup.
    
    2530
    +  continuation as (DoneEx e1) and (DoneEx e2).
    
    2594 2531
     
    
    2595 2532
     * Beta-reduction fires (in `simpl_lam`) for the \x.
    
    2596 2533
     
    
    2597 2534
     * Suppose `x` occurs many times.  Then we want to behave like `let x=e1 in ..`,
    
    2598
    -  but we use `simplArg`, which in turn uses that `sc_env` flag to avoid
    
    2535
    +  but we use `simplArg`, which in turn uses the DoneEx to avoid
    
    2599 2536
       re-simplifying `e1`.
    
    2600 2537
     
    
    2601 2538
     * Suppose `x` occurs just once or not at all; then the call to
    
    2602
    -  `preInlineUnconditionally` in `simpl_lam` will fire, and extend the
    
    2603
    -  substitution with
    
    2539
    +  `preInlineBetaUnconditionally` in `simpl_lam` will fire, and extend the
    
    2540
    +  substitution with the very same SimplClo
    
    2604 2541
           x :-> DoneEx e1
    
    2605 2542
     
    
    2606 2543
     * At the /occurrence/ of `x`, the function `simplInId` calls `simplOutExpr`
    
    ... ... @@ -2807,8 +2744,7 @@ trySeqRules in_env scrut rhs cont
    2807 2744
                      , ValArg { as_arg = no_cast_scrut
    
    2808 2745
                               , as_dmd = seqDmd
    
    2809 2746
                               , as_hole_ty = res3_ty } ]
    
    2810
    -    rule_cont = ApplyToVal { sc_env = UnSimplified in_env, sc_arg = rhs
    
    2811
    -                           , sc_cast = MRefl
    
    2747
    +    rule_cont = ApplyToVal { sc_arg = ContEx in_env rhs MRefl, sc_dup = NoDup
    
    2812 2748
                                , sc_cont = cont, sc_hole_ty = res4_ty }
    
    2813 2749
     
    
    2814 2750
         out_args = [Type rhs_rep, Type scrut_ty, Type rhs_ty, no_cast_scrut]
    
    ... ... @@ -3913,8 +3849,8 @@ knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
    3913 3849
             return ( emptyFloats env
    
    3914 3850
                    , extendIdSubst env case_bndr (DoneEx scrut NotJoinPoint))
    
    3915 3851
     
    
    3916
    -      | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr
    
    3917
    -                            (UnSimplified env) con_app MRefl
    
    3852
    +      | Just env' <- preInlineLetUnconditionally env NotTopLevel case_bndr
    
    3853
    +                                                 con_app env
    
    3918 3854
           = return (emptyFloats env', env')
    
    3919 3855
     
    
    3920 3856
           | otherwise
    
    ... ... @@ -4148,8 +4084,7 @@ mkDupableContWithDmds env dmds
    4148 4084
                                         , sc_arg_ty = arg_ty, sc_hole_ty = hole_ty }) }
    
    4149 4085
     
    
    4150 4086
     mkDupableContWithDmds env dmds
    
    4151
    -    (ApplyToVal { sc_arg = arg, sc_env = se, sc_cast = arg_mco
    
    4152
    -                , sc_cont = cont, sc_hole_ty = hole_ty })
    
    4087
    +    (ApplyToVal { sc_arg = arg, sc_cont = cont, sc_hole_ty = hole_ty })
    
    4153 4088
       =     -- e.g.         [...hole...] (...arg...)
    
    4154 4089
             --      ==>
    
    4155 4090
             --              let a = ...arg...
    
    ... ... @@ -4161,12 +4096,12 @@ mkDupableContWithDmds env dmds
    4161 4096
                     expectNonEmpty dmds
    
    4162 4097
             ; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
    
    4163 4098
             ; let env' = env `setInScopeFromF` floats1
    
    4164
    -        ; arg' <- simplArg env' Nothing hole_ty se arg arg_mco
    
    4099
    +        ; arg' <- simplArg env' Nothing hole_ty arg
    
    4165 4100
             ; (let_floats2, triv_arg) <- makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
    
    4166 4101
             ; let all_floats = floats1 `addLetFloats` let_floats2
    
    4167 4102
             ; return ( all_floats
    
    4168
    -                 , ApplyToVal { sc_arg = triv_arg, sc_env = Simplified OkDup
    
    4169
    -                              , sc_cast = MRefl, sc_cont = cont', sc_hole_ty = hole_ty }) }
    
    4103
    +                 , ApplyToVal { sc_arg = DoneEx triv_arg NotJoinPoint, sc_dup = OkDup
    
    4104
    +                              , sc_cont = cont', sc_hole_ty = hole_ty }) }
    
    4170 4105
     
    
    4171 4106
     mkDupableContWithDmds env _
    
    4172 4107
         (Select { sc_bndr = case_bndr, sc_alts = alts, sc_env = se, sc_cont = cont })
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -12,7 +12,8 @@ module GHC.Core.Opt.Simplify.Utils (
    12 12
             tryEtaExpandRhs, wantEtaExpansion,
    
    13 13
     
    
    14 14
             -- Inlining,
    
    15
    -        preInlineUnconditionally, postInlineUnconditionally,
    
    15
    +        preInlineLetUnconditionally, preInlineBetaUnconditionally,
    
    16
    +        postInlineUnconditionally,
    
    16 17
             activeRule,
    
    17 18
             getUnfoldingInRuleMatch,
    
    18 19
             updModeForStableUnfoldings, updModeForRuleLHS, updModeForRuleRHS,
    
    ... ... @@ -174,16 +175,14 @@ data SimplCont
    174 175
                                     -- Invariant: never an identity coercion
    
    175 176
           , sc_opt  :: Bool         -- True <=> sc_co has had optCoercion applied to it
    
    176 177
                                     --      See Note [Avoid re-simplifying coercions]
    
    177
    -                                --      in GHC.Core.Opt.Simplify.Iteration
    
    178 178
           , sc_cont :: SimplCont }
    
    179 179
     
    
    180 180
       | ApplyToVal         -- (ApplyToVal arg K)[e] = K[ e arg ]
    
    181 181
           { sc_hole_ty :: OutType    -- Type of the function, presumably (forall a. blah)
    
    182 182
                                      -- See Note [The hole type in ApplyToTy]
    
    183
    -      , sc_env  :: StaticEnv     -- See Note [StaticEnv]
    
    184
    -      , sc_arg  :: CoreExpr      -- The argument
    
    185
    -      , sc_cast :: MOutCoercion  -- Wrap this OutCoercion around the (simplified) argument
    
    186
    -                                 -- See Note [The sc_cast field of ApplyToVal]
    
    183
    +      , sc_dup  :: DupFlag       -- See Note [The argument of ApplyToVal]
    
    184
    +      , sc_arg  :: SimplClo      -- The argument
    
    185
    +                                 -- Invariant: if sc_arg is a ContEx, then sc_dup = NoDup
    
    187 186
           , sc_cont :: SimplCont }
    
    188 187
     
    
    189 188
       | ApplyToTy          -- (ApplyToTy ty K)[e] = K[ e ty ]
    
    ... ... @@ -253,49 +252,85 @@ perhapsSubstTy (UnSimplified env) ty = substTy env ty
    253 252
     
    
    254 253
     {- Note [StaticEnv]
    
    255 254
     ~~~~~~~~~~~~~~~~~~~
    
    256
    -Consider ApplyToVal, which has
    
    257
    -    sc_env :: StaticEnv
    
    258
    -    sc_arg :: CoreExpr
    
    259
    -Initially, `sc_arg` is an un-simplified InExpr, and `sc_env` is (UnSimplified env),
    
    260
    -where `env` gives meaning to the free variables of `sc_arg`; in particular, `env`
    
    261
    -may have substitutions that must apply to the argument.
    
    262
    -
    
    263
    -But sometimes we simplify the argument, and in that case, `sc_arg` is an OutExpr,
    
    264
    -the simplified argument, and `sc_env` is (Simplified NoDup) or (Simplified OkDup).
    
    265
    -The former is the safe, conservative option, but in `mkDupableCont` we want to make
    
    266
    -the continuation duplicable, so we make the argument small and tag it with
    
    267
    -(Simplified OkDup).
    
    268
    -
    
    269
    -We later simplify the argument, e.g. in `simplArg`.  Then
    
    270
    -  * If sc_env is Simplified, it's a no-op
    
    271
    -  * If sc_env is (UnSimplified arg_env) we simplify `sc_arg` with
    
    272
    -     - Its captured envt `arg_env`
    
    255
    +Consider Select, which has
    
    256
    +    sc_env  :: StaticEnv
    
    257
    +    sc_bndr :: Id
    
    258
    +    sc_alts :: [CoreAlt]
    
    259
    +Initially, `sc_bndr` and `sc_alts` are un-simplified InThings, and `sc_env` is
    
    260
    +(UnSimplified env), where `env` gives meaning to their free variables; in
    
    261
    +particular, `env` may have substitutions that must apply to them.
    
    262
    +
    
    263
    +But sometimes (notably in `mkDupableCont`) we simplify them, and in that case
    
    264
    +`sc_bndr` and `sc_alts` are OutThings, and `sc_env` is (Simplified dup).
    
    265
    +
    
    266
    +When we finally simplify the alternatives (see `mkAltEnv`)
    
    267
    +  * If sc_env is Simplified, there is nothing to do
    
    268
    +  * If sc_env is (UnSimplified alt_env) we simplify them with
    
    269
    +     - Their captured envt `alt_env`
    
    273 270
          - but overriding its InScopeSet with the larger one at the
    
    274 271
            simplification point.
    
    275 272
         Why override the InScopeSet?  Example:
    
    276
    -          (let y = ey in f) ex
    
    277
    -    By the time we simplify ex, 'y' will be in scope.
    
    278
    -  All this is done in `simplArg`.
    
    273
    +          case (let y = ey in f) of alts
    
    274
    +    By the time we simplify alts, 'y' will be in scope.
    
    279 275
     
    
    280 276
     Note that:
    
    281 277
     
    
    282 278
     * In the Simplified case there is no environment, because the substitution has
    
    283 279
       already been applied.
    
    284 280
     
    
    285
    -* We say sc_arg :: CoreExpr, rather than sc_arg :: InExpr or sc_arg :: OutExpr,
    
    286
    -  because whether it is InExpr or OutExpr depends on `sc_env`
    
    281
    +* We say sc_alts :: [CoreAlt], rather than [InAlt] or [OutAlt],
    
    282
    +  because whether they are InAlts or OutAlts depends on `sc_env`
    
    283
    +
    
    284
    +* Same deal for StrictBind, where the StaticEnv scopes over sc_bndr and sc_body.
    
    287 285
     
    
    288
    -* Same deal for Select, and StrictBind, but the StaticEnv scopes over
    
    289
    -    * sc_bndr and sc_alts (for Select)
    
    290
    -    * sc_bndr and sc_body (for StrictBind)
    
    286
    +* ApplyToVal is similar, but simpler: it uses a SimplClo instead.
    
    287
    +  See Note [The argument of ApplyToVal].
    
    291 288
     
    
    292
    -* Even though the InScopeSet of an (UnSimplified se) is overridden in `simplArg`,
    
    293
    -  that InScopeSet is not irrelevant: it should include all the free vars of
    
    294
    -  applying the substitution to the InExpr. Reason: contHoleType uses perhapsSubstTy
    
    295
    -  to apply the substitution to the expression, and that (rightly) gives ASSERT
    
    296
    -  failures if the InScopeSet isn't big enough.
    
    289
    +* Even though the InScopeSet of an (UnSimplified se) is overridden, that
    
    290
    +  InScopeSet is not irrelevant: it should include all the free vars of
    
    291
    +  applying the substitution to the InThing. Reason: contHoleType uses
    
    292
    +  perhapsSubstTy to apply the substitution to the binder, and that
    
    293
    +  (rightly) gives ASSERT failures if the InScopeSet isn't big enough.
    
    297 294
     
    
    298 295
     (SE1) If dup = OkToDup, then continuation k is also ok-to-dup
    
    296
    +
    
    297
    +Note [The argument of ApplyToVal]
    
    298
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    299
    +ApplyToVal has
    
    300
    +    sc_dup :: DupFlag
    
    301
    +    sc_arg :: SimplClo
    
    302
    +
    
    303
    +Initially, `sc_arg` is (ContEx env arg MRefl), where `arg` is the un-simplified
    
    304
    +InExpr, and `env` gives meaning to the free variables of `arg`; in particular,
    
    305
    +`env` may have substitutions that must apply to the argument.
    
    306
    +
    
    307
    +But sometimes we simplify the argument, and in that case, `sc_arg` is
    
    308
    +(DoneEx arg' NotJoinPoint), where `arg'` is the simplified argument.
    
    309
    +
    
    310
    +The `sc_dup` flag says whether the continuation can be duplicated.  NoDup is
    
    311
    +the safe, conservative option, but in `mkDupableCont` we want to make the
    
    312
    +continuation duplicable, so we make the argument small (and hence a DoneEx)
    
    313
    +and set `sc_dup` to OkDup.  Invariants:
    
    314
    +
    
    315
    +  (AV1) If `sc_arg` is a ContEx, then `sc_dup` is NoDup.
    
    316
    +
    
    317
    +  (AV2) If `sc_dup` is OkDup then `sc_cont` is also ok-to-dup; see (SE1)
    
    318
    +        in Note [StaticEnv].
    
    319
    +
    
    320
    +We later simplify the argument, in `simplArg`.  Then
    
    321
    +  * If `sc_arg` is a DoneEx (or DoneId), it's a no-op
    
    322
    +  * If `sc_arg` is (ContEx arg_env arg mco) we simplify `arg` with
    
    323
    +     - Its captured envt `arg_env`
    
    324
    +     - but overriding its InScopeSet with the larger one at the
    
    325
    +       simplification point.
    
    326
    +    Why override the InScopeSet?  Example:
    
    327
    +          (let y = ey in f) ex
    
    328
    +    By the time we simplify ex, 'y' will be in scope.
    
    329
    +    Then we wrap the cast `mco` around the result.
    
    330
    +    See Note [The MOutCoercion field of ContEx].
    
    331
    +
    
    332
    +Using a SimplClo for the argument means that it can be substituted for a lambda
    
    333
    +binder, in `preInlineBetaUnconditionally`, without further ado.
    
    299 334
     -}
    
    300 335
     
    
    301 336
     instance Outputable DupFlag where
    
    ... ... @@ -313,9 +348,9 @@ instance Outputable SimplCont where
    313 348
         = (text "TickIt" <+> ppr t) $$ ppr cont
    
    314 349
       ppr (ApplyToTy  { sc_arg_ty = ty, sc_cont = cont })
    
    315 350
         = (text "ApplyToTy" <+> pprParendType ty) $$ ppr cont
    
    316
    -  ppr (ApplyToVal { sc_arg = arg, sc_env = env, sc_cont = cont, sc_hole_ty = hole_ty })
    
    317
    -    = (hang (text "ApplyToVal" <> braces (ppr env) <+> text "hole-ty:" <+> pprParendType hole_ty)
    
    318
    -          2 (pprParendExpr arg))
    
    351
    +  ppr (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_cont = cont, sc_hole_ty = hole_ty })
    
    352
    +    = (hang (text "ApplyToVal" <> braces (ppr dup) <+> text "hole-ty:" <+> pprParendType hole_ty)
    
    353
    +          2 (ppr arg))
    
    319 354
           $$ ppr cont
    
    320 355
       ppr (StrictBind { sc_bndr = b, sc_cont = cont })
    
    321 356
         = (text "StrictBind" <+> ppr b) $$ ppr cont
    
    ... ... @@ -434,8 +469,8 @@ pushOutArgs fun_ty (arg:args) cont
    434 469
       = ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
    
    435 470
                   , sc_cont = pushOutArgs (piResultTy fun_ty ty) args cont }
    
    436 471
       | otherwise
    
    437
    -  = ApplyToVal { sc_hole_ty = fun_ty, sc_cast = MRefl
    
    438
    -               , sc_arg = arg, sc_env = Simplified NoDup
    
    472
    +  = ApplyToVal { sc_hole_ty = fun_ty
    
    473
    +               , sc_arg = DoneEx arg NotJoinPoint, sc_dup = NoDup
    
    439 474
                    , sc_cont = pushOutArgs (funResultTy fun_ty) args  cont}
    
    440 475
     
    
    441 476
     pushArgSpecs :: [ArgSpec]   -- In normal, forward order
    
    ... ... @@ -446,7 +481,7 @@ pushArgSpec :: ArgSpec -> SimplCont -> SimplCont
    446 481
     pushArgSpec (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
    
    447 482
       = ApplyToTy  { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont }
    
    448 483
     pushArgSpec (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
    
    449
    -  = ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup, sc_cast = MRefl
    
    484
    +  = ApplyToVal { sc_arg = DoneEx arg NotJoinPoint, sc_dup = NoDup
    
    450 485
                    , sc_hole_ty = hole_ty, sc_cont = cont }
    
    451 486
     
    
    452 487
     argSpecArg :: ArgSpec -> OutExpr
    
    ... ... @@ -497,7 +532,12 @@ contIsStop _ = False
    497 532
     contIsDupable :: SimplCont -> Bool
    
    498 533
     contIsDupable (Stop {})                    = True
    
    499 534
     contIsDupable (ApplyToTy  { sc_cont = k }) = contIsDupable k
    
    500
    -contIsDupable (ApplyToVal { sc_env = se }) = okToDupSE se -- See (SE1) in Note [StaticEnv]
    
    535
    +contIsDupable (ApplyToVal { sc_dup = dup, sc_arg = arg })
    
    536
    +  = assertPpr (not (okToDup dup && is_cont_ex arg)) (ppr arg) $
    
    537
    +    okToDup dup -- See (AV1,AV2) in Note [The argument of ApplyToVal]
    
    538
    +  where
    
    539
    +    is_cont_ex (ContEx {}) = True
    
    540
    +    is_cont_ex _           = False
    
    501 541
     contIsDupable (Select { sc_env = se })     = okToDupSE se -- ...ditto...
    
    502 542
     contIsDupable (StrictBind { sc_env = se }) = okToDupSE se -- ...ditto...
    
    503 543
     contIsDupable (StrictArg { sc_dup = dup }) = okToDup dup  -- ...ditto...
    
    ... ... @@ -606,8 +646,8 @@ contArgs env cont
    606 646
         lone (CastIt {})     = False  --     stops it being "lone"
    
    607 647
         lone _               = True
    
    608 648
     
    
    609
    -    go args (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = k })
    
    610
    -                                        = go (interestingArg env se arg : args) k
    
    649
    +    go args (ApplyToVal { sc_arg = arg, sc_cont = k })
    
    650
    +                                        = go (interestingArg env arg : args) k
    
    611 651
         go args (ApplyToTy { sc_cont = k }) = go args k
    
    612 652
         go args (CastIt { sc_cont = k })    = go args k
    
    613 653
         go args k                           = (False, reverse args, k)
    
    ... ... @@ -622,15 +662,13 @@ contOutArgs env cont
    622 662
         go (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
    
    623 663
           = Type ty : go cont
    
    624 664
     
    
    625
    -    go (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = cont })
    
    626
    -      = case se of
    
    627
    -          Simplified {}    -> arg : go cont
    
    628
    -          UnSimplified env -> GHC.Core.Subst.substExpr (getFullSubst in_scope env) arg : go cont
    
    629
    -        -- Make sure we apply the static environment `sc_env` as a substitution
    
    665
    +    go (ApplyToVal { sc_arg = arg, sc_cont = cont })
    
    666
    +      = simplCloExpr in_scope arg : go cont
    
    667
    +        -- Make sure we apply the static environment of a ContEx as a substitution
    
    630 668
             --   to get an OutExpr.  See (BF1) in Note [tryRules: plan (BEFORE)]
    
    631 669
             --   in GHC.Core.Opt.Simplify.Iteration
    
    632
    -        -- NB: we use substExpr, not substExprSC: we want to get the benefit of
    
    633
    -        --     knowing what is evaluated etc, via the in-scope set
    
    670
    +        -- simplCloExpr also wraps the pending cast (if any) around the argument;
    
    671
    +        --   omitting it can make a rule fail to match (#27963)
    
    634 672
     
    
    635 673
         -- No more arguments
    
    636 674
         go _ = []
    
    ... ... @@ -827,23 +865,86 @@ make use of the strictness info for the function.
    827 865
     *                                                                      *
    
    828 866
     ********************************************************************* -}
    
    829 867
     
    
    830
    -{- Note [The sc_cast field of ApplyToVal]
    
    831
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    868
    +{- Note [The MOutCoercion field of ContEx]
    
    869
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    832 870
     In the `ApplyToVal` case of `pushCast` we want to push an `OutCoercion` into the
    
    833
    -argument.  But the argument may or may not have been simplified (see Note [StaticEnv])
    
    834
    -so we definitely can't just wrap the cast around the argument. Instead we store it
    
    835
    -in the `sc_cast` field -- this is the whole reason for the `sc_cast` field.
    
    871
    +argument.  But the argument may or may not have been simplified (see Note [The
    
    872
    +argument of ApplyToVal]):
    
    873
    +
    
    874
    +* If it has been simplified, it is (DoneEx arg' _), and we can simply wrap the
    
    875
    +  cast around `arg'`.
    
    876
    +
    
    877
    +* If it has not, it is (ContEx env arg mco), and we definitely can't just wrap
    
    878
    +  the (Out)cast around the InExpr `arg`. Instead we compose it with `mco` --
    
    879
    +  this is the whole reason for the MOutCoercion field of `ContEx`.
    
    880
    +
    
    881
    +All this is done by `mkCloCastMCo`.
    
    836 882
     
    
    837 883
     We deal with that pending cast mainly in `simplArg`.
    
    838 884
     
    
    839 885
     But we /also/ sometimes want to substitute that argument for a lambda-binder, in
    
    840
    -`preInlineUnconditionally`.  So we also have to put that pending cast into
    
    841
    -`ContEx`; hence the MOutCoercion field of `ContEx`.  Then we deal with it
    
    842
    -appropriately when /applying/ the substitution in `simplInId`.
    
    886
    +`preInlineBetaUnconditionally`; and since the substitution maps an Id to a SimplClo,
    
    887
    +the pending cast comes along for free.  Then we deal with it appropriately when
    
    888
    +/applying/ the substitution in `simplInId`.
    
    889
    +
    
    890
    +Note [Optimising reflexivity]
    
    891
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    892
    +It's important (for compiler performance) to get rid of reflexivity as soon
    
    893
    +as it appears.  See #11735, #14737, and #15019.
    
    894
    +
    
    895
    +In particular, we want to behave well on
    
    896
    +
    
    897
    + *  e |> co1 |> co2
    
    898
    +    where the two happen to cancel out entirely. That is quite common;
    
    899
    +    e.g. a newtype wrapping and unwrapping cancel.
    
    900
    +
    
    901
    +
    
    902
    + * (f |> co) @t1 @t2 ... @tn x1 .. xm
    
    903
    +   Here we will use pushCoTyArg and pushCoValArg successively, which
    
    904
    +   build up SelCo stacks.  Silly to do that if co is reflexive.
    
    905
    +
    
    906
    +However, we don't want to call isReflexiveCo too much, because it uses
    
    907
    +type equality which is expensive on big types (#14737 comment:7).
    
    908
    +
    
    909
    +A good compromise (determined experimentally) seems to be to call
    
    910
    +isReflexiveCo
    
    911
    + * when composing casts, and
    
    912
    + * at the end
    
    913
    +
    
    914
    +In investigating this I saw missed opportunities for on-the-fly
    
    915
    +coercion shrinkage. See #15090.
    
    916
    +
    
    917
    +Note [Avoid re-simplifying coercions]
    
    918
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    919
    +In some benchmarks (with deeply nested cases) we successively push
    
    920
    +casts onto the SimplCont.  We don't want to call the coercion optimiser
    
    921
    +on each successive composition -- that's at least quadratic.  So:
    
    922
    +
    
    923
    +* The CastIt constructor in SimplCont has a `sc_opt :: Bool` flag to
    
    924
    +  record whether the coercion optimiser has been applied to the coercion.
    
    925
    +
    
    926
    +* In `simplCast`, when we see (Cast e co), we simplify `co` to get
    
    927
    +  an OutCoercion, and built a CastIt with sc_opt=True.
    
    928
    +
    
    929
    +  Actually not quite: if we are simplifying the result of inlining an
    
    930
    +  unfolding (seInlineDepth > 0), then instead of /optimising/ it again,
    
    931
    +  just /substitute/ which is cheaper.  See `simplCoercion`.
    
    932
    +
    
    933
    +* In `pushCast` if we combine this new coercion with an existing one,
    
    934
    +  we build a CastIt for (co1 ; co2) with sc_opt=False.
    
    935
    +
    
    936
    +* When unpacking a CastIt, in `rebuild`, we optimise the (presumably
    
    937
    +  composed) coercion if sc_opt=False; this is done by `optOutCoercion`.
    
    938
    +
    
    939
    +* When duplicating a continuation in `mkDupableContWithDmds`, before
    
    940
    +  duplicating a CastIt, optimise the coercion. Otherwise we'll end up
    
    941
    +  optimising it separately in the duplicate copies.
    
    942
    +
    
    943
    +* See also Note [The MOutCoercion field of ContEx]
    
    843 944
     -}
    
    844 945
     
    
    845 946
     optOutCoercion :: SimplEnvIS -> OutCoercion -> Bool -> OutCoercion
    
    846
    --- See Note [Avoid re-simplifying coercions] in GHC.Core.Opt.Simplify.Iteration
    
    947
    +-- See Note [Avoid re-simplifying coercions]
    
    847 948
     optOutCoercion env co already_optimised
    
    848 949
       | already_optimised = co  -- Ditto
    
    849 950
       | otherwise         = optCoercion opts empty_subst co
    
    ... ... @@ -863,7 +964,8 @@ pushCastMCo env (MCo co) cont = pushCast env co cont
    863 964
     
    
    864 965
     pushCast :: SimplEnv -> OutCoercion -> SimplCont -> SimplCont
    
    865 966
     pushCast env co cont
    
    866
    -  = go co True cont
    
    967
    +  | isReflCo co = cont     -- See Note [Optimising reflexivity]
    
    968
    +  | otherwise   = go co True cont
    
    867 969
       where
    
    868 970
     
    
    869 971
         -- ToDo:   pushCast Refl (ApplylToVal arg1 (ApplyToVal arg2 ...))
    
    ... ... @@ -872,7 +974,7 @@ pushCast env co cont
    872 974
         go co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity] in GHC.Core.Opt.Simplify.Iteration
    
    873 975
           = go (mkTransCo co1 co2) False cont
    
    874 976
                       -- False: (mkTransCo co1 co2) is not fully optimised
    
    875
    -                  -- See Note [Avoid re-simplifying coercions] in GHC.Core.Opt.Simplify.Iteration
    
    977
    +                  -- See Note [Avoid re-simplifying coercions]
    
    876 978
     
    
    877 979
         go co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
    
    878 980
           | Just (tyL, arg_ty', m_co') <- pushCoTyArg co arg_ty
    
    ... ... @@ -887,21 +989,17 @@ pushCast env co cont
    887 989
         -- where   co :: (s1->s2) ~ (t1->t2)
    
    888 990
         --         co1 :: t1 ~ s1
    
    889 991
         --         co2 :: s2 ~ t2
    
    890
    -    go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    891
    -                                     , sc_cast = arg_mco, sc_cont = tail })
    
    992
    +    go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_cont = tail })
    
    892 993
           | not co_is_opt
    
    893 994
           = -- pushCoValArg duplicates the coercion, so optimise first
    
    894 995
             go (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
    
    895 996
     
    
    896 997
           | Just (tyL, m_co1, m_co2) <- pushCoValArg co
    
    897 998
           = {-#SCC "addCoerce-pushCoValArg" #-}
    
    898
    -        -- Dealing with m_co1 is the entire reason for the sc_cast field
    
    899
    -        -- of ApplyToVal; see Note [The sc_cast field of ApplyToVal]
    
    900
    -        ApplyToVal { sc_arg  = arg
    
    901
    -                   , sc_env  = arg_se
    
    902
    -                   , sc_cast = arg_mco `mkTransMCo` m_co1
    
    903
    -                   , sc_cont = go_mco m_co2 True tail
    
    904
    -                   , sc_hole_ty = tyL }
    
    999
    +        -- See Note [The MOutCoercion field of ContEx]
    
    1000
    +        cont { sc_arg     = mkCloCastMCo arg m_co1
    
    1001
    +             , sc_cont    = go_mco m_co2 True tail
    
    1002
    +             , sc_hole_ty = tyL }
    
    905 1003
     
    
    906 1004
         go co co_is_opt cont
    
    907 1005
           | isReflCo co = cont  -- Having this at the end makes a huge
    
    ... ... @@ -915,6 +1013,13 @@ pushCast env co cont
    915 1013
         go_mco MRefl    _   cont = cont
    
    916 1014
         go_mco (MCo co) opt cont = go co opt cont
    
    917 1015
     
    
    1016
    +mkCloCastMCo :: SimplClo -> MOutCoercion -> SimplClo
    
    1017
    +-- See Note [The MOutCoercion field of ContEx]
    
    1018
    +mkCloCastMCo clo               MRefl    = clo
    
    1019
    +mkCloCastMCo (DoneId v)        (MCo co) = DoneEx (mkCast (Var v) co) NotJoinPoint
    
    1020
    +mkCloCastMCo (DoneEx e _)      (MCo co) = DoneEx (mkCast e co)       NotJoinPoint
    
    1021
    +mkCloCastMCo (ContEx se e mco) (MCo co) = ContEx se e (mco `mkTransMCo` MCo co)
    
    1022
    +
    
    918 1023
     
    
    919 1024
     {-
    
    920 1025
     ************************************************************************
    
    ... ... @@ -1228,19 +1333,17 @@ Wrinkles:
    1228 1333
     
    
    1229 1334
     -}
    
    1230 1335
     
    
    1231
    -interestingArg :: SimplEnv -> StaticEnv -> CoreExpr -> ArgSummary
    
    1336
    +interestingArg :: SimplEnv -> SimplClo -> ArgSummary
    
    1232 1337
     -- See Note [Interesting arguments]
    
    1233
    -interestingArg env se e
    
    1234
    -  = case se of
    
    1235
    -      Simplified {}           -> go env                                0 e
    
    1236
    -      UnSimplified static_env -> go (static_env `setInScopeFromE` env) 0 e
    
    1338
    +interestingArg env clo
    
    1339
    +  = go_clo env 0 clo
    
    1237 1340
       where
    
    1341
    +    go_clo _   n (DoneId v)       = go_var n v
    
    1342
    +    go_clo env n (DoneEx e _)     = go (zapSubstEnv env)          n e
    
    1343
    +    go_clo env n (ContEx se e _)  = go (se `setInScopeFromE` env) n e
    
    1344
    +
    
    1238 1345
         -- n is # value args to which the expression is applied
    
    1239
    -    go env n (Var v)
    
    1240
    -       = case substId env v of
    
    1241
    -           DoneId v'            -> go_var n v'
    
    1242
    -           DoneEx e _           -> go (zapSubstEnv env)          n e
    
    1243
    -           ContEx se e _mco     -> go (se `setInScopeFromE` env) n e
    
    1346
    +    go env n (Var v) = go_clo env n (substId env v)
    
    1244 1347
     
    
    1245 1348
         go _   _ (Lit l)
    
    1246 1349
            | isLitRubbish l        = NonTrivArg -- See (IA3) in Note [Interesting arguments]
    
    ... ... @@ -1739,15 +1842,15 @@ is a term (not a coercion) so we can't necessarily inline the latter in
    1739 1842
     the former.
    
    1740 1843
     -}
    
    1741 1844
     
    
    1742
    -preInlineUnconditionally
    
    1845
    +preInlineLetUnconditionally
    
    1743 1846
         :: SimplEnv -> TopLevelFlag -> InId
    
    1744
    -    -> StaticEnv -> CoreExpr -> MOutCoercion  -- The argument
    
    1847
    +    -> InExpr -> SimplEnv   -- These two go together
    
    1745 1848
         -> Maybe SimplEnv       -- Returned env has extended substitution
    
    1746 1849
     -- Precondition: rhs satisfies the let-can-float invariant
    
    1747 1850
     -- See Note [Core let-can-float invariant] in GHC.Core
    
    1748 1851
     -- Reason: we don't want to inline single uses, or discard dead bindings,
    
    1749 1852
     --         for unlifted, side-effect-ful bindings
    
    1750
    -preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
    
    1853
    +preInlineLetUnconditionally env top_lvl bndr rhs rhs_env
    
    1751 1854
       | not pre_inline_unconditionally           = Nothing
    
    1752 1855
       | not active                               = Nothing
    
    1753 1856
       | isTopLevel top_lvl && isDeadEndId bndr   = Nothing -- Note [Top-level bottoming Ids]
    
    ... ... @@ -1759,26 +1862,15 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
    1759 1862
     
    
    1760 1863
       -- See Note [Stable unfoldings and preInlineUnconditionally]
    
    1761 1864
       | not (isInlinePragma inline_prag)
    
    1762
    -  , Just inl <- maybeUnfoldingTemplate unf   = assertPpr (isReflMCo rhs_mco) (ppr bndr) $
    
    1763
    -                                               Just $! (extend_subst_with inl)
    
    1865
    +  , Just inl <- maybeUnfoldingTemplate unf   = Just $! (extend_subst_with inl)
    
    1764 1866
     
    
    1765 1867
       | otherwise                                = Nothing
    
    1766 1868
       where
    
    1767 1869
         unf = idUnfolding bndr
    
    1768 1870
     
    
    1769
    -    -- If the rhs is /not/ already simplified, extend the envt with ContEx, which captures
    
    1770
    -    --    the the lexical environment for us to restore in `simplInId`.
    
    1771
    -    -- If the rhs /is/ already simplified, then extend the envt with DoneEx;
    
    1772
    -    --    That makes `simplInId` call `simplOutExpr` which avoids re-simplifying
    
    1773
    -    --    the RHS.
    
    1774
    -    -- See Note [Avoid repeated simplification] in GHC.Core.Opt.Simplify.Iteration
    
    1775
    -    extend_subst_with inl_rhs
    
    1776
    -      = extendIdSubst env bndr $!
    
    1777
    -        case rhs_se of
    
    1778
    -          Simplified _ -> case rhs_mco of
    
    1779
    -                             MRefl  -> DoneEx inl_rhs NotJoinPoint -- Common case
    
    1780
    -                             MCo co -> DoneEx (mkCast inl_rhs co) NotJoinPoint
    
    1781
    -          UnSimplified rhs_env -> ContEx rhs_env inl_rhs rhs_mco
    
    1871
    +    -- The rhs is not yet simplified, so extend the envt with ContEx, which
    
    1872
    +    -- captures the lexical environment for us to restore in `simplInId`.
    
    1873
    +    extend_subst_with inl_rhs = extendIdSubst env bndr $! ContEx rhs_env inl_rhs MRefl
    
    1782 1874
     
    
    1783 1875
         one_occ IAmDead = True -- Happens in ((\x.1) v)
    
    1784 1876
         one_occ OneOcc{ occ_n_br   = 1
    
    ... ... @@ -1794,39 +1886,6 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
    1794 1886
                  -- See Note [pre/postInlineUnconditionally in gentle mode]
    
    1795 1887
         inline_prag = idInlinePragma bndr
    
    1796 1888
     
    
    1797
    --- Be very careful before inlining inside a lambda, because (a) we must not
    
    1798
    --- invalidate occurrence information, and (b) we want to avoid pushing a
    
    1799
    --- single allocation (here) into multiple allocations (inside lambda).
    
    1800
    --- Inlining a *function* with a single *saturated* call would be ok, mind you.
    
    1801
    ---      || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
    
    1802
    ---      where
    
    1803
    ---              is_cheap = exprIsCheap rhs
    
    1804
    ---              ok = is_cheap && int_cxt
    
    1805
    -
    
    1806
    -        --      int_cxt         The context isn't totally boring
    
    1807
    -        -- E.g. let f = \ab.BIG in \y. map f xs
    
    1808
    -        --      Don't want to substitute for f, because then we allocate
    
    1809
    -        --      its closure every time the \y is called
    
    1810
    -        -- But: let f = \ab.BIG in \y. map (f y) xs
    
    1811
    -        --      Now we do want to substitute for f, even though it's not
    
    1812
    -        --      saturated, because we're going to allocate a closure for
    
    1813
    -        --      (f y) every time round the loop anyhow.
    
    1814
    -
    
    1815
    -        -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
    
    1816
    -        -- so substituting rhs inside a lambda doesn't change the occ info.
    
    1817
    -        -- Sadly, not quite the same as exprIsHNF.
    
    1818
    -    canInlineInLam (Lit _)    = True
    
    1819
    -    canInlineInLam (Cast e _) = canInlineInLam e
    
    1820
    -    canInlineInLam (Lam b e)  = isRuntimeVar b || canInlineInLam e
    
    1821
    -    canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
    
    1822
    -    canInlineInLam (Var v)    = case idOccInfo v of
    
    1823
    -                                  OneOcc { occ_in_lam = IsInsideLam } -> True
    
    1824
    -                                  ManyOccs {}                         -> True
    
    1825
    -                                  _                                   -> False
    
    1826
    -    canInlineInLam _          = False
    
    1827
    -      -- not ticks.  Counting ticks cannot be duplicated, and non-counting
    
    1828
    -      -- ticks around a Lam will disappear anyway.
    
    1829
    -
    
    1830 1889
         early_phase =
    
    1831 1890
           case sePhase env of
    
    1832 1891
             SimplPhase p -> p /= FinalPhase
    
    ... ... @@ -1857,6 +1916,97 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
    1857 1916
         -- (Nor can we check for `exprIsExpandable rhs`, because that needs to look
    
    1858 1917
         -- at the non-existent unfolding for the `I# 2#` which is also floated out.)
    
    1859 1918
     
    
    1919
    +preInlineBetaUnconditionally
    
    1920
    +    :: SimplEnv -> Levity -> InId
    
    1921
    +    -> SimplClo             -- The argument
    
    1922
    +    -> Maybe SimplEnv       -- Returned env has extended substitution
    
    1923
    +-- Like preInlineLetUnconditionally, but for a beta-redex (\bndr. body) arg
    
    1924
    +-- The argument may or may not be already simplified (DoneEx or ContEx)
    
    1925
    +--
    
    1926
    +-- The binder is a lambda binder and so lacks most IdInfo;
    
    1927
    +--   see Note [Core binder IdInfo invariants]
    
    1928
    +--
    
    1929
    +-- Compared to preInlineLetUnconditionally we omit some checks:
    
    1930
    +--   * The binder is never top-level, so no need for the
    
    1931
    +--     Note [Top-level bottoming Ids] check, nor for `early_phase`
    
    1932
    +--   * A lambda binder is never a join point, so no need for the
    
    1933
    +--     Note [Do not inline exit join points] check
    
    1934
    +--   * A lambda binder never has an inline pragma, a stable unfolding, or RULES
    
    1935
    +--     (see `lamBndrInfoOK`), so no need to check activation, nor for
    
    1936
    +--     Note [Stable unfoldings and preInlineUnconditionally]
    
    1937
    +--
    
    1938
    +-- And we add one extra one
    
    1939
    +--   * Check the let-can-float invariant, and don't inline if not
    
    1940
    +
    
    1941
    +preInlineBetaUnconditionally env levity bndr arg
    
    1942
    +  | assertPpr (lamBndrInfoOK bndr) (ppr bndr) $
    
    1943
    +    not pre_inline_unconditionally           = Nothing
    
    1944
    +  | isCoVar bndr                             = Nothing -- Note [Do not inline CoVars unconditionally]
    
    1945
    +  | not (one_occ (idOccInfo bndr))           = Nothing
    
    1946
    +  | needs_case_binding                       = Nothing  -- Enforce the let-can-float invariant
    
    1947
    +  | otherwise                                = Just $! extendIdSubst env bndr arg
    
    1948
    +    -- If the arg is not yet simplified, it is a ContEx, which captures the
    
    1949
    +    --    lexical environment for us to restore in `simplInId`.
    
    1950
    +    -- If the arg is already simplified, then it is a DoneEx;
    
    1951
    +    --    That makes `simplInId` call `simplOutExpr` which avoids re-simplifying
    
    1952
    +    --    the arg.
    
    1953
    +    -- See Note [Avoid repeated simplification] in GHC.Core.Opt.Simplify.Iteration
    
    1954
    +  where
    
    1955
    +    pre_inline_unconditionally = sePreInline env
    
    1956
    +
    
    1957
    +    needs_case_binding = needsCaseBindingL levity rhs
    
    1958
    +    -- Ok to test an InExpr or OutExpr in needsCaseBindingL because
    
    1959
    +    -- exprOkForSpeculation is stable under simplification
    
    1960
    +
    
    1961
    +    rhs :: CoreExpr   -- Can be InExpr or OutExpr, but here it does not matter
    
    1962
    +    rhs = case arg of
    
    1963
    +            ContEx _ e _ -> e          -- InExpr
    
    1964
    +            DoneEx e _   -> e          -- OutExpr
    
    1965
    +            DoneId v     -> Var v      -- OutExpr
    
    1966
    +
    
    1967
    +    one_occ IAmDead = True -- Happens in ((\x.1) v)
    
    1968
    +    one_occ OneOcc{ occ_n_br   = 1
    
    1969
    +                  , occ_in_lam = NotInsideLam }   = True
    
    1970
    +    one_occ OneOcc{ occ_n_br   = 1
    
    1971
    +                  , occ_in_lam = IsInsideLam
    
    1972
    +                  , occ_int_cxt = IsInteresting } = canInlineInLam rhs
    
    1973
    +    one_occ _                                     = False
    
    1974
    +
    
    1975
    +
    
    1976
    +canInlineInLam :: CoreExpr -> Bool
    
    1977
    +-- Be very careful before inlining inside a lambda, because (a) we must not
    
    1978
    +-- invalidate occurrence information, and (b) we want to avoid pushing a
    
    1979
    +-- single allocation (here) into multiple allocations (inside lambda).
    
    1980
    +-- Inlining a *function* with a single *saturated* call would be ok, mind you.
    
    1981
    +--      || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
    
    1982
    +--      where
    
    1983
    +--              is_cheap = exprIsCheap rhs
    
    1984
    +--              ok = is_cheap && int_cxt
    
    1985
    +
    
    1986
    +        --      int_cxt         The context isn't totally boring
    
    1987
    +        -- E.g. let f = \ab.BIG in \y. map f xs
    
    1988
    +        --      Don't want to substitute for f, because then we allocate
    
    1989
    +        --      its closure every time the \y is called
    
    1990
    +        -- But: let f = \ab.BIG in \y. map (f y) xs
    
    1991
    +        --      Now we do want to substitute for f, even though it's not
    
    1992
    +        --      saturated, because we're going to allocate a closure for
    
    1993
    +        --      (f y) every time round the loop anyhow.
    
    1994
    +
    
    1995
    +        -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
    
    1996
    +        -- so substituting rhs inside a lambda doesn't change the occ info.
    
    1997
    +        -- Sadly, not quite the same as exprIsHNF.
    
    1998
    +canInlineInLam (Lit _)    = True
    
    1999
    +canInlineInLam (Cast e _) = canInlineInLam e
    
    2000
    +canInlineInLam (Lam b e)  = isRuntimeVar b || canInlineInLam e
    
    2001
    +canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
    
    2002
    +canInlineInLam (Var v)    = case idOccInfo v of
    
    2003
    +                              OneOcc { occ_in_lam = IsInsideLam } -> True
    
    2004
    +                              ManyOccs {}                         -> True
    
    2005
    +                              _                                   -> False
    
    2006
    +canInlineInLam _          = False
    
    2007
    +  -- not ticks.  Counting ticks cannot be duplicated, and non-counting
    
    2008
    +  -- ticks around a Lam will disappear anyway.
    
    2009
    +
    
    1860 2010
     {-
    
    1861 2011
     ************************************************************************
    
    1862 2012
     *                                                                      *
    

  • testsuite/tests/simplCore/should_compile/T15445.stderr
    ... ... @@ -4,6 +4,7 @@ Rule fired: Int# -> Integer -> Int# (GHC.Internal.Bignum.Integer)
    4 4
     Rule fired: USPEC plusTwoRec @Int (T15445a)
    
    5 5
     Rule fired: USPEC $fShowList @Int (GHC.Internal.Show)
    
    6 6
     Rule fired: Class op >> (BUILTIN)
    
    7
    +Rule fired: Class op show (BUILTIN)
    
    7 8
     Rule fired: USPEC plusTwoRec @Int (T15445a)
    
    8 9
     Rule fired: Class op enumFromTo (BUILTIN)
    
    9 10
     Rule fired: eftInt (GHC.Internal.Enum)
    
    ... ... @@ -11,7 +12,6 @@ Rule fired: Class op show (BUILTIN)
    11 12
     Rule fired: USPEC plusTwoRec @Int (T15445a)
    
    12 13
     Rule fired: Class op enumFromTo (BUILTIN)
    
    13 14
     Rule fired: eftInt (GHC.Internal.Enum)
    
    14
    -Rule fired: Class op show (BUILTIN)
    
    15 15
     Rule fired: eftIntList (GHC.Internal.Enum)
    
    16 16
     Rule fired: ># (BUILTIN)
    
    17 17
     Rule fired: ==# (BUILTIN)
    

  • testsuite/tests/simplCore/should_compile/T27962.hs
    1
    +{-# LANGUAGE MagicHash #-}
    
    2
    +
    
    3
    +module T27962 where
    
    4
    +
    
    5
    +import GHC.Exts
    
    6
    +
    
    7
    +newtype N = MkN Int
    
    8
    +
    
    9
    +-- After inlining myRun, we get  (runRW# @LiftedRep @Int |> co) (\_ -> ...)
    
    10
    +-- and the simplifier pushes co into the argument of runRW#.
    
    11
    +-- #27962: the simplifier dropped that cast, yielding ill-typed Core
    
    12
    +myRun :: (State# RealWorld -> N) -> N
    
    13
    +myRun = coerce (runRW# :: (State# RealWorld -> Int) -> Int)
    
    14
    +{-# INLINE myRun #-}
    
    15
    +
    
    16
    +foo x = myRun (\_ -> MkN (x+1))

  • testsuite/tests/simplCore/should_compile/T27963.hs
    1
    +{-# OPTIONS_GHC -Wno-inline-rule-shadowing #-}
    
    2
    +
    
    3
    +module T27963 where
    
    4
    +
    
    5
    +-- This test is pretty delicate because it relies on a function
    
    6
    +-- that has BOTH a rule AND an INLINE pragma
    
    7
    +--
    
    8
    +-- See #27963 for some discussion
    
    9
    +--
    
    10
    +-- Still, it should (just) work
    
    11
    +
    
    12
    +import GHC.Exts
    
    13
    +
    
    14
    +newtype N = MkN Int
    
    15
    +
    
    16
    +f x = x
    
    17
    +{-# INLINE f #-}
    
    18
    +{-# RULES "f/42" forall x. f x = 42::Int #-}
    
    19
    +
    
    20
    +-- The rule "f/42" should fire in both h1 and h2
    
    21
    +h1,h2 :: N -> Int
    
    22
    +h1 n = f (coerce n) + 0
    
    23
    +h2 n = (coerce f) n + 0   -- #27963: the rule did not fire here

  • testsuite/tests/simplCore/should_compile/T27963.stderr
    1
    +Rule fired: f/42 (T27963)
    
    2
    +Rule fired: f/42 (T27963)

  • testsuite/tests/simplCore/should_compile/all.T
    ... ... @@ -633,4 +633,3 @@ test('T27962', normal, compile, [''])
    633 633
     test('T27962a', [extra_files(['T27962.hs'])], multimod_compile, ['T27962', '-v0 -O'])
    
    634 634
     test('T27963', [grep_errmsg(r'f/42')], compile, ['-O -ddump-rule-firings'])
    
    635 635
     test('T27965', normal, compile, [''])
    636
    -