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

Commits:

6 changed files:

Changes:

  • compiler/GHC/Core/Opt/OccurAnal.hs
    ... ... @@ -28,7 +28,7 @@ core expression with (hopefully) improved usage information.
    28 28
     module GHC.Core.Opt.OccurAnal (
    
    29 29
         occurAnalysePgm,
    
    30 30
         occurAnalyseExpr,
    
    31
    -    zapLambdaBndrs, BinderSwapDecision(..), scrutOkForBinderSwap
    
    31
    +    zapLambdaBndrs
    
    32 32
       ) where
    
    33 33
     
    
    34 34
     import GHC.Prelude hiding ( head, init, last, tail )
    
    ... ... @@ -36,7 +36,7 @@ import GHC.Prelude hiding ( head, init, last, tail )
    36 36
     import GHC.Core
    
    37 37
     import GHC.Core.FVs
    
    38 38
     import GHC.Core.Utils   ( exprIsTrivial, isDefaultAlt, isExpandableApp,
    
    39
    -                          mkCastMCo, mkTicks )
    
    39
    +                          mkCastMCo, mkTicks, BinderSwapDecision(..), scrutOkForBinderSwap )
    
    40 40
     import GHC.Core.Opt.Arity   ( joinRhsArity, isOneShotBndr )
    
    41 41
     import GHC.Core.Coercion
    
    42 42
     import GHC.Core.Type
    
    ... ... @@ -3446,6 +3446,7 @@ doesn't use it. So this is only to satisfy the perhaps-over-picky Lint.
    3446 3446
     -}
    
    3447 3447
     
    
    3448 3448
     addBndrSwap :: OutExpr -> Id -> OccEnv -> OccEnv
    
    3449
    +-- See Note [Binder swap]
    
    3449 3450
     -- See Note [The binder-swap substitution]
    
    3450 3451
     addBndrSwap scrut case_bndr
    
    3451 3452
                 env@(OccEnv { occ_bs_env = swap_env, occ_bs_rng = rng_vars })
    
    ... ... @@ -3463,27 +3464,6 @@ addBndrSwap scrut case_bndr
    3463 3464
         case_bndr' = zapIdOccInfo case_bndr
    
    3464 3465
                      -- See Note [Zap case binders in proxy bindings]
    
    3465 3466
     
    
    3466
    --- | See bBinderSwaOk.
    
    3467
    -data BinderSwapDecision
    
    3468
    -  = NoBinderSwap
    
    3469
    -  | DoBinderSwap OutVar MCoercion
    
    3470
    -
    
    3471
    -scrutOkForBinderSwap :: OutExpr -> BinderSwapDecision
    
    3472
    --- If (scrutOkForBinderSwap e = DoBinderSwap v mco, then
    
    3473
    ---    v = e |> mco
    
    3474
    --- See Note [Case of cast]
    
    3475
    --- See Historical Note [Care with binder-swap on dictionaries]
    
    3476
    ---
    
    3477
    --- We use this same function in SpecConstr, and Simplify.Iteration,
    
    3478
    --- when something binder-swap-like is happening
    
    3479
    -scrutOkForBinderSwap e
    
    3480
    -  = case e of
    
    3481
    -      Tick _ e        -> scrutOkForBinderSwap e  -- Drop ticks
    
    3482
    -      Var v           -> DoBinderSwap v MRefl
    
    3483
    -      Cast (Var v) co -> DoBinderSwap v (MCo (mkSymCo co))
    
    3484
    -                         -- Cast: see Note [Case of cast]
    
    3485
    -      _               -> NoBinderSwap
    
    3486
    -
    
    3487 3467
     lookupBndrSwap :: OccEnv -> Id -> (CoreExpr, Id)
    
    3488 3468
     -- See Note [The binder-swap substitution]
    
    3489 3469
     -- Returns an expression of the same type as Id
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -22,7 +22,7 @@ import GHC.Core.TyCo.Compare( eqType )
    22 22
     import GHC.Core.Opt.Simplify.Env
    
    23 23
     import GHC.Core.Opt.Simplify.Inline
    
    24 24
     import GHC.Core.Opt.Simplify.Utils
    
    25
    -import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr, zapLambdaBndrs, scrutOkForBinderSwap, BinderSwapDecision (..) )
    
    25
    +import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr, zapLambdaBndrs )
    
    26 26
     import GHC.Core.Make       ( FloatBind, mkImpossibleExpr, castBottomExpr )
    
    27 27
     import qualified GHC.Core.Make
    
    28 28
     import GHC.Core.Coercion hiding ( substCo, substCoVar )
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -2693,7 +2693,7 @@ mkCase, mkCase1, mkCase2, mkCase3
    2693 2693
     
    
    2694 2694
     mkCase mode scrut outer_bndr alts_ty alts
    
    2695 2695
       | sm_case_merge mode
    
    2696
    -  , Just (joins, alts') <- mergeCaseAlts outer_bndr alts
    
    2696
    +  , Just (joins, alts') <- mergeCaseAlts scrut outer_bndr alts
    
    2697 2697
       = do  { tick (CaseMerge outer_bndr)
    
    2698 2698
             ; case_expr <- mkCase1 mode scrut outer_bndr alts_ty alts'
    
    2699 2699
             ; return (mkLets joins case_expr) }
    

  • compiler/GHC/Core/Opt/SpecConstr.hs
    ... ... @@ -30,7 +30,6 @@ import GHC.Core.Opt.Simplify.Inline
    30 30
     import GHC.Core.FVs     ( exprsFreeVarsList, exprFreeVars )
    
    31 31
     import GHC.Core.Opt.Monad
    
    32 32
     import GHC.Core.Opt.WorkWrap.Utils
    
    33
    -import GHC.Core.Opt.OccurAnal( BinderSwapDecision(..), scrutOkForBinderSwap )
    
    34 33
     import GHC.Core.DataCon
    
    35 34
     import GHC.Core.Class( classTyVars )
    
    36 35
     import GHC.Core.Coercion hiding( substCo )
    
    ... ... @@ -2026,9 +2025,9 @@ spec_one env fn arg_bndrs body (call_pat, rule_number)
    2026 2025
     --               , text "spec_call_args" <+> ppr spec_call_args
    
    2027 2026
     --               , text "rule_rhs" <+> ppr rule_rhs
    
    2028 2027
     --               , text "adds_void_worker_arg" <+> ppr add_void_arg
    
    2029
    -----               , text "body" <+> ppr body
    
    2030
    -----               , text "spec_rhs" <+> ppr spec_rhs
    
    2031
    -----               , text "how_bound" <+> ppr (sc_how_bound env) ]
    
    2028
    +--               , text "body" <+> ppr body
    
    2029
    +--               , text "spec_rhs" <+> ppr spec_rhs
    
    2030
    +--               , text "how_bound" <+> ppr (sc_how_bound env) ]
    
    2032 2031
     --               ]
    
    2033 2032
             ; return (spec_usg, OS { os_pat = call_pat, os_rule = rule
    
    2034 2033
                                    , os_id = spec_id
    

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -1798,8 +1798,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1798 1798
                                            , text "rule_act" <+> ppr rule_act
    
    1799 1799
                                            ]
    
    1800 1800
     
    
    1801
    -           ; pprTrace "spec_call: rule" _rule_trace_doc
    
    1802
    -             return ( spec_rule            : rules_acc
    
    1801
    +           ; return ( spec_rule            : rules_acc
    
    1803 1802
                         , (spec_fn, spec_rhs1) : pairs_acc
    
    1804 1803
                         , rhs_uds2 `thenUDs` uds_acc
    
    1805 1804
                         ) } }
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -19,6 +19,7 @@ module GHC.Core.Utils (
    19 19
             mergeAlts, mergeCaseAlts, trimConArgs,
    
    20 20
             filterAlts, combineIdenticalAlts, refineDefaultAlt,
    
    21 21
             scaleAltsBy,
    
    22
    +        BinderSwapDecision(..), scrutOkForBinderSwap,
    
    22 23
     
    
    23 24
             -- * Properties of expressions
    
    24 25
             exprType, coreAltType, coreAltsType,
    
    ... ... @@ -117,7 +118,6 @@ import Data.Function ( on )
    117 118
     import Data.List           ( sort, sortBy, partition, zipWith4, mapAccumL )
    
    118 119
     import qualified Data.List as Partial ( init, last )
    
    119 120
     import Data.Ord            ( comparing )
    
    120
    -import Control.Monad       ( guard )
    
    121 121
     import qualified Data.Set as Set
    
    122 122
     
    
    123 123
     {-
    
    ... ... @@ -591,6 +591,28 @@ The default alternative must be first, if it exists at all.
    591 591
     This makes it easy to find, though it makes matching marginally harder.
    
    592 592
     -}
    
    593 593
     
    
    594
    +data BinderSwapDecision
    
    595
    +  = NoBinderSwap
    
    596
    +  | DoBinderSwap OutVar MCoercion
    
    597
    +
    
    598
    +scrutOkForBinderSwap :: OutExpr -> BinderSwapDecision
    
    599
    +-- If (scrutOkForBinderSwap e = DoBinderSwap v mco, then
    
    600
    +--    v = e |> mco
    
    601
    +-- See Note [Case of cast]
    
    602
    +-- See Historical Note [Care with binder-swap on dictionaries]
    
    603
    +--
    
    604
    +-- We use this same function in SpecConstr, and Simplify.Iteration,
    
    605
    +-- when something binder-swap-like is happening
    
    606
    +--
    
    607
    +-- See Note [Binder swap] in GHC.Core.Opt.OccurAnal
    
    608
    +scrutOkForBinderSwap e
    
    609
    +  = case e of
    
    610
    +      Tick _ e        -> scrutOkForBinderSwap e  -- Drop ticks
    
    611
    +      Var v           -> DoBinderSwap v MRefl
    
    612
    +      Cast (Var v) co -> DoBinderSwap v (MCo (mkSymCo co))
    
    613
    +                         -- Cast: see Note [Case of cast]
    
    614
    +      _               -> NoBinderSwap
    
    615
    +
    
    594 616
     -- | Extract the default case alternative
    
    595 617
     findDefault :: [Alt b] -> ([Alt b], Maybe (Expr b))
    
    596 618
     findDefault (Alt DEFAULT args rhs : alts) = assert (null args) (alts, Just rhs)
    
    ... ... @@ -652,9 +674,9 @@ filters down the matching alternatives in GHC.Core.Opt.Simplify.rebuildCase.
    652 674
     -}
    
    653 675
     
    
    654 676
     ---------------------------------
    
    655
    -mergeCaseAlts :: Id -> [CoreAlt] -> Maybe ([CoreBind], [CoreAlt])
    
    677
    +mergeCaseAlts :: CoreExpr -> Id -> [CoreAlt] -> Maybe ([CoreBind], [CoreAlt])
    
    656 678
     -- See Note [Merge Nested Cases]
    
    657
    -mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    
    679
    +mergeCaseAlts scrut outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    
    658 680
       | Just (joins, inner_alts) <- go deflt_rhs
    
    659 681
       = Just (joins, mergeAlts outer_alts inner_alts)
    
    660 682
                     -- NB: mergeAlts gives priority to the left
    
    ... ... @@ -666,6 +688,9 @@ mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    666 688
                     -- When we merge, we must ensure that e1 takes
    
    667 689
                     -- precedence over e2 as the value for A!
    
    668 690
       where
    
    691
    +    bndr_swap :: BinderSwapDecision
    
    692
    +    bndr_swap = scrutOkForBinderSwap scrut
    
    693
    +
    
    669 694
         go :: CoreExpr -> Maybe ([CoreBind], [CoreAlt])
    
    670 695
     
    
    671 696
         -- Whizzo: we can merge!
    
    ... ... @@ -704,16 +729,9 @@ mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    704 729
     
    
    705 730
                  -- Check for capture; but only if we could otherwise do a merge
    
    706 731
                  --    (i.e. the recursive `go` succeeds)
    
    707
    -             -- "Capture" means
    
    708
    -             --    (a) case x of r { DEFAULT -> join r = ... in ...r... }
    
    709
    -             --    (b) case x of r { DEFAULT -> join j = ...r.. in ... }
    
    710
    -             -- In both cases we can't float the join point out
    
    711
    -             -- because r changes its meaning
    
    712
    -           ; let capture = outer_bndr `elem` bindersOf bind          -- (a)
    
    713
    -                        || outer_bndr `elemVarSet` bindFreeVars bind -- (b)
    
    714
    -           ; guard (not capture)
    
    715
    -
    
    716
    -           ; return (bind:joins, alts ) }
    
    732
    +           ; fix_up_binds <- okToFloatJoin bndr_swap outer_bndr bind
    
    733
    +
    
    734
    +           ; return (fix_up_binds ++ (bind : joins), alts ) }
    
    717 735
           | otherwise
    
    718 736
           = Nothing
    
    719 737
     
    
    ... ... @@ -725,7 +743,25 @@ mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    725 743
     
    
    726 744
         go _ = Nothing
    
    727 745
     
    
    728
    -mergeCaseAlts _ _ = Nothing
    
    746
    +mergeCaseAlts _ _ _ = Nothing
    
    747
    +
    
    748
    +okToFloatJoin :: BinderSwapDecision -> Id -> CoreBind -> Maybe [CoreBind]
    
    749
    +-- Check a join-point binding to see if it can be floated out of
    
    750
    +-- the DEFAULT branch of a `case`.   A Just result means "yes",
    
    751
    +-- and the [CoreBInd] are the extra fix-up bindings to add.
    
    752
    +-- See Note [Floating join points out of DEFAULT alternatives]
    
    753
    +okToFloatJoin bndr_swap outer_bndr bind
    
    754
    +  | outer_bndr `elem` bindersOf bind          -- (a)
    
    755
    +  = Nothing
    
    756
    +  | outer_bndr `elemVarSet` bindFreeVars bind -- (b)
    
    757
    +  = case bndr_swap of
    
    758
    +      DoBinderSwap scrut_var mco
    
    759
    +        | scrut_var /= outer_bndr
    
    760
    +        -> Just [ NonRec outer_bndr (mkCastMCo (Var scrut_var) mco) ]
    
    761
    +      _ -> Nothing
    
    762
    +  | otherwise
    
    763
    +  = Just []
    
    764
    +
    
    729 765
     
    
    730 766
     ---------------------------------
    
    731 767
     mergeAlts :: [Alt a] -> [Alt a] -> [Alt a]
    
    ... ... @@ -934,10 +970,43 @@ Wrinkles
    934 970
           non-join-points unless the /outer/ case has just one alternative; doing
    
    935 971
           so would risk more allocation
    
    936 972
     
    
    973
    +      Floating out join points isn't entirely straightforward.
    
    974
    +      See Note [Floating join points out of DEFAULT alternatives]
    
    975
    +
    
    937 976
     (MC5) See Note [Cascading case merge]
    
    938 977
     
    
    939 978
     See also Note [Example of case-merging and caseRules] in GHC.Core.Opt.Simplify.Utils
    
    940 979
     
    
    980
    +Note [Floating join points out of DEFAULT alternatives]
    
    981
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    982
    +Consider this, from (MC4) of Note [Merge Nested Cases]
    
    983
    +   case x of r
    
    984
    +     DEFAULT -> join j = rhs in case r of ...
    
    985
    +     alts
    
    986
    +
    
    987
    +We want to float that join point out to give this
    
    988
    +   join j = rhs
    
    989
    +   case x of r
    
    990
    +     DEFAULT -> case r of ...
    
    991
    +     alts
    
    992
    +
    
    993
    +But doing so is flat-out wrong if the scoping gets messed up:
    
    994
    +    (a) case x of r { DEFAULT -> join r = ... in ...r... }
    
    995
    +    (b) case x of r { DEFAULT -> join j = ...r.. in ... }
    
    996
    +In both cases we can't float the join point out because r changes its meaning.
    
    997
    +
    
    998
    +BUT we can fix up case (b) by adding an extra binding, like this
    
    999
    +    let r = x in
    
    1000
    +    join j = rhs[r]
    
    1001
    +    case x of r
    
    1002
    +       DEFAULT -> ...r...
    
    1003
    +       ...other alts...
    
    1004
    +
    
    1005
    +This extra binding is figured out by `okToFloatJoin`.
    
    1006
    +
    
    1007
    +Note that the cases that still don't work (e.g. (a)) will probably work fine the
    
    1008
    +next iteration of the Simplifier, because they involve shadowing, and the Simplifier
    
    1009
    +generally eliminates shadowing.
    
    941 1010
     
    
    942 1011
     Note [Cascading case merge]
    
    943 1012
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~