Andreas Klebinger pushed to branch wip/andreask/bomb_out at Glasgow Haskell Compiler / GHC

Commits:

1 changed file:

Changes:

  • compiler/GHC/Core/Unfold.hs
    1
    +{-# OPTIONS_GHC -ddump-simpl -ddump-to-file -dumpdir dumps #-}
    
    2
    +{-# LANGUAGE DataKinds #-}
    
    3
    +
    
    1 4
     {-
    
    2 5
     (c) The University of Glasgow 2006
    
    3 6
     (c) The AQUA Project, Glasgow University, 1994-1998
    
    ... ... @@ -59,6 +62,7 @@ import GHC.Data.Bag
    59 62
     
    
    60 63
     import GHC.Utils.Misc
    
    61 64
     import GHC.Utils.Outputable
    
    65
    +import GHC.Utils.Panic.Plain (assert)
    
    62 66
     
    
    63 67
     import qualified Data.ByteString as BS
    
    64 68
     import Data.List.NonEmpty (nonEmpty)
    
    ... ... @@ -560,7 +564,7 @@ sizeExpr :: UnfoldingOpts
    560 564
              -> [Id]            -- Arguments; we're interested in which of these
    
    561 565
                                 -- get case'd
    
    562 566
              -> CoreExpr
    
    563
    -         -> ExprSize
    
    567
    +         -> ExprSize WithDiscount
    
    564 568
     
    
    565 569
     -- Note [Computing the size of an expression]
    
    566 570
     
    
    ... ... @@ -569,16 +573,18 @@ sizeExpr :: UnfoldingOpts
    569 573
     sizeExpr opts !bOMB_OUT_SIZE top_args expr
    
    570 574
       = size_up sizeZero expr
    
    571 575
       where
    
    572
    -    size_up :: ExprSize -> CoreExpr -> ExprSize
    
    576
    +    -- (size_up s e) returns `s` plus the size of `e`
    
    577
    +    size_up :: ExprSize NoDiscount -> CoreExpr -> ExprSize WithDiscount
    
    573 578
         size_up TooBig !_ = TooBig
    
    574
    -    size_up (SizeIs !s _ _) _
    
    575
    -      | s > bOMB_OUT_SIZE = TooBig
    
    579
    +    size_up (SizeIs !s _ d) _
    
    580
    +      | assert (d == 0) $ s > bOMB_OUT_SIZE
    
    581
    +      = TooBig
    
    576 582
         size_up s (Cast e _)  = size_up s e
    
    577 583
         size_up s (Tick _ e)  = size_up s e
    
    578
    -    size_up s (Type _)    = s           -- Types cost nothing
    
    579
    -    size_up s (Coercion _)  = s
    
    580
    -    size_up s (Lit lit)  = addSizeNSD (sizeN (litSize lit)) s
    
    581
    -    size_up s (Var f)    | isZeroBitId f = s
    
    584
    +    size_up s (Type _)    = withDiscount s           -- Types cost nothing
    
    585
    +    size_up s (Coercion _)  = withDiscount s
    
    586
    +    size_up s (Lit lit)  = withDiscount $ s `addSizeN` litSize lit
    
    587
    +    size_up s (Var f)    | isZeroBitId f = withDiscount s
    
    582 588
                             -- Make sure we get constructor discounts even
    
    583 589
                             -- on nullary constructors
    
    584 590
                             | otherwise       = size_up_call s f [] 0
    
    ... ... @@ -598,7 +604,7 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    598 604
     
    
    599 605
     
    
    600 606
         size_up s (Let (Rec pairs) body)
    
    601
    -      = size_up (stripDiscounts (foldr (flip size_up_let) s pairs))
    
    607
    +      = size_up ((foldr (flip (size_up_let)) s pairs))
    
    602 608
                     body
    
    603 609
     
    
    604 610
         size_up s (Case e _ _ alts) = case nonEmpty alts of
    
    ... ... @@ -635,7 +641,7 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    635 641
                     -- And it eliminates the case itself
    
    636 642
     
    
    637 643
             | otherwise -> foldr  (addAltSize . size_up_alt s)
    
    638
    -                              (stripDiscounts $ size_up (s `addSizeN` case_size) e)
    
    644
    +                              (size_up (s `addSizeN` case_size) e)
    
    639 645
                                   alts
    
    640 646
     
    
    641 647
             where
    
    ... ... @@ -681,18 +687,18 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    681 687
                   | otherwise
    
    682 688
                     = False
    
    683 689
     
    
    684
    -    size_up_let :: ExprSize -> (Id, CoreExpr) -> ExprSize
    
    690
    +    size_up_let :: ExprSize NoDiscount -> (Id, CoreExpr) -> ExprSize NoDiscount
    
    685 691
         size_up_let s (bndr, rhs)
    
    686 692
           | JoinPoint join_arity <- idJoinPointHood bndr
    
    687 693
             -- Skip arguments to join point
    
    688
    -      , (_bndrs, body) <- collectNBinders join_arity rhs
    
    689
    -      = size_up s body
    
    694
    +      , (_bndrs, join_rhs) <- collectNBinders join_arity rhs
    
    695
    +      = stripDiscounts $ size_up s join_rhs
    
    690 696
           | otherwise
    
    691
    -      = size_up (s `addSizeN` size_up_alloc bndr) rhs
    
    697
    +      = stripDiscounts $ size_up (s `addSizeN` size_up_alloc bndr) rhs
    
    692 698
     
    
    693 699
         ------------
    
    694 700
         -- size_up_app is used when there's ONE OR MORE value args
    
    695
    -    size_up_app :: ExprSize -> CoreExpr -> [CoreExpr] -> Int -> ExprSize
    
    701
    +    size_up_app :: ExprSize NoDiscount -> CoreExpr -> [CoreExpr] -> Int -> ExprSize WithDiscount
    
    696 702
         size_up_app s (App fun arg) args voids
    
    697 703
             | isTyCoArg arg                  = size_up_app s fun args voids
    
    698 704
             | isZeroBitExpr arg              = size_up_app s fun (arg:args) (voids + 1)
    
    ... ... @@ -708,14 +714,14 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    708 714
            -- size of the lhs itself.
    
    709 715
     
    
    710 716
         ------------
    
    711
    -    size_up_call :: ExprSize -> Id -> [CoreExpr] -> Int -> ExprSize
    
    717
    +    size_up_call :: ExprSize NoDiscount -> Id -> [CoreExpr] -> Int -> ExprSize WithDiscount
    
    712 718
         size_up_call !s fun val_args voids
    
    713 719
            = let !n_args = length val_args
    
    714 720
                  call_size = case idDetails fun of
    
    715
    -                            FCallId _                     -> sizeN (callSize n_args voids)
    
    721
    +                            FCallId _                     -> withDiscount $ sizeN (callSize n_args voids)
    
    716 722
                                 DataConWorkId dc              -> conSize    dc n_args
    
    717
    -                            PrimOpId op _                 -> primOpSize op n_args
    
    718
    -                            ClassOpId cls _               -> classOpSize opts cls top_args val_args
    
    723
    +                            PrimOpId op _                 -> withDiscount $ primOpSize op n_args
    
    724
    +                            ClassOpId cls _               -> withDiscount $ classOpSize opts cls top_args val_args
    
    719 725
                                 _ | fun `hasKey` buildIdKey   -> buildSize
    
    720 726
                                   | fun `hasKey` augmentIdKey -> augmentSize
    
    721 727
                                   | otherwise                 -> funSize opts top_args fun n_args voids
    
    ... ... @@ -730,7 +736,7 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    730 736
             size_up (sizeN s) rhs
    
    731 737
                     -- Why add and then subtract s?
    
    732 738
                     -- If the expression large enough this will ensure we bomb out early.
    
    733
    -                `addSizeN` (10 -s)
    
    739
    +                `addSizeND` (10 -s)
    
    734 740
     
    
    735 741
             -- Don't charge for args, so that wrappers look cheap
    
    736 742
             -- (See comments about wrappers with Case)
    
    ... ... @@ -752,23 +758,29 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    752 758
         ------------
    
    753 759
             -- These addSize things have to be here because
    
    754 760
             -- I don't want to give them bOMB_OUT_SIZE as an argument
    
    761
    +    addSizeND :: ExprSize WithDiscount -> Int -> ExprSize WithDiscount
    
    762
    +    addSizeND TooBig          _  = TooBig
    
    763
    +    addSizeND (SizeIs n xs d) m  = mkSizeDiscount bOMB_OUT_SIZE (n + m) xs d
    
    764
    +
    
    765
    +    addSizeN :: ExprSize NoDiscount -> Int -> ExprSize NoDiscount
    
    755 766
         addSizeN TooBig          _  = TooBig
    
    756
    -    addSizeN (SizeIs n xs d) m  = mkSizeIs bOMB_OUT_SIZE (n + m) xs d
    
    767
    +    addSizeN (SizeIs n xs _d) m  = mkSizeNoDiscount bOMB_OUT_SIZE (n + m) xs
    
    757 768
     
    
    758 769
             -- addAltSize is used to add the sizes of case alternatives
    
    759 770
         addAltSize TooBig            _      = TooBig
    
    760 771
         addAltSize _                 TooBig = TooBig
    
    761 772
         addAltSize (SizeIs n1 xs d1) (SizeIs n2 ys d2)
    
    762
    -        = mkSizeIs bOMB_OUT_SIZE (n1 + n2)
    
    773
    +        = mkSizeDiscount bOMB_OUT_SIZE (n1 + n2)
    
    763 774
                                      (xs `unionBags` ys)
    
    764 775
                                      (d1 + d2) -- Note [addAltSize result discounts]
    
    765 776
     
    
    766 777
             -- This variant ignores the result discount from its LEFT argument
    
    767 778
             -- It's used when the second argument isn't part of the result
    
    779
    +    addSizeNSD :: ExprSize NoDiscount -> ExprSize WithDiscount -> ExprSize WithDiscount
    
    768 780
         addSizeNSD TooBig            _      = TooBig
    
    769 781
         addSizeNSD _                 TooBig = TooBig
    
    770 782
         addSizeNSD (SizeIs n1 xs _) (SizeIs n2 ys d2)
    
    771
    -        = mkSizeIs bOMB_OUT_SIZE (n1 + n2)
    
    783
    +        = mkSizeDiscount bOMB_OUT_SIZE (n1 + n2)
    
    772 784
                                      (xs `unionBags` ys)
    
    773 785
                                      d2  -- Ignore d1
    
    774 786
     
    
    ... ... @@ -777,6 +789,7 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
    777 789
         -- this benefit for the body.
    
    778 790
         -- Why? `x` is visible to `body` either way, so it really should not
    
    779 791
         -- affect our inlining decision either way.
    
    792
    +    stripDiscounts :: ExprSize a -> ExprSize NoDiscount
    
    780 793
         stripDiscounts TooBig = TooBig
    
    781 794
         stripDiscounts (SizeIs n xs _) = (SizeIs n xs 0)
    
    782 795
     
    
    ... ... @@ -801,7 +814,7 @@ litSize _other = 0 -- Must match size of nullary constructors
    801 814
                           -- Key point: if  x |-> 4, then x must inline unconditionally
    
    802 815
                           --            (eg via case binding)
    
    803 816
     
    
    804
    -classOpSize :: UnfoldingOpts -> Class -> [Id] -> [CoreExpr] -> ExprSize
    
    817
    +classOpSize :: UnfoldingOpts -> Class -> [Id] -> [CoreExpr] -> ExprSize NoDiscount
    
    805 818
     -- See Note [Conlike is interesting]
    
    806 819
     classOpSize opts cls top_args args
    
    807 820
       | isUnaryClass cls
    
    ... ... @@ -844,7 +857,7 @@ jumpSize _n_val_args _voids = 0 -- Jumps are small, and we don't want penalise
    844 857
       -- spectral/puzzle. TODO Perhaps adjusting the default threshold would be a
    
    845 858
       -- better solution?
    
    846 859
     
    
    847
    -funSize :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize
    
    860
    +funSize :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize WithDiscount
    
    848 861
     -- Size for function calls where the function is not a constructor or primops
    
    849 862
     -- Note [Function applications]
    
    850 863
     funSize opts top_args fun n_val_args voids
    
    ... ... @@ -870,14 +883,14 @@ funSize opts top_args fun n_val_args voids
    870 883
             -- If the function is partially applied, show a result discount
    
    871 884
     -- XXX maybe behave like ConSize for eval'd variable
    
    872 885
     
    
    873
    -conSize :: DataCon -> Int -> ExprSize
    
    886
    +conSize :: DataCon -> Int -> ExprSize WithDiscount
    
    874 887
     conSize dc n_val_args
    
    875 888
       | n_val_args == 0 = SizeIs 0 emptyBag 10    -- Like variables
    
    876 889
     
    
    877 890
     -- See Note [Unboxed tuple size and result discount]
    
    878 891
       | isUnboxedTupleDataCon dc = SizeIs 0 emptyBag 10
    
    879 892
     
    
    880
    -  | isUnaryClassDataCon dc = sizeZero
    
    893
    +  | isUnaryClassDataCon dc = withDiscount sizeZero
    
    881 894
     
    
    882 895
     -- See Note [Constructor size and result discount]
    
    883 896
       | otherwise = SizeIs 10 emptyBag 10
    
    ... ... @@ -974,7 +987,7 @@ that mention a literal Integer, because the float-out pass will float
    974 987
     all those constants to top level.
    
    975 988
     -}
    
    976 989
     
    
    977
    -primOpSize :: PrimOp -> Int -> ExprSize
    
    990
    +primOpSize :: PrimOp -> Int -> ExprSize NoDiscount
    
    978 991
     primOpSize op n_val_args
    
    979 992
      = if primOpOutOfLine op
    
    980 993
           then sizeN (op_size + n_val_args)
    
    ... ... @@ -983,7 +996,7 @@ primOpSize op n_val_args
    983 996
        op_size = primOpCodeSize op
    
    984 997
     
    
    985 998
     
    
    986
    -buildSize :: ExprSize
    
    999
    +buildSize :: ExprSize WithDiscount
    
    987 1000
     buildSize = SizeIs 0 emptyBag 40
    
    988 1001
             -- We really want to inline applications of build
    
    989 1002
             -- build t (\cn -> e) should cost only the cost of e (because build will be inlined later)
    
    ... ... @@ -992,13 +1005,13 @@ buildSize = SizeIs 0 emptyBag 40
    992 1005
             -- build is saturated (it usually is).  The "-2" discounts for the \c n,
    
    993 1006
             -- The "4" is rather arbitrary.
    
    994 1007
     
    
    995
    -augmentSize :: ExprSize
    
    1008
    +augmentSize :: ExprSize WithDiscount
    
    996 1009
     augmentSize = SizeIs 0 emptyBag 40
    
    997 1010
             -- Ditto (augment t (\cn -> e) ys) should cost only the cost of
    
    998 1011
             -- e plus ys. The -2 accounts for the \cn
    
    999 1012
     
    
    1000 1013
     -- When we return a lambda, give a discount if it's used (applied)
    
    1001
    -lamScrutDiscount :: UnfoldingOpts -> ExprSize -> ExprSize
    
    1014
    +lamScrutDiscount :: UnfoldingOpts -> ExprSize a -> ExprSize WithDiscount
    
    1002 1015
     lamScrutDiscount opts (SizeIs n vs _) = SizeIs n vs (unfoldingFunAppDiscount opts)
    
    1003 1016
     lamScrutDiscount _      TooBig          = TooBig
    
    1004 1017
     
    
    ... ... @@ -1071,18 +1084,25 @@ In a function application (f a b)
    1071 1084
     Code for manipulating sizes
    
    1072 1085
     -}
    
    1073 1086
     
    
    1087
    +-- | Does an ExprSize include an evaluation Discount?
    
    1088
    +data HasDiscount = NoDiscount | WithDiscount deriving (Eq)
    
    1089
    +
    
    1074 1090
     -- | The size of a candidate expression for unfolding
    
    1075
    -data ExprSize
    
    1091
    +--
    
    1092
    +-- We don't use a separate constructor without a discount field as the
    
    1093
    +-- re-allocation here as the resulting re-allocation when converting
    
    1094
    +-- between them outweights any benefit.
    
    1095
    +data ExprSize (hasDiscount :: HasDiscount)
    
    1076 1096
         = TooBig
    
    1077 1097
         | SizeIs { _es_size_is  :: {-# UNPACK #-} !Int -- ^ Size found
    
    1078 1098
                  , _es_args     :: !(Bag (Id,Int))
    
    1079 1099
                    -- ^ Arguments cased herein, and discount for each such
    
    1080 1100
                  , _es_discount :: {-# UNPACK #-} !Int
    
    1081 1101
                    -- ^ Size to subtract if result is scrutinised by a case
    
    1082
    -               -- expression
    
    1102
    +               -- expression. Must be zero if `hasDiscount == NoDiscount`
    
    1083 1103
                  }
    
    1084 1104
     
    
    1085
    -instance Outputable ExprSize where
    
    1105
    +instance Outputable (ExprSize a) where
    
    1086 1106
       ppr TooBig         = text "TooBig"
    
    1087 1107
       ppr (SizeIs a _ c) = brackets (int a <+> int c)
    
    1088 1108
     
    
    ... ... @@ -1091,18 +1111,26 @@ instance Outputable ExprSize where
    1091 1111
     --      tup = (a_1, ..., a_99)
    
    1092 1112
     --      x = case tup of ...
    
    1093 1113
     --
    
    1094
    -mkSizeIs :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
    
    1095
    -mkSizeIs max n xs d | (n - d) > max = TooBig
    
    1096
    -                    | otherwise     = SizeIs n xs d
    
    1114
    +mkSizeDiscount :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize WithDiscount
    
    1115
    +mkSizeDiscount max n xs d | (n - d) > max = TooBig
    
    1116
    +                          | otherwise     = SizeIs n xs d
    
    1117
    +
    
    1118
    +mkSizeNoDiscount :: Int -> Int -> Bag (Id, Int) -> ExprSize NoDiscount
    
    1119
    +mkSizeNoDiscount max n xs | n > max   = TooBig
    
    1120
    +                          | otherwise = SizeIs n xs 0
    
    1097 1121
     
    
    1098
    -maxSize :: ExprSize -> ExprSize -> ExprSize
    
    1122
    +maxSize :: ExprSize a -> ExprSize a -> ExprSize a
    
    1099 1123
     maxSize TooBig         _                                  = TooBig
    
    1100 1124
     maxSize _              TooBig                             = TooBig
    
    1101 1125
     maxSize s1@(SizeIs n1 _ _) s2@(SizeIs n2 _ _) | n1 > n2   = s1
    
    1102 1126
                                                   | otherwise = s2
    
    1127
    +withDiscount :: ExprSize NoDiscount -> ExprSize WithDiscount
    
    1128
    +withDiscount s = case s of
    
    1129
    +  TooBig -> TooBig
    
    1130
    +  SizeIs x1 x2 x3 -> SizeIs x1 x2 x3
    
    1103 1131
     
    
    1104
    -sizeZero :: ExprSize
    
    1105
    -sizeN :: Int -> ExprSize
    
    1132
    +sizeZero :: ExprSize NoDiscount
    
    1133
    +sizeN :: Int -> ExprSize NoDiscount
    
    1106 1134
     
    
    1107 1135
     sizeZero = SizeIs 0 emptyBag 0
    
    1108 1136
     sizeN n  = SizeIs n emptyBag 0