|
|
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 |