Simon Peyton Jones pushed to branch wip/26543 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Core/Opt/Simplify/Env.hs
    ... ... @@ -11,7 +11,7 @@ module GHC.Core.Opt.Simplify.Env (
    11 11
             SimplMode(..), updMode, smPlatform,
    
    12 12
     
    
    13 13
             -- * Environments
    
    14
    -        SimplEnv(..), pprSimplEnv,   -- Temp not abstract
    
    14
    +        SimplEnv(..), StaticEnv, pprSimplEnv,   -- Temp not abstract
    
    15 15
             SimplPhase(..), isActive,
    
    16 16
             seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
    
    17 17
             seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
    
    ... ... @@ -28,13 +28,13 @@ module GHC.Core.Opt.Simplify.Env (
    28 28
             SimplEnvIS,  checkSimplEnvIS, pprBadSimplEnvIS,
    
    29 29
     
    
    30 30
             -- * Substitution results
    
    31
    -        SimplSR(..), mkContEx, substId, lookupRecBndr,
    
    31
    +        SimplClo(..), mkContEx, substId, lookupRecBndr,
    
    32 32
     
    
    33 33
             -- * Simplifying 'Id' binders
    
    34 34
             simplNonRecBndr, simplNonRecJoinBndr, simplRecBndrs, simplRecJoinBndrs,
    
    35 35
             simplBinder, simplBinders,
    
    36 36
             substTy, substTyVar, getFullSubst, getTCvSubst,
    
    37
    -        substCo, substCoVar,
    
    37
    +        substCo, substCoVar, simplCloExpr, simplCloCoercion_maybe,
    
    38 38
     
    
    39 39
             -- * Floats
    
    40 40
             SimplFloats(..), emptyFloats, isEmptyFloats, mkRecFloats,
    
    ... ... @@ -60,8 +60,9 @@ import GHC.Core.Opt.Arity ( ArityOpts(..) )
    60 60
     import GHC.Core.Opt.Simplify.Monad
    
    61 61
     import GHC.Core.Rules.Config ( RuleOpts(..) )
    
    62 62
     import GHC.Core
    
    63
    +import GHC.Core.Ppr
    
    63 64
     import GHC.Core.Utils
    
    64
    -import GHC.Core.Subst( substExprSC )
    
    65
    +import GHC.Core.Subst( substExpr )
    
    65 66
     import GHC.Core.Unfold
    
    66 67
     import GHC.Core.TyCo.Subst (emptyIdSubstEnv, mkSubst)
    
    67 68
     import GHC.Core.Multiplicity( Scaled(..), mkMultMul )
    
    ... ... @@ -209,6 +210,8 @@ type SimplEnvIS = SimplEnv
    209 210
          -- Invariant: the substitution is empty
    
    210 211
          -- We want this SimplEnv for its InScopeSet and flags
    
    211 212
     
    
    213
    +type StaticEnv = SimplEnv       -- Just the static part is relevant
    
    214
    +
    
    212 215
     checkSimplEnvIS :: SimplEnvIS -> Bool
    
    213 216
     -- Check the invariant for SimplEnvIS
    
    214 217
     checkSimplEnvIS (SimplEnv { seIdSubst = id_env, seTvSubst = tv_env, seCvSubst = cv_env })
    
    ... ... @@ -459,41 +462,46 @@ pprSimplEnv env
    459 462
        ppr_one v | isId v = ppr v <+> ppr (idUnfolding v)
    
    460 463
                  | otherwise = ppr v
    
    461 464
     
    
    462
    -type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
    
    465
    +type SimplIdSubst = IdEnv SimplClo -- IdId |--> OutExpr
    
    463 466
             -- See Note [Extending the IdSubstEnv] in GHC.Core.Subst
    
    464 467
     
    
    465
    --- | A substitution result.
    
    466
    -data SimplSR
    
    468
    +-- | A "closure" used in the Simplifier
    
    469
    +-- Roughly: either an (InExpr, StaticEnv) pair for an
    
    470
    +--                 as-yet-unsimplified expression
    
    471
    +--          or     an OutExpr, for an already-simplified one
    
    472
    +
    
    473
    +data SimplClo
    
    467 474
       = DoneEx OutExpr JoinPointHood
    
    468 475
            -- If  x :-> DoneEx e ja   is in the SimplIdSubst
    
    469 476
            -- then replace occurrences of x by e
    
    470 477
            -- and  ja = Just a <=> x is a join-point of arity a
    
    471 478
            -- See Note [Join arity in SimplIdSubst]
    
    472 479
     
    
    473
    -
    
    474 480
       | DoneId OutId
    
    475 481
            -- If  x :-> DoneId v   is in the SimplIdSubst
    
    476 482
            -- then replace occurrences of x by v
    
    477 483
            -- and  v is a join-point of arity a
    
    478 484
            --      <=> x is a join-point of arity a
    
    479 485
     
    
    480
    -  | ContEx TvSubstEnv                 -- A suspended substitution
    
    481
    -           CvSubstEnv
    
    482
    -           SimplIdSubst
    
    486
    +  | ContEx StaticEnv
    
    483 487
                InExpr
    
    484
    -      -- If   x :-> ContEx tv cv id e   is in the SimplISubst
    
    485
    -      -- then replace occurrences of x by (subst (tv,cv,id) e)
    
    488
    +           MOutCoercion   -- An /optimised/ OutCoercion
    
    489
    +      -- If   x :-> ContEx subst e co   is in the SimplISubst
    
    490
    +      -- then replace occurrences of x by ((substExpr subst e) |> co)
    
    486 491
     
    
    487
    -instance Outputable SimplSR where
    
    492
    +instance Outputable SimplClo where
    
    488 493
       ppr (DoneId v)    = text "DoneId" <+> ppr v
    
    489
    -  ppr (DoneEx e mj) = text "DoneEx" <> pp_mj <+> ppr e
    
    494
    +  ppr (DoneEx e mj) = text "DoneEx" <> pp_mj<> braces (ppr e)
    
    490 495
         where
    
    491 496
           pp_mj = case mj of
    
    492 497
                     NotJoinPoint -> empty
    
    493 498
                     JoinPoint n  -> parens (int n)
    
    494 499
     
    
    495
    -  ppr (ContEx _tv _cv _id e) = vcat [text "ContEx" <+> ppr e {-,
    
    496
    -                                ppr (filter_env tv), ppr (filter_env id) -}]
    
    500
    +  ppr (ContEx _se e mco)
    
    501
    +    = text "ContEx" <> vcat [ pprParendExpr e
    
    502
    +                            , case mco of
    
    503
    +                                 MRefl -> empty
    
    504
    +                                 MCo co -> text "|>" <+> pprOptCo co ]
    
    497 505
             -- where
    
    498 506
             -- fvs = exprFreeVars e
    
    499 507
             -- filter_env env = filterVarEnv_Directly keep env
    
    ... ... @@ -627,7 +635,7 @@ reSimplifying :: SimplEnv -> Bool
    627 635
     reSimplifying (SimplEnv { seInlineDepth = n }) = n>0
    
    628 636
     
    
    629 637
     ---------------------
    
    630
    -extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
    
    638
    +extendIdSubst :: SimplEnv -> Id -> SimplClo -> SimplEnv
    
    631 639
     extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
    
    632 640
       = assertPpr (isId var && not (isCoVar var)) (ppr var) $
    
    633 641
         env { seIdSubst = extendVarEnv subst var res }
    
    ... ... @@ -725,8 +733,8 @@ zapSubstEnv env@(SimplEnv { seInlineDepth = n })
    725 733
     setSubstEnv :: SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
    
    726 734
     setSubstEnv env tvs cvs ids = env { seTvSubst = tvs, seCvSubst = cvs, seIdSubst = ids }
    
    727 735
     
    
    728
    -mkContEx :: SimplEnv -> InExpr -> SimplSR
    
    729
    -mkContEx (SimplEnv { seTvSubst = tvs, seCvSubst = cvs, seIdSubst = ids }) e = ContEx tvs cvs ids e
    
    736
    +mkContEx :: SimplEnv -> InExpr -> SimplClo
    
    737
    +mkContEx env e = ContEx env e MRefl
    
    730 738
     
    
    731 739
     {-
    
    732 740
     ************************************************************************
    
    ... ... @@ -1011,7 +1019,7 @@ So we want to look up the inner X.g_34 in the substitution, where we'll
    1011 1019
     find that it has been substituted by b.  (Or conceivably cloned.)
    
    1012 1020
     -}
    
    1013 1021
     
    
    1014
    -substId :: SimplEnv -> InId -> SimplSR
    
    1022
    +substId :: SimplEnv -> InId -> SimplClo
    
    1015 1023
     -- Returns DoneEx only on a non-Var expression
    
    1016 1024
     substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
    
    1017 1025
       = case lookupVarEnv ids v of  -- Note [Global Ids in the substitution]
    
    ... ... @@ -1343,17 +1351,29 @@ getTCvSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seCvSubst = cv
    1343 1351
     
    
    1344 1352
     getFullSubst :: InScopeSet -> SimplEnv -> Subst
    
    1345 1353
     getFullSubst in_scope (SimplEnv { seIdSubst = id_env, seTvSubst = tv_env, seCvSubst = cv_env })
    
    1346
    -  = mk_full_subst in_scope tv_env cv_env id_env
    
    1347
    -
    
    1348
    -mk_full_subst :: InScopeSet -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> Subst
    
    1349
    -mk_full_subst in_scope tv_env cv_env id_env
    
    1350
    -  = mkSubst in_scope (mapVarEnv to_expr id_env) tv_env cv_env
    
    1351
    -  where
    
    1352
    -    to_expr :: SimplSR -> CoreExpr
    
    1353
    -    -- A tiresome impedence-matcher
    
    1354
    -    to_expr (DoneEx e _)           = e
    
    1355
    -    to_expr (DoneId v)             = Var v
    
    1356
    -    to_expr (ContEx tvs cvs ids e) = GHC.Core.Subst.substExprSC (mk_full_subst in_scope tvs cvs ids) e
    
    1354
    +  = mkSubst in_scope (mapVarEnv (simplCloExpr in_scope) id_env) tv_env cv_env
    
    1355
    +
    
    1356
    +simplCloExpr :: InScopeSet -> SimplClo -> OutExpr
    
    1357
    +simplCloExpr _        (DoneEx e _)      = e
    
    1358
    +simplCloExpr _        (DoneId v)        = Var v
    
    1359
    +simplCloExpr in_scope (ContEx se e mco) = mkCastMCo e' mco
    
    1360
    +      where
    
    1361
    +        e' = GHC.Core.Subst.substExpr (getFullSubst in_scope se) e
    
    1362
    +        -- Make sure we apply the static environment `sc_env` as a substitution
    
    1363
    +        --   to get an OutExpr.  See (BF1) in Note [tryRules: plan (BEFORE)]
    
    1364
    +        --   in GHC.Core.Opt.Simplify.Iteration
    
    1365
    +        -- NB: we use substExpr, not substExprSC: we want to get the benefit of
    
    1366
    +        --     knowing what is evaluated etc, via the in-scope set
    
    1367
    +
    
    1368
    +simplCloCoercion_maybe :: SimplClo -> Maybe OutCoercion
    
    1369
    +-- If the closure is just a coercion, give it to me
    
    1370
    +simplCloCoercion_maybe clo
    
    1371
    +  = case clo of
    
    1372
    +      DoneEx (Coercion co) _        -> Just co
    
    1373
    +      ContEx se (Coercion co) MRefl -> Just (substCo se co)
    
    1374
    +                                          -- Do we ever cast a coercion??
    
    1375
    +      DoneId {} -> Nothing  -- Coercion variables never occur naked
    
    1376
    +      _         -> Nothing
    
    1357 1377
     
    
    1358 1378
     substTy :: HasDebugCallStack => SimplEnv -> Type -> Type
    
    1359 1379
     substTy env ty = Type.substTy (getTCvSubst env) ty
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -278,8 +278,8 @@ simplRecOrTopPair :: SimplEnv
    278 278
                       -> SimplM (SimplFloats, SimplEnv)
    
    279 279
     
    
    280 280
     simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
    
    281
    -  | Just env' <- preInlineUnconditionally env (bindContextLevel bind_cxt)
    
    282
    -                                          old_bndr rhs env
    
    281
    +  | Just env' <- preInlineLetUnconditionally env (bindContextLevel bind_cxt)
    
    282
    +                                             old_bndr rhs env
    
    283 283
       = {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
    
    284 284
         simplTrace "SimplBindr:inline-uncond1" (ppr old_bndr) $
    
    285 285
         do { tick (PreInlineUnconditionally old_bndr)
    
    ... ... @@ -1211,7 +1211,7 @@ simplExprF1 env (App fun arg) cont
    1211 1211
               -- observed the quadratic behavior, so this extra entanglement
    
    1212 1212
               -- seems not worthwhile.
    
    1213 1213
             simplExprF env fun $
    
    1214
    -        ApplyToVal { sc_arg = arg, sc_env = env
    
    1214
    +        ApplyToVal { sc_arg = mkContEx env arg
    
    1215 1215
                        , sc_hole_ty = substTy env (exprType fun)
    
    1216 1216
                        , sc_dup = NoDup, sc_cont = cont }
    
    1217 1217
     
    
    ... ... @@ -1249,7 +1249,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont
    1249 1249
         do { ty' <- simplType env ty
    
    1250 1250
            ; simplExprF (extendTvSubst env bndr ty') body cont }
    
    1251 1251
     
    
    1252
    -  | Just env' <- preInlineUnconditionally env NotTopLevel bndr rhs env
    
    1252
    +  | Just env' <- preInlineLetUnconditionally env NotTopLevel bndr rhs env
    
    1253 1253
         -- Because of the let-can-float invariant, it's ok to
    
    1254 1254
         -- inline freely, or to drop the binding if it is dead.
    
    1255 1255
       = do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr) $
    
    ... ... @@ -1266,7 +1266,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont
    1266 1266
     
    
    1267 1267
       | otherwise
    
    1268 1268
       = {-#SCC "simplNonRecE" #-}
    
    1269
    -    simplNonRecE env FromLet bndr (rhs, env) body cont
    
    1269
    +    simplNonRecE env FromLet bndr (mkContEx env rhs) body cont
    
    1270 1270
     
    
    1271 1271
     {- Note [Avoiding space leaks in OutType]
    
    1272 1272
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1549,10 +1549,9 @@ rebuild_go env expr cont
    1549 1549
           ApplyToTy  { sc_arg_ty = ty, sc_cont = cont}
    
    1550 1550
             -> rebuild_go env (App expr (Type ty)) cont
    
    1551 1551
     
    
    1552
    -      ApplyToVal { sc_arg = arg, sc_env = se, sc_dup = dup_flag
    
    1553
    -                 , sc_cont = cont, sc_hole_ty = fun_ty }
    
    1552
    +      ApplyToVal { sc_arg = arg_clo, sc_cont = cont, sc_hole_ty = fun_ty }
    
    1554 1553
             -- See Note [Avoid redundant simplification]
    
    1555
    -        -> do { (_, _, arg') <- simplLazyArg env dup_flag fun_ty Nothing se arg
    
    1554
    +        -> do { arg' <- simplClo env fun_ty Nothing arg_clo
    
    1556 1555
                   ; rebuild_go env (App expr arg') cont }
    
    1557 1556
     
    
    1558 1557
     completeBindX :: SimplEnv
    
    ... ... @@ -1709,7 +1708,7 @@ simplCast env body co0 cont0
    1709 1708
             -- where   co :: (s1->s2) ~ (t1->t2)
    
    1710 1709
             --         co1 :: t1 ~ s1
    
    1711 1710
             --         co2 :: s2 ~ t2
    
    1712
    -        addCoerce co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1711
    +        addCoerce co co_is_opt cont@(ApplyToVal { sc_arg = arg_clo
    
    1713 1712
                                                     , sc_dup = dup, sc_cont = tail
    
    1714 1713
                                                     , sc_hole_ty = fun_ty })
    
    1715 1714
               | not co_is_opt  -- pushCoValArg duplicates the coercion, so optimise first
    
    ... ... @@ -1724,15 +1723,13 @@ simplCast env body co0 cont0
    1724 1723
                           -- See Note [Avoiding simplifying repeatedly]
    
    1725 1724
     
    
    1726 1725
                        MCo co1 ->
    
    1727
    -            do { (dup', arg_se', arg') <- simplLazyArg env dup fun_ty Nothing arg_se arg
    
    1728
    -                    -- When we build the ApplyTo we can't mix the OutCoercion
    
    1729
    -                    -- 'co' with the InExpr 'arg', so we simplify
    
    1730
    -                    -- to make it all consistent.  It's a bit messy.
    
    1731
    -                    -- But it isn't a common case.
    
    1732
    -                    -- Example of use: #995
    
    1733
    -               ; return (ApplyToVal { sc_arg  = mkCast arg' co1
    
    1734
    -                                    , sc_env  = arg_se'
    
    1735
    -                                    , sc_dup  = dup'
    
    1726
    +            do { let arg_clo' = case arg_clo of
    
    1727
    +                                 DoneId v        -> DoneEx (Cast (Var v) co1) NotJoinPoint
    
    1728
    +                                 DoneEx e _jp    -> DoneEx (Cast e       co1) NotJoinPoint
    
    1729
    +                                 ContEx se e mco -> ContEx se e (mkTransMCoL mco co1)
    
    1730
    +
    
    1731
    +               ; return (ApplyToVal { sc_arg  = arg_clo'
    
    1732
    +                                    , sc_dup  = dup
    
    1736 1733
                                         , sc_cont = tail'
    
    1737 1734
                                         , sc_hole_ty = coercionLKind co }) } } }
    
    1738 1735
     
    
    ... ... @@ -1742,28 +1739,25 @@ simplCast env body co0 cont0
    1742 1739
                                            -- See Note [Optimising reflexivity]
    
    1743 1740
               | otherwise = return (CastIt { sc_co = co, sc_opt = co_is_opt, sc_cont = cont })
    
    1744 1741
     
    
    1745
    -simplLazyArg :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1746
    -             -> DupFlag
    
    1747
    -             -> OutType                 -- ^ Type of the function applied to this arg
    
    1748
    -             -> Maybe ArgInfo           -- ^ Just <=> This arg `ai` occurs in an app
    
    1749
    -                                        --   `f a1 ... an` where we have ArgInfo on
    
    1750
    -                                        --   how `f` uses `ai`, affecting the Stop
    
    1751
    -                                        --   continuation passed to 'simplExprC'
    
    1752
    -             -> StaticEnv -> CoreExpr   -- ^ Expression with its static envt
    
    1753
    -             -> SimplM (DupFlag, StaticEnv, OutExpr)
    
    1754
    -simplLazyArg env dup_flag fun_ty mb_arg_info arg_env arg
    
    1755
    -  | isSimplified dup_flag
    
    1756
    -  = return (dup_flag, arg_env, arg)
    
    1757
    -  | otherwise
    
    1758
    -  = do { let arg_env' = arg_env `setInScopeFromE` env
    
    1759
    -       ; let arg_ty = funArgTy fun_ty
    
    1760
    -       ; let stop = case mb_arg_info of
    
    1761
    -               Nothing -> mkBoringStop arg_ty
    
    1762
    -               Just ai -> mkLazyArgStop arg_ty ai
    
    1763
    -       ; arg' <- simplExprC arg_env' arg stop
    
    1764
    -       ; return (Simplified, zapSubstEnv arg_env', arg') }
    
    1765
    -         -- Return a StaticEnv that includes the in-scope set from 'env',
    
    1766
    -         -- because arg' may well mention those variables (#20639)
    
    1742
    +simplClo :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1743
    +         -> OutType                 -- ^ Type of the function applied to this arg
    
    1744
    +         -> Maybe ArgInfo           -- ^ Just <=> This arg `ai` occurs in an app
    
    1745
    +                                    --   `f a1 ... an` where we have ArgInfo on
    
    1746
    +                                    --   how `f` uses `ai`, affecting the Stop
    
    1747
    +                                    --   continuation passed to 'simplExprC'
    
    1748
    +         -> SimplClo
    
    1749
    +         -> SimplM OutExpr
    
    1750
    +simplClo env fun_ty mb_arg_info (ContEx arg_se arg mco)
    
    1751
    +  = simplExprC arg_env arg stop
    
    1752
    +  where
    
    1753
    +    arg_env = arg_se `setInScopeFromE` env
    
    1754
    +    arg_ty  = funArgTy fun_ty
    
    1755
    +    stop    = case mb_arg_info of
    
    1756
    +                 Nothing -> mkBoringStop arg_ty
    
    1757
    +                 Just ai -> mkLazyArgStop arg_ty ai
    
    1758
    +
    
    1759
    +simplClo _ _ _ (DoneEx e _) = return e
    
    1760
    +simplClo _ _ _ (DoneId v)   = return (Var v)
    
    1767 1761
     
    
    1768 1762
     {-
    
    1769 1763
     ************************************************************************
    
    ... ... @@ -1797,16 +1791,15 @@ simpl_lam env bndr body (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = cont })
    1797 1791
            ; simplLam (extendTvSubst env bndr arg_ty) body cont }
    
    1798 1792
     
    
    1799 1793
     -- Coercion beta-reduction
    
    1800
    -simpl_lam env bndr body (ApplyToVal { sc_arg = Coercion arg_co, sc_env = arg_se
    
    1801
    -                                    , sc_cont = cont })
    
    1794
    +simpl_lam env bndr body (ApplyToVal { sc_arg = arg_clo, sc_cont = cont })
    
    1795
    +  | Just out_co <- simplCloCoercion_maybe arg_clo
    
    1802 1796
       = assertPpr (isCoVar bndr) (ppr bndr) $
    
    1803 1797
         do { tick (BetaReduction bndr)
    
    1804
    -       ; let arg_co' = substCo (arg_se `setInScopeFromE` env) arg_co
    
    1805
    -       ; simplLam (extendCvSubst env bndr arg_co') body cont }
    
    1798
    +       ; simplLam (extendCvSubst env bndr out_co) body cont }
    
    1806 1799
     
    
    1807 1800
     -- Value beta-reduction
    
    1808 1801
     -- This works for /coercion/ lambdas too
    
    1809
    -simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1802
    +simpl_lam env bndr body (ApplyToVal { sc_arg = arg_clo
    
    1810 1803
                                         , sc_cont = cont, sc_dup = dup
    
    1811 1804
                                         , sc_hole_ty = fun_ty})
    
    1812 1805
       = do { tick (BetaReduction bndr)
    
    ... ... @@ -1823,24 +1816,13 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
    1823 1816
                  --      It's wrong to err in either direction
    
    1824 1817
                  --      But fun_ty is an OutType, so is fully substituted
    
    1825 1818
     
    
    1826
    -       ; if | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg arg_se
    
    1827
    -            , not (needsCaseBindingL arg_levity arg)
    
    1828
    -              -- Ok to test arg::InExpr in needsCaseBinding because
    
    1829
    -              -- exprOkForSpeculation is stable under simplification
    
    1830
    -            , not ( isSimplified dup &&  -- See (SR2) in Note [Avoiding simplifying repeatedly]
    
    1831
    -                    not (exprIsTrivial arg) &&
    
    1832
    -                    not (isDeadOcc (idOccInfo bndr)) )
    
    1819
    +       ; if | Just env' <- preInlineBetaUnconditionally env arg_levity bndr arg_clo
    
    1833 1820
                 -> do { simplTrace "SimplBindr:inline-uncond3" (ppr bndr) $
    
    1834 1821
                         tick (PreInlineUnconditionally bndr)
    
    1835 1822
                       ; simplLam env' body cont }
    
    1836 1823
     
    
    1837
    -            | isSimplified dup  -- Don't re-simplify if we've simplified it once
    
    1838
    -                                -- Including don't preInlineUnconditionally
    
    1839
    -                                -- See Note [Avoiding simplifying repeatedly]
    
    1840
    -            -> completeBindX env from_what bndr arg body cont
    
    1841
    -
    
    1842 1824
                 | otherwise
    
    1843
    -            -> simplNonRecE env from_what bndr (arg, arg_se) body cont }
    
    1825
    +            -> simplNonRecE env from_what bndr arg_clo body cont }
    
    1844 1826
     
    
    1845 1827
     -- Discard a non-counting tick on a lambda.  This may change the
    
    1846 1828
     -- cost attribution slightly (moving the allocation of the
    
    ... ... @@ -1876,8 +1858,7 @@ simplNonRecE :: HasDebugCallStack
    1876 1858
                  -> FromWhat
    
    1877 1859
                  -> InId               -- The binder, always an Id
    
    1878 1860
                                        -- Never a join point
    
    1879
    -                                   -- The static env for its unfolding (if any) is the first parameter
    
    1880
    -             -> (InExpr, SimplEnv) -- Rhs of binding (or arg of lambda)
    
    1861
    +             -> SimplClo           -- Rhs of binding (or arg of lambda)
    
    1881 1862
                  -> InExpr             -- Body of the let/lambda
    
    1882 1863
                  -> SimplCont
    
    1883 1864
                  -> SimplM (SimplFloats, OutExpr)
    
    ... ... @@ -1896,7 +1877,14 @@ simplNonRecE :: HasDebugCallStack
    1896 1877
     -- from_what=FromLet => the RHS satisfies the let-can-float invariant
    
    1897 1878
     -- Otherwise it may or may not satisfy it.
    
    1898 1879
     
    
    1899
    -simplNonRecE env from_what bndr (rhs, rhs_se) body cont
    
    1880
    +simplNonRecE env from_what bndr (DoneEx rhs jp) body cont
    
    1881
    +  = assertPpr (jp == NotJoinPoint) (ppr bndr) $
    
    1882
    +    completeBindX env from_what bndr rhs body cont
    
    1883
    +
    
    1884
    +simplNonRecE env from_what bndr (DoneId v) body cont
    
    1885
    +  = completeBindX env from_what bndr (Var v) body cont
    
    1886
    +
    
    1887
    +simplNonRecE env from_what bndr (ContEx rhs_se rhs mco) body cont
    
    1900 1888
       | assert (isId bndr && not (isJoinId bndr) ) $
    
    1901 1889
         is_strict_bind
    
    1902 1890
       = -- Evaluate RHS strictly
    
    ... ... @@ -2237,10 +2225,10 @@ simplInVar env var
    2237 2225
       | isCoVar var = return $! Coercion $! (substCoVar env var)
    
    2238 2226
       | otherwise
    
    2239 2227
       = case substId env var of
    
    2240
    -        ContEx tvs cvs ids e -> let env' = setSubstEnv env tvs cvs ids
    
    2241
    -                                in simplExpr env' e
    
    2242
    -        DoneId var1          -> return (Var var1)
    
    2243
    -        DoneEx e _           -> return e
    
    2228
    +        ContEx se e mco -> do { e' <- simplExpr (se `setInScopeFromE` env) e
    
    2229
    +                              ; return (mkCastMCo e' mco) }
    
    2230
    +        DoneId var1     -> return (Var var1)
    
    2231
    +        DoneEx e _      -> return e
    
    2244 2232
     
    
    2245 2233
     simplInId :: SimplEnv -> InId -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    2246 2234
     simplInId env var cont
    
    ... ... @@ -2249,19 +2237,16 @@ simplInId env var cont
    2249 2237
       = rebuild zapped_env (Var var) cont
    
    2250 2238
       | otherwise
    
    2251 2239
       = case substId env var of
    
    2252
    -      ContEx tvs cvs ids e -> simplExprF env' e cont
    
    2253
    -        -- Don't trimJoinCont; haven't already simplified e,
    
    2240
    +      ContEx se e mco -> do { e' <- simplExprF (se `setInScopeFromE` env) e cont
    
    2241
    +                            ; return (mkCastMCo e' mco) }
    
    2242
    +        -- Don't trimJoinCont; we haven't already simplified e,
    
    2254 2243
             -- so the cont is not embodied in e
    
    2255
    -        where
    
    2256
    -          env' = setSubstEnv env tvs cvs ids
    
    2257 2244
     
    
    2258
    -      DoneId out_id -> simplOutId zapped_env out_id cont'
    
    2259
    -        where
    
    2260
    -          cont' = trimJoinCont out_id (idJoinPointHood out_id) cont
    
    2245
    +      DoneId out_id -> simplOutId zapped_env out_id $
    
    2246
    +                       trimJoinCont out_id (idJoinPointHood out_id) cont
    
    2261 2247
     
    
    2262
    -      DoneEx e mb_join -> simplExprF zapped_env e cont'
    
    2263
    -        where
    
    2264
    -          cont' = trimJoinCont var mb_join cont
    
    2248
    +      DoneEx e mb_join -> simplExprF zapped_env e $
    
    2249
    +                          trimJoinCont var mb_join cont
    
    2265 2250
       where
    
    2266 2251
         zapped_env =  zapSubstEnv env  -- See Note [zapSubstEnv]
    
    2267 2252
     
    
    ... ... @@ -2277,8 +2262,8 @@ simplOutId env fun cont
    2277 2262
       | fun `hasKey` runRWKey
    
    2278 2263
       , ApplyToTy  { sc_cont = cont1 } <- cont
    
    2279 2264
       , ApplyToTy  { sc_cont = cont2, sc_arg_ty = hole_ty } <- cont1
    
    2280
    -  , ApplyToVal { sc_cont = cont3, sc_arg = arg
    
    2281
    -               , sc_env = arg_se, sc_hole_ty = fun_ty } <- cont2
    
    2265
    +  , ApplyToVal { sc_cont = cont3, sc_arg = arg_clo
    
    2266
    +               , sc_hole_ty = fun_ty } <- cont2
    
    2282 2267
       -- Do this even if (contIsStop cont), or if seCaseCase is off.
    
    2283 2268
       -- See Note [No eta-expansion in runRW#]
    
    2284 2269
       = do { let arg_env = arg_se `setInScopeFromE` env
    
    ... ... @@ -2306,8 +2291,8 @@ simplOutId env fun cont
    2306 2291
                _ -> do { s' <- newId (fsLit "s") ManyTy realWorldStatePrimTy
    
    2307 2292
                        ; let (m,_,_) = splitFunTy fun_ty
    
    2308 2293
                              env'  = arg_env `addNewInScopeIds` [s']
    
    2309
    -                         cont' = ApplyToVal { sc_dup = Simplified, sc_arg = Var s'
    
    2310
    -                                            , sc_env = env', sc_cont = inner_cont
    
    2294
    +                         cont' = ApplyToVal { sc_dup = Dupable, sc_arg = DoneId s'
    
    2295
    +                                            , sc_cont = inner_cont
    
    2311 2296
                                                 , sc_hole_ty = mkVisFunTy m realWorldStatePrimTy new_runrw_res_ty }
    
    2312 2297
                                     -- cont' applies to s', then K
    
    2313 2298
                        ; body' <- simplExprC env' arg cont'
    
    ... ... @@ -2386,32 +2371,36 @@ rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_c
    2386 2371
     
    
    2387 2372
     ---------- Simplify value arguments --------------------
    
    2388 2373
     rebuildCall env fun_info
    
    2389
    -            (ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    2374
    +            (ApplyToVal { sc_arg = arg_clo
    
    2390 2375
                             , sc_dup = dup_flag, sc_hole_ty = fun_ty
    
    2391 2376
                             , sc_cont = cont })
    
    2392
    -  -- Argument is already simplified
    
    2393
    -  | isSimplified dup_flag     -- See Note [Avoid redundant simplification]
    
    2394
    -  = rebuildCall env (addValArgTo fun_info arg fun_ty) cont
    
    2395
    -
    
    2396
    -  -- Strict arguments
    
    2397
    -  | isStrictArgInfo fun_info
    
    2398
    -  , seCaseCase env    -- Only when case-of-case is on. See GHC.Driver.Config.Core.Opt.Simplify
    
    2399
    -                      --    Note [Case-of-case and full laziness]
    
    2400
    -  = -- pprTrace "Strict Arg" (ppr arg $$ ppr (seIdSubst env) $$ ppr (seInScope env)) $
    
    2401
    -    simplExprF (arg_se `setInScopeFromE` env) arg
    
    2402
    -               (StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
    
    2403
    -                          , sc_dup = Simplified
    
    2404
    -                          , sc_cont = cont })
    
    2377
    +  = case arg_clo of      -- See Note [Avoid redundant simplification]
    
    2378
    +      DoneId v     -> rebuildCall env (addValArgTo fun_info (Var v) fun_ty) cont
    
    2379
    +      DoneEx arg _ -> rebuildCall env (addValArgTo fun_info arg     fun_ty) cont
    
    2380
    +      ContEx arg_se in_arg mco
    
    2381
    +        -- Strict arguments
    
    2382
    +        | isStrictArgInfo fun_info
    
    2383
    +        , seCaseCase env    -- Only when case-of-case is on. See GHC.Driver.Config.Core.Opt.Simplify
    
    2384
    +                            --    Note [Case-of-case and full laziness]
    
    2385
    +        -> simplExprF (arg_se `setInScopeFromE` env) in_arg
    
    2386
    +               (add_cast mco $
    
    2387
    +                StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
    
    2388
    +                          , sc_dup = NoDup, sc_cont = cont })
    
    2405 2389
                     -- Note [Shadowing in the Simplifier]
    
    2406 2390
     
    
    2407
    -  -- Lazy arguments
    
    2408
    -  | otherwise
    
    2391
    +        -- Lazy arguments
    
    2392
    +        | otherwise
    
    2409 2393
             -- DO NOT float anything outside, hence simplExprC
    
    2410 2394
             -- There is no benefit (unlike in a let-binding), and we'd
    
    2411 2395
             -- have to be very careful about bogus strictness through
    
    2412 2396
             -- floating a demanded let.
    
    2413
    -  = do  { (_, _, arg') <- simplLazyArg env dup_flag fun_ty (Just fun_info) arg_se arg
    
    2414
    -        ; rebuildCall env (addValArgTo fun_info  arg' fun_ty) cont }
    
    2397
    +        -> do { arg' <- simplClo env fun_ty (Just fun_info) arg_clo
    
    2398
    +              ; rebuildCall env (addValArgTo fun_info  arg' fun_ty) cont }
    
    2399
    +
    
    2400
    +  where
    
    2401
    +    add_cast MRefl    cont = cont
    
    2402
    +    add_cast (MCo co) cont = CastIt { sc_co = co, sc_opt = True, sc_cont = cont }
    
    2403
    +
    
    2415 2404
     
    
    2416 2405
     ---------- No further useful info, revert to generic rebuild ------------
    
    2417 2406
     rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_rules = rules }) cont
    
    ... ... @@ -2436,7 +2425,7 @@ tryInlining env logger var cont
    2436 2425
       = return Nothing
    
    2437 2426
     
    
    2438 2427
       where
    
    2439
    -    (lone_variable, arg_infos, call_cont) = contArgs cont
    
    2428
    +    (lone_variable, arg_infos, call_cont) = contArgs env cont
    
    2440 2429
         interesting_cont = interestingCallContext env call_cont
    
    2441 2430
     
    
    2442 2431
         log_inlining doc
    
    ... ... @@ -2644,7 +2633,7 @@ tryRules env rules fn args
    2644 2633
             --, text "Rule activation:" <+> ppr (ruleActivation rule)
    
    2645 2634
               , text "Full arity:" <+>  ppr (ruleArity rule)
    
    2646 2635
               , text "Before:" <+> hang (ppr fn) 2 (sep (map ppr args))
    
    2647
    -          , text "After: " <+> pprCoreExpr rule_rhs ]
    
    2636
    +          , text "After: " <+> mkApps (pprCoreExpr rule_rhs) (drop (ruleArity rule) args) ]
    
    2648 2637
     
    
    2649 2638
           | logHasDumpFlag logger Opt_D_dump_rule_firings
    
    2650 2639
           = log_rule Opt_D_dump_rule_firings "Rule fired:" $
    
    ... ... @@ -2713,8 +2702,8 @@ trySeqRules in_env scrut rhs cont
    2713 2702
                          , ValArg { as_arg = no_cast_scrut
    
    2714 2703
                                   , as_dmd = seqDmd
    
    2715 2704
                                   , as_hole_ty = res3_ty } ]
    
    2716
    -    rule_cont = ApplyToVal { sc_dup = NoDup, sc_arg = rhs
    
    2717
    -                           , sc_env = in_env, sc_cont = cont
    
    2705
    +    rule_cont = ApplyToVal { sc_dup = NoDup, sc_arg = mkContEx in_env rhs
    
    2706
    +                           , sc_cont = cont
    
    2718 2707
                                , sc_hole_ty = res4_ty }
    
    2719 2708
     
    
    2720 2709
         -- Lazily evaluated, so we don't do most of this
    
    ... ... @@ -3941,7 +3930,7 @@ mkDupableContWithDmds env dmds
    3941 3930
                                         , sc_arg_ty = arg_ty, sc_hole_ty = hole_ty }) }
    
    3942 3931
     
    
    3943 3932
     mkDupableContWithDmds env dmds
    
    3944
    -    (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_env = se
    
    3933
    +    (ApplyToVal { sc_arg = arg_clo, sc_dup = dup
    
    3945 3934
                     , sc_cont = cont, sc_hole_ty = hole_ty })
    
    3946 3935
       =     -- e.g.         [...hole...] (...arg...)
    
    3947 3936
             --      ==>
    
    ... ... @@ -3951,16 +3940,11 @@ mkDupableContWithDmds env dmds
    3951 3940
         do  { let dmd:|cont_dmds = expectNonEmpty dmds
    
    3952 3941
             ; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
    
    3953 3942
             ; let env' = env `setInScopeFromF` floats1
    
    3954
    -        ; (_, se', arg') <- simplLazyArg env' dup hole_ty Nothing se arg
    
    3943
    +        ; arg' <- simplClo env' hole_ty Nothing arg_clo
    
    3955 3944
             ; (let_floats2, arg'') <- makeTrivial env NotTopLevel dmd (fsLit "karg") arg'
    
    3956 3945
             ; let all_floats = floats1 `addLetFloats` let_floats2
    
    3957 3946
             ; return ( all_floats
    
    3958
    -                 , ApplyToVal { sc_arg = arg''
    
    3959
    -                              , sc_env = se' `setInScopeFromF` all_floats
    
    3960
    -                                         -- Ensure that sc_env includes the free vars of
    
    3961
    -                                         -- arg'' in its in-scope set, even if makeTrivial
    
    3962
    -                                         -- has turned arg'' into a fresh variable
    
    3963
    -                                         -- See Note [StaticEnv invariant] in GHC.Core.Opt.Simplify.Utils
    
    3947
    +                 , ApplyToVal { sc_arg = DoneEx arg'' NotJoinPoint
    
    3964 3948
                                   , sc_dup = OkToDup, sc_cont = cont'
    
    3965 3949
                                   , sc_hole_ty = hole_ty }) }
    
    3966 3950
     
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -12,7 +12,9 @@ module GHC.Core.Opt.Simplify.Utils (
    12 12
             tryEtaExpandRhs, wantEtaExpansion,
    
    13 13
     
    
    14 14
             -- Inlining,
    
    15
    -        preInlineUnconditionally, postInlineUnconditionally,
    
    15
    +        preInlineLetUnconditionally,
    
    16
    +        preInlineBetaUnconditionally,
    
    17
    +        postInlineUnconditionally,
    
    16 18
             activeRule,
    
    17 19
             getUnfoldingInRuleMatch,
    
    18 20
             updModeForStableUnfoldings, updModeForRuleLHS, updModeForRuleRHS,
    
    ... ... @@ -173,8 +175,7 @@ data SimplCont
    173 175
           { sc_dup     :: DupFlag   -- See Note [DupFlag invariants]
    
    174 176
           , sc_hole_ty :: OutType   -- Type of the function, presumably (forall a. blah)
    
    175 177
                                     -- See Note [The hole type in ApplyToTy]
    
    176
    -      , sc_arg  :: InExpr       -- The argument,
    
    177
    -      , sc_env  :: StaticEnv    -- see Note [StaticEnv invariant]
    
    178
    +      , sc_arg  :: SimplClo     -- The argument
    
    178 179
           , sc_cont :: SimplCont }
    
    179 180
     
    
    180 181
       | ApplyToTy          -- (ApplyToTy ty K)[e] = K[ e ty ]
    
    ... ... @@ -216,23 +217,17 @@ data SimplCont
    216 217
             CoreTickish     -- Tick tickish <hole>
    
    217 218
             SimplCont
    
    218 219
     
    
    219
    -type StaticEnv = SimplEnv       -- Just the static part is relevant
    
    220 220
     
    
    221 221
     data FromWhat = FromLet | FromBeta Levity
    
    222 222
     
    
    223 223
     -- See Note [DupFlag invariants]
    
    224 224
     data DupFlag = NoDup       -- Unsimplified, might be big
    
    225
    -             | Simplified  -- Simplified
    
    226 225
                  | OkToDup     -- Simplified and small
    
    227 226
     
    
    228 227
     isSimplified :: DupFlag -> Bool
    
    229 228
     isSimplified NoDup = False
    
    230 229
     isSimplified _     = True       -- Invariant: the subst-env is empty
    
    231 230
     
    
    232
    -perhapsSubstTy :: DupFlag -> StaticEnv -> Type -> Type
    
    233
    -perhapsSubstTy dup env ty
    
    234
    -  | isSimplified dup = ty
    
    235
    -  | otherwise        = substTy env ty
    
    236 231
     
    
    237 232
     {- Note [StaticEnv invariant]
    
    238 233
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -255,21 +250,16 @@ the expression, and that (rightly) gives ASSERT failures if the InScopeSet
    255 250
     isn't big enough.
    
    256 251
     
    
    257 252
     Note [DupFlag invariants]
    
    258
    -~~~~~~~~~~~~~~~~~~~~~~~~~
    
    253
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    259 254
     In both ApplyToVal { se_dup = dup, se_env = env, se_cont = k}
    
    260 255
        and  Select { se_dup = dup, se_env = env, se_cont = k}
    
    261
    -the following invariants hold
    
    262
    -
    
    263
    -  (a) if dup = OkToDup, then continuation k is also ok-to-dup
    
    264
    -  (b) if dup = OkToDup or Simplified, the subst-env is empty,
    
    265
    -               or at least is always ignored; the payload is
    
    266
    -               already an OutThing
    
    256
    +the following invariant holds
    
    257
    +  if dup = OkToDup, then continuation k is also ok-to-dup
    
    267 258
     -}
    
    268 259
     
    
    269 260
     instance Outputable DupFlag where
    
    270 261
       ppr OkToDup    = text "ok"
    
    271 262
       ppr NoDup      = text "nodup"
    
    272
    -  ppr Simplified = text "simpl"
    
    273 263
     
    
    274 264
     instance Outputable SimplCont where
    
    275 265
       ppr (Stop ty interesting eval_sd)
    
    ... ... @@ -284,7 +274,7 @@ instance Outputable SimplCont where
    284 274
         = (text "ApplyToTy" <+> pprParendType ty) $$ ppr cont
    
    285 275
       ppr (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_cont = cont, sc_hole_ty = hole_ty })
    
    286 276
         = (hang (text "ApplyToVal" <+> ppr dup <+> text "hole-ty:" <+> pprParendType hole_ty)
    
    287
    -          2 (pprParendExpr arg))
    
    277
    +          2 (ppr arg))
    
    288 278
           $$ ppr cont
    
    289 279
       ppr (StrictBind { sc_bndr = b, sc_cont = cont })
    
    290 280
         = (text "StrictBind" <+> ppr b) $$ ppr cont
    
    ... ... @@ -392,9 +382,8 @@ pushSimplifiedArgs env args cont = foldr (pushSimplifiedArg env) cont args
    392 382
     pushSimplifiedArg :: SimplEnv -> ArgSpec -> SimplCont -> SimplCont
    
    393 383
     pushSimplifiedArg _env (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
    
    394 384
       = ApplyToTy  { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont }
    
    395
    -pushSimplifiedArg env (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
    
    396
    -  = ApplyToVal { sc_arg = arg, sc_env = env, sc_dup = Simplified
    
    397
    -                 -- The SubstEnv will be ignored since sc_dup=Simplified
    
    385
    +pushSimplifiedArg _env (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
    
    386
    +  = ApplyToVal { sc_arg = DoneEx arg NotJoinPoint, sc_dup = NoDup
    
    398 387
                    , sc_hole_ty = hole_ty, sc_cont = cont }
    
    399 388
     
    
    400 389
     argSpecArg :: ArgSpec -> OutExpr
    
    ... ... @@ -475,14 +464,17 @@ contHoleType :: SimplCont -> OutType
    475 464
     contHoleType (Stop ty _ _)                    = ty
    
    476 465
     contHoleType (TickIt _ k)                     = contHoleType k
    
    477 466
     contHoleType (CastIt { sc_co = co })          = coercionLKind co
    
    478
    -contHoleType (StrictBind { sc_bndr = b, sc_dup = dup, sc_env = se })
    
    479
    -  = perhapsSubstTy dup se (idType b)
    
    480 467
     contHoleType (StrictArg  { sc_fun_ty = ty })  = funArgTy ty
    
    481 468
     contHoleType (ApplyToTy  { sc_hole_ty = ty }) = ty  -- See Note [The hole type in ApplyToTy]
    
    482 469
     contHoleType (ApplyToVal { sc_hole_ty = ty }) = ty  -- See Note [The hole type in ApplyToTy]
    
    483
    -contHoleType (Select { sc_dup = d, sc_bndr =  b, sc_env = se })
    
    484
    -  = perhapsSubstTy d se (idType b)
    
    470
    +contHoleType (StrictBind { sc_bndr = b, sc_dup = d, sc_env = se }) = perhapsSubstIdTy d se b
    
    471
    +contHoleType (Select     { sc_bndr = b, sc_dup = d, sc_env = se }) = perhapsSubstIdTy d se b
    
    485 472
     
    
    473
    +perhapsSubstIdTy :: DupFlag -> StaticEnv -> Id -> Type
    
    474
    +perhapsSubstIdTy dup_flag env bndr
    
    475
    +  = case dup_flag of
    
    476
    +      OkToDup -> idType bndr                -- The Id is an OutId
    
    477
    +      NoDup   -> substTy env (idType bndr)  -- The Id is an InId
    
    486 478
     
    
    487 479
     -- Computes the multiplicity scaling factor at the hole. That is, in (case [] of
    
    488 480
     -- x ::(p) _ { … }) (respectively for arguments of functions), the scaling
    
    ... ... @@ -525,11 +517,11 @@ countValArgs (CastIt { sc_cont = cont }) = countValArgs cont
    525 517
     countValArgs _                               = 0
    
    526 518
     
    
    527 519
     -------------------
    
    528
    -contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
    
    520
    +contArgs :: SimplEnv -> SimplCont -> (Bool, [ArgSummary], SimplCont)
    
    529 521
     -- Summarises value args, discards type args and coercions
    
    530 522
     -- The returned continuation of the call is only used to
    
    531 523
     -- answer questions like "are you interesting?"
    
    532
    -contArgs cont
    
    524
    +contArgs env cont
    
    533 525
       | lone cont = (True, [], cont)
    
    534 526
       | otherwise = go [] cont
    
    535 527
       where
    
    ... ... @@ -538,34 +530,22 @@ contArgs cont
    538 530
         lone (CastIt {})     = False  --     stops it being "lone"
    
    539 531
         lone _               = True
    
    540 532
     
    
    541
    -    go args (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = k })
    
    542
    -                                        = go (is_interesting arg se : args) k
    
    533
    +    go args (ApplyToVal { sc_arg = arg_clo, sc_cont = k })
    
    534
    +                                        = go (interestingArg env arg_clo : args) k
    
    543 535
         go args (ApplyToTy { sc_cont = k }) = go args k
    
    544 536
         go args (CastIt { sc_cont = k })    = go args k
    
    545 537
         go args k                           = (False, reverse args, k)
    
    546 538
     
    
    547
    -    is_interesting arg se = interestingArg se arg
    
    548
    -                   -- Do *not* use short-cutting substitution here
    
    549
    -                   -- because we want to get as much IdInfo as possible
    
    550
    -
    
    551 539
     contOutArgs :: SimplEnv -> SimplCont -> [OutExpr]
    
    552 540
     -- Get the leading arguments from the `SimplCont`, as /OutExprs/
    
    553 541
     contOutArgs env cont
    
    554 542
       = go cont
    
    555 543
       where
    
    556
    -    in_scope = seInScope env
    
    557
    -
    
    558 544
         go (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
    
    559 545
           = Type ty : go cont
    
    560 546
     
    
    561
    -    go (ApplyToVal { sc_dup = dup, sc_arg = arg, sc_env = env, sc_cont = cont })
    
    562
    -      | isSimplified dup = arg : go cont
    
    563
    -      | otherwise        = GHC.Core.Subst.substExpr (getFullSubst in_scope env) arg : go cont
    
    564
    -        -- Make sure we apply the static environment `sc_env` as a substitution
    
    565
    -        --   to get an OutExpr.  See (BF1) in Note [tryRules: plan (BEFORE)]
    
    566
    -        --   in GHC.Core.Opt.Simplify.Iteration
    
    567
    -        -- NB: we use substExpr, not substExprSC: we want to get the benefit of
    
    568
    -        --     knowing what is evaluated etc, via the in-scope set
    
    547
    +    go (ApplyToVal { sc_arg = arg_clo, sc_cont = cont })
    
    548
    +      = simplCloExpr (seInScope env) arg_clo : go cont
    
    569 549
     
    
    570 550
         -- No more arguments
    
    571 551
         go _ = []
    
    ... ... @@ -993,16 +973,18 @@ rule for (*) (df d) can fire. To do this
    993 973
       b) we say that a con-like argument (eg (df d)) is interesting
    
    994 974
     -}
    
    995 975
     
    
    996
    -interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
    
    976
    +interestingArg :: SimplEnv -> SimplClo -> ArgSummary
    
    997 977
     -- See Note [Interesting arguments]
    
    998
    -interestingArg env e = go env 0 e
    
    978
    +-- Do *not* use short-cutting substitution here
    
    979
    +-- because we want to get as much IdInfo as possible
    
    980
    +interestingArg env e = go_clo env 0 e
    
    999 981
       where
    
    982
    +    go_clo _env n (DoneId v)        = go_var n v
    
    983
    +    go_clo env  n (DoneEx e _)      = go (zapSubstEnv env)         n e
    
    984
    +    go_clo env  n (ContEx se e _co) = go (se `setInScopeFromE` env) n e
    
    985
    +
    
    1000 986
         -- n is # value args to which the expression is applied
    
    1001
    -    go env n (Var v)
    
    1002
    -       = case substId env v of
    
    1003
    -           DoneId v'            -> go_var n v'
    
    1004
    -           DoneEx e _           -> go (zapSubstEnv env)             n e
    
    1005
    -           ContEx tvs cvs ids e -> go (setSubstEnv env tvs cvs ids) n e
    
    987
    +    go env n (Var v) = go_clo env n (substId env v)
    
    1006 988
     
    
    1007 989
         go _   _ (Lit l)
    
    1008 990
            | isLitRubbish l        = TrivArg -- Leads to unproductive inlining in WWRec, #20035
    
    ... ... @@ -1490,7 +1472,38 @@ is a term (not a coercion) so we can't necessarily inline the latter in
    1490 1472
     the former.
    
    1491 1473
     -}
    
    1492 1474
     
    
    1493
    -preInlineUnconditionally
    
    1475
    +
    
    1476
    +preInlineBetaUnconditionally
    
    1477
    +    :: SimplEnv -> Levity -> InId -> SimplClo
    
    1478
    +    -> Maybe SimplEnv       -- Returned env has extended substitution
    
    1479
    +preInlineBetaUnconditionally env levity bndr clo
    
    1480
    +  | not pre_inline_unconditionally = Nothing
    
    1481
    +  | isCoVar bndr                   = Nothing -- Note [Do not inline CoVars unconditionally]
    
    1482
    +  | not (one_occ (idOccInfo bndr)) = Nothing
    
    1483
    +  | needs_case_binding levity      = Nothing
    
    1484
    +  | otherwise                      = Just $! extendIdSubst env bndr clo
    
    1485
    +  where
    
    1486
    +    pre_inline_unconditionally = sePreInline env
    
    1487
    +
    
    1488
    +    one_occ OneOcc{ occ_n_br = 1, occ_in_lam = NotInsideLam }
    
    1489
    +      = True
    
    1490
    +    one_occ OneOcc{ occ_n_br = 1, occ_in_lam = IsInsideLam, occ_int_cxt = IsInteresting }
    
    1491
    +      = case clo of
    
    1492
    +          ContEx _ rhs _ -> canInlineInLam rhs
    
    1493
    +          DoneId {}      -> True
    
    1494
    +          DoneEx rhs _   -> exprIsTrivial rhs
    
    1495
    +    one_occ IAmDead = True -- Happens in ((\x.1) v)
    
    1496
    +    one_occ _       = False
    
    1497
    +
    
    1498
    +    -- NB: exprOkForSpeculation is stable under substitution
    
    1499
    +    --     so we can apply it to an InExpr in the ContEx case
    
    1500
    +    needs_case_binding Lifted   = False
    
    1501
    +    needs_case_binding Unlifted = case clo of
    
    1502
    +                                    DoneId {}    -> False
    
    1503
    +                                    DoneEx e _   -> exprOkForSpeculation e
    
    1504
    +                                    ContEx _ e _ -> exprOkForSpeculation e
    
    1505
    +
    
    1506
    +preInlineLetUnconditionally
    
    1494 1507
         :: SimplEnv -> TopLevelFlag -> InId
    
    1495 1508
         -> InExpr -> StaticEnv  -- These two go together
    
    1496 1509
         -> Maybe SimplEnv       -- Returned env has extended substitution
    
    ... ... @@ -1498,7 +1511,7 @@ preInlineUnconditionally
    1498 1511
     -- See Note [Core let-can-float invariant] in GHC.Core
    
    1499 1512
     -- Reason: we don't want to inline single uses, or discard dead bindings,
    
    1500 1513
     --         for unlifted, side-effect-ful bindings
    
    1501
    -preInlineUnconditionally env top_lvl bndr rhs rhs_env
    
    1514
    +preInlineLetUnconditionally env top_lvl bndr rhs rhs_env
    
    1502 1515
       | not pre_inline_unconditionally           = Nothing
    
    1503 1516
       | not active                               = Nothing
    
    1504 1517
       | isTopLevel top_lvl && isDeadEndId bndr   = Nothing -- Note [Top-level bottoming Ids]
    
    ... ... @@ -1516,13 +1529,12 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
    1516 1529
         unf = idUnfolding bndr
    
    1517 1530
         extend_subst_with inl_rhs = extendIdSubst env bndr $! (mkContEx rhs_env inl_rhs)
    
    1518 1531
     
    
    1532
    +    one_occ OneOcc{ occ_n_br = 1, occ_in_lam = NotInsideLam }
    
    1533
    +      = isNotTopLevel top_lvl || early_phase
    
    1534
    +    one_occ OneOcc{ occ_n_br = 1, occ_in_lam = IsInsideLam, occ_int_cxt = IsInteresting }
    
    1535
    +      = canInlineInLam rhs
    
    1519 1536
         one_occ IAmDead = True -- Happens in ((\x.1) v)
    
    1520
    -    one_occ OneOcc{ occ_n_br   = 1
    
    1521
    -                  , occ_in_lam = NotInsideLam }   = isNotTopLevel top_lvl || early_phase
    
    1522
    -    one_occ OneOcc{ occ_n_br   = 1
    
    1523
    -                  , occ_in_lam = IsInsideLam
    
    1524
    -                  , occ_int_cxt = IsInteresting } = canInlineInLam rhs
    
    1525
    -    one_occ _                                     = False
    
    1537
    +    one_occ _       = False
    
    1526 1538
     
    
    1527 1539
         pre_inline_unconditionally = sePreInline env
    
    1528 1540
         active = isActive (sePhase env)
    
    ... ... @@ -1530,38 +1542,6 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
    1530 1542
                  -- See Note [pre/postInlineUnconditionally in gentle mode]
    
    1531 1543
         inline_prag = idInlinePragma bndr
    
    1532 1544
     
    
    1533
    --- Be very careful before inlining inside a lambda, because (a) we must not
    
    1534
    --- invalidate occurrence information, and (b) we want to avoid pushing a
    
    1535
    --- single allocation (here) into multiple allocations (inside lambda).
    
    1536
    --- Inlining a *function* with a single *saturated* call would be ok, mind you.
    
    1537
    ---      || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
    
    1538
    ---      where
    
    1539
    ---              is_cheap = exprIsCheap rhs
    
    1540
    ---              ok = is_cheap && int_cxt
    
    1541
    -
    
    1542
    -        --      int_cxt         The context isn't totally boring
    
    1543
    -        -- E.g. let f = \ab.BIG in \y. map f xs
    
    1544
    -        --      Don't want to substitute for f, because then we allocate
    
    1545
    -        --      its closure every time the \y is called
    
    1546
    -        -- But: let f = \ab.BIG in \y. map (f y) xs
    
    1547
    -        --      Now we do want to substitute for f, even though it's not
    
    1548
    -        --      saturated, because we're going to allocate a closure for
    
    1549
    -        --      (f y) every time round the loop anyhow.
    
    1550
    -
    
    1551
    -        -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
    
    1552
    -        -- so substituting rhs inside a lambda doesn't change the occ info.
    
    1553
    -        -- Sadly, not quite the same as exprIsHNF.
    
    1554
    -    canInlineInLam (Lit _)    = True
    
    1555
    -    canInlineInLam (Cast e _) = canInlineInLam e
    
    1556
    -    canInlineInLam (Lam b e)  = isRuntimeVar b || canInlineInLam e
    
    1557
    -    canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
    
    1558
    -    canInlineInLam (Var v)    = case idOccInfo v of
    
    1559
    -                                  OneOcc { occ_in_lam = IsInsideLam } -> True
    
    1560
    -                                  ManyOccs {}                         -> True
    
    1561
    -                                  _                                   -> False
    
    1562
    -    canInlineInLam _          = False
    
    1563
    -      -- not ticks.  Counting ticks cannot be duplicated, and non-counting
    
    1564
    -      -- ticks around a Lam will disappear anyway.
    
    1565 1545
     
    
    1566 1546
         early_phase =
    
    1567 1547
           case sePhase env of
    
    ... ... @@ -1593,6 +1573,39 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
    1593 1573
         -- (Nor can we check for `exprIsExpandable rhs`, because that needs to look
    
    1594 1574
         -- at the non-existent unfolding for the `I# 2#` which is also floated out.)
    
    1595 1575
     
    
    1576
    +canInlineInLam :: CoreExpr -> Bool
    
    1577
    +-- Be very careful before inlining inside a lambda, because (a) we must not
    
    1578
    +-- invalidate occurrence information, and (b) we want to avoid pushing a
    
    1579
    +-- single allocation (here) into multiple allocations (inside lambda).
    
    1580
    +-- Inlining a *function* with a single *saturated* call would be ok, mind you.
    
    1581
    +--      || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
    
    1582
    +--      where
    
    1583
    +--              is_cheap = exprIsCheap rhs
    
    1584
    +--              ok = is_cheap && int_cxt
    
    1585
    +        --      int_cxt         The context isn't totally boring
    
    1586
    +        -- E.g. let f = \ab.BIG in \y. map f xs
    
    1587
    +        --      Don't want to substitute for f, because then we allocate
    
    1588
    +        --      its closure every time the \y is called
    
    1589
    +        -- But: let f = \ab.BIG in \y. map (f y) xs
    
    1590
    +        --      Now we do want to substitute for f, even though it's not
    
    1591
    +        --      saturated, because we're going to allocate a closure for
    
    1592
    +        --      (f y) every time round the loop anyhow.
    
    1593
    +
    
    1594
    +        -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
    
    1595
    +        -- so substituting rhs inside a lambda doesn't change the occ info.
    
    1596
    +        -- Sadly, not quite the same as exprIsHNF.
    
    1597
    +canInlineInLam (Lit _)    = True
    
    1598
    +canInlineInLam (Cast e _) = canInlineInLam e
    
    1599
    +canInlineInLam (Lam b e)  = isRuntimeVar b || canInlineInLam e
    
    1600
    +canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
    
    1601
    +canInlineInLam (Var v)    = case idOccInfo v of
    
    1602
    +                              OneOcc { occ_in_lam = IsInsideLam } -> True
    
    1603
    +                              ManyOccs {}                         -> True
    
    1604
    +                              _                                   -> False
    
    1605
    +canInlineInLam _          = False
    
    1606
    +  -- not ticks.  Counting ticks cannot be duplicated, and non-counting
    
    1607
    +  -- ticks around a Lam will disappear anyway.
    
    1608
    +
    
    1596 1609
     {-
    
    1597 1610
     ************************************************************************
    
    1598 1611
     *                                                                      *
    

  • compiler/GHC/Core/TyCo/Rep.hs
    ... ... @@ -1022,7 +1022,7 @@ instance NFData CoSel where
    1022 1022
     
    
    1023 1023
     instance Outputable MCoercion where
    
    1024 1024
       ppr MRefl    = text "MRefl"
    
    1025
    -  ppr (MCo co) = text "MCo" <+> ppr co
    
    1025
    +  ppr (MCo co) = text "MCo" <> braces (ppr co)
    
    1026 1026
     
    
    1027 1027
     {- Note [Refl invariant]
    
    1028 1028
     ~~~~~~~~~~~~~~~~~~~~~~~~