| ... |
... |
@@ -62,7 +62,6 @@ import GHC.Data.Bag |
|
62
|
62
|
|
|
63
|
63
|
import GHC.Utils.Misc
|
|
64
|
64
|
import GHC.Utils.Outputable
|
|
65
|
|
-import GHC.Utils.Panic.Plain (assert)
|
|
66
|
65
|
|
|
67
|
66
|
import qualified Data.ByteString as BS
|
|
68
|
67
|
import Data.List.NonEmpty (nonEmpty)
|
| ... |
... |
@@ -558,7 +557,6 @@ uncondInlineJoin bndrs body |
|
558
|
557
|
go_arg (Var f) = Just $! f `notElem` bndrs
|
|
559
|
558
|
go_arg _ = Nothing
|
|
560
|
559
|
|
|
561
|
|
-
|
|
562
|
560
|
sizeExpr :: UnfoldingOpts
|
|
563
|
561
|
-> Int -- Bomb out if it gets bigger than this
|
|
564
|
562
|
-> [Id] -- Arguments; we're interested in which of these
|
| ... |
... |
@@ -571,44 +569,51 @@ sizeExpr :: UnfoldingOpts |
|
571
|
569
|
-- Forcing bOMB_OUT_SIZE early prevents repeated
|
|
572
|
570
|
-- unboxing of the Int argument.
|
|
573
|
571
|
sizeExpr opts !bOMB_OUT_SIZE top_args expr
|
|
574
|
|
- = size_up sizeZero expr
|
|
|
572
|
+ = size_up 0 expr
|
|
575
|
573
|
where
|
|
576
|
574
|
-- (size_up s e) returns `s` plus the size of `e`
|
|
577
|
|
- size_up :: (ExprSize NoDiscount) -> CoreExpr -> ExprSize WithDiscount
|
|
578
|
|
- size_up s (Cast e _) = size_up s e
|
|
579
|
|
- size_up s (Tick _ e) = size_up s e
|
|
580
|
|
- size_up s (Type _) = withDiscount s -- Types cost nothing
|
|
581
|
|
- size_up s (Coercion _) = withDiscount s
|
|
582
|
|
- size_up s (Lit lit) = withDiscount $ s `addSizeN` litSize lit
|
|
583
|
|
- size_up s (Var f) | isZeroBitId f = withDiscount s
|
|
|
575
|
+ size_up :: Int -> CoreExpr -> ExprSize WithDiscount
|
|
|
576
|
+ size_up acc_size (Cast e _) = size_up acc_size e
|
|
|
577
|
+ size_up acc_size (Tick _ e) = size_up acc_size e
|
|
|
578
|
+ size_up acc_size (Type _) = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0 -- Types cost nothing
|
|
|
579
|
+ size_up acc_size (Coercion _) = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0
|
|
|
580
|
+ size_up acc_size (Lit lit) = (mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0) `addSizeND` litSize lit
|
|
|
581
|
+ size_up acc_size (Var f) | isZeroBitId f = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0
|
|
584
|
582
|
-- Make sure we get constructor discounts even
|
|
585
|
583
|
-- on nullary constructors
|
|
586
|
|
- | otherwise = size_up_call s f [] 0
|
|
587
|
|
-
|
|
588
|
|
- size_up s (App fun arg)
|
|
589
|
|
- | isTyCoArg arg = size_up s fun
|
|
590
|
|
- | otherwise = size_up_app (stripDiscounts $ size_up s arg)
|
|
591
|
|
- fun [arg] (if isZeroBitExpr arg then 1 else 0)
|
|
592
|
|
-
|
|
593
|
|
- size_up s (Lam b e)
|
|
594
|
|
- | isId b && not (isZeroBitId b) = lamScrutDiscount opts (size_up (addSizeN s 10) e)
|
|
595
|
|
- | otherwise = size_up s e
|
|
596
|
|
-
|
|
597
|
|
- size_up s (Let (NonRec binder rhs) body)
|
|
598
|
|
- = let rhs_s = size_up_let s (binder, rhs)
|
|
599
|
|
- in size_up (stripDiscounts $ rhs_s) body
|
|
600
|
|
-
|
|
601
|
|
-
|
|
602
|
|
- size_up s (Let (Rec pairs) body)
|
|
603
|
|
- = size_up ((foldr (flip (size_up_let)) s pairs))
|
|
604
|
|
- body
|
|
605
|
|
-
|
|
606
|
|
- size_up s (Case e _ _ alts) = case nonEmpty alts of
|
|
607
|
|
- Nothing -> size_up s e -- case e of {} never returns, so take size of scrutinee
|
|
|
584
|
+ | otherwise = size_up_call acc_size emptyBag f [] 0
|
|
|
585
|
+
|
|
|
586
|
+ size_up acc_size (App fun arg)
|
|
|
587
|
+ | isTyCoArg arg = size_up acc_size fun
|
|
|
588
|
+ | otherwise = case size_up acc_size arg of
|
|
|
589
|
+ TooBig -> TooBig
|
|
|
590
|
+ SizeIs acc_size' acc_args' _d -> size_up_app acc_size' acc_args'
|
|
|
591
|
+ fun [arg] (if isZeroBitExpr arg then 1 else 0)
|
|
|
592
|
+
|
|
|
593
|
+ size_up acc_size (Lam b e)
|
|
|
594
|
+ | isId b && not (isZeroBitId b) = lamScrutDiscount opts (size_up (acc_size+10) e)
|
|
|
595
|
+ | otherwise = size_up acc_size e
|
|
|
596
|
+
|
|
|
597
|
+ size_up acc_size (Let (NonRec binder rhs) body)
|
|
|
598
|
+ = case size_up_let acc_size emptyBag (binder, rhs) of
|
|
|
599
|
+ TooBig -> TooBig
|
|
|
600
|
+ SizeIs acc_size' acc_args' _d -> size_up acc_size' body `addSizeB` acc_args'
|
|
|
601
|
+
|
|
|
602
|
+ size_up acc_size (Let (Rec pairs) body)
|
|
|
603
|
+ = do_pairs acc_size emptyBag pairs
|
|
|
604
|
+ where
|
|
|
605
|
+ do_pairs acc_size acc_args [] = size_up acc_size body `addSizeB` acc_args
|
|
|
606
|
+ do_pairs acc_size acc_args (pair:pairs) =
|
|
|
607
|
+ case size_up_let acc_size acc_args pair of
|
|
|
608
|
+ TooBig -> TooBig
|
|
|
609
|
+ SizeIs acc_size' acc_args' _d -> do_pairs acc_size' acc_args' pairs
|
|
|
610
|
+
|
|
|
611
|
+ size_up acc_size (Case e _ _ alts) = case nonEmpty alts of
|
|
|
612
|
+ Nothing -> size_up acc_size e -- case e of {} never returns, so take size of scrutinee
|
|
608
|
613
|
Just alts
|
|
609
|
614
|
| Just v <- is_top_arg e -> -- We are scrutinising an argument variable
|
|
610
|
615
|
let
|
|
611
|
|
- alt_sizes = NE.map (size_up_alt s) alts
|
|
|
616
|
+ alt_sizes = NE.map (size_up_alt acc_size) alts
|
|
612
|
617
|
|
|
613
|
618
|
-- alts_size tries to compute a good discount for
|
|
614
|
619
|
-- the case when we are scrutinising an argument variable
|
| ... |
... |
@@ -630,14 +635,14 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr |
|
630
|
635
|
|
|
631
|
636
|
alts_size tot_size _ = tot_size
|
|
632
|
637
|
in
|
|
633
|
|
- s `addSizeNSD` alts_size (foldr1 addAltSize alt_sizes) -- alts is non-empty
|
|
|
638
|
+ mkSizeNoDiscount bOMB_OUT_SIZE acc_size emptyBag `addSizeNSD` alts_size (foldr1 addAltSize alt_sizes) -- alts is non-empty
|
|
634
|
639
|
(foldr1 maxSize alt_sizes)
|
|
635
|
640
|
-- Good to inline if an arg is scrutinised, because
|
|
636
|
641
|
-- that may eliminate allocation in the caller
|
|
637
|
642
|
-- And it eliminates the case itself
|
|
638
|
643
|
|
|
639
|
|
- | otherwise -> foldr (addAltSize . size_up_alt s)
|
|
640
|
|
- (size_up (s `addSizeN` case_size) e)
|
|
|
644
|
+ | otherwise -> foldr (addAltSize . (size_up_alt acc_size))
|
|
|
645
|
+ (size_up (acc_size + case_size) e)
|
|
641
|
646
|
alts
|
|
642
|
647
|
|
|
643
|
648
|
where
|
| ... |
... |
@@ -683,35 +688,38 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr |
|
683
|
688
|
| otherwise
|
|
684
|
689
|
= False
|
|
685
|
690
|
|
|
686
|
|
- size_up_let :: ExprSize NoDiscount -> (Id, CoreExpr) -> ExprSize NoDiscount
|
|
687
|
|
- size_up_let s (bndr, rhs)
|
|
|
691
|
+ size_up_let :: Int -> Bag (Id,Int) -> (Id, CoreExpr) -> ExprSize NoDiscount
|
|
|
692
|
+ size_up_let acc_size acc_args (bndr, rhs)
|
|
688
|
693
|
| JoinPoint join_arity <- idJoinPointHood bndr
|
|
689
|
694
|
-- Skip arguments to join point
|
|
690
|
695
|
, (_bndrs, join_rhs) <- collectNBinders join_arity rhs
|
|
691
|
|
- = stripDiscounts $ size_up s join_rhs
|
|
|
696
|
+ = (stripDiscounts $ size_up acc_size join_rhs) `addSizeB` acc_args
|
|
692
|
697
|
| otherwise
|
|
693
|
|
- = stripDiscounts $ size_up (s `addSizeN` size_up_alloc bndr) rhs
|
|
|
698
|
+ = (stripDiscounts $ size_up (acc_size + size_up_alloc bndr) rhs) `addSizeB` acc_args
|
|
694
|
699
|
|
|
695
|
700
|
------------
|
|
696
|
701
|
-- size_up_app is used when there's ONE OR MORE value args
|
|
697
|
|
- size_up_app :: ExprSize NoDiscount -> CoreExpr -> [CoreExpr] -> Int -> ExprSize WithDiscount
|
|
698
|
|
- size_up_app s (App fun arg) args voids
|
|
699
|
|
- | isTyCoArg arg = size_up_app s fun args voids
|
|
700
|
|
- | isZeroBitExpr arg = size_up_app s fun (arg:args) (voids + 1)
|
|
701
|
|
- | otherwise = let arg_size = stripDiscounts $ size_up s arg
|
|
702
|
|
- in size_up_app arg_size fun (arg:args) voids
|
|
703
|
|
- size_up_app s (Var fun) args voids = size_up_call s fun args voids
|
|
704
|
|
- size_up_app s (Tick _ expr) args voids = size_up_app s expr args voids
|
|
705
|
|
- size_up_app s (Cast expr _) args voids = size_up_app s expr args voids
|
|
706
|
|
- size_up_app s other args voids = size_up (s `addSizeN` callSize (length args) voids) other
|
|
|
702
|
+ size_up_app :: Int -> Bag (Id,Int) -> CoreExpr -> [CoreExpr] -> Int -> ExprSize WithDiscount
|
|
|
703
|
+ size_up_app acc_size acc_args (App fun arg) args voids
|
|
|
704
|
+ | isTyCoArg arg = size_up_app acc_size acc_args fun args voids
|
|
|
705
|
+ | isZeroBitExpr arg = size_up_app acc_size acc_args fun (arg:args) (voids + 1)
|
|
|
706
|
+ | otherwise = case size_up acc_size arg of
|
|
|
707
|
+ TooBig -> TooBig
|
|
|
708
|
+ SizeIs acc_size' acc_args' _ ->
|
|
|
709
|
+ size_up_app acc_size' acc_args' fun (arg:args) voids
|
|
|
710
|
+ `addSizeB` acc_args
|
|
|
711
|
+ size_up_app acc_size acc_args (Var fun) args voids = size_up_call acc_size acc_args fun args voids
|
|
|
712
|
+ size_up_app acc_size acc_args (Tick _ expr) args voids = size_up_app acc_size acc_args expr args voids
|
|
|
713
|
+ size_up_app acc_size acc_args (Cast expr _) args voids = size_up_app acc_size acc_args expr args voids
|
|
|
714
|
+ size_up_app acc_size acc_args other args voids = size_up (acc_size + callSize (length args) voids) other `addSizeB` acc_args
|
|
707
|
715
|
|
|
708
|
716
|
-- if the lhs is not an App or a Var, or an invisible thing like a
|
|
709
|
717
|
-- Tick or Cast, then we should charge for a complete call plus the
|
|
710
|
718
|
-- size of the lhs itself.
|
|
711
|
719
|
|
|
712
|
720
|
------------
|
|
713
|
|
- size_up_call :: ExprSize NoDiscount -> Id -> [CoreExpr] -> Int -> ExprSize WithDiscount
|
|
714
|
|
- size_up_call !s fun val_args voids
|
|
|
721
|
+ size_up_call :: Int -> Bag (Id,Int) -> Id -> [CoreExpr] -> Int -> ExprSize WithDiscount
|
|
|
722
|
+ size_up_call acc_size acc_args fun val_args voids
|
|
715
|
723
|
= let !n_args = length val_args
|
|
716
|
724
|
call_size = case idDetails fun of
|
|
717
|
725
|
FCallId _ -> withDiscount $ sizeN (callSize n_args voids)
|
| ... |
... |
@@ -721,18 +729,18 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr |
|
721
|
729
|
_ | fun `hasKey` buildIdKey -> buildSize
|
|
722
|
730
|
| fun `hasKey` augmentIdKey -> augmentSize
|
|
723
|
731
|
| otherwise -> funSize opts top_args fun n_args voids
|
|
724
|
|
- in s `addSizeNSD` call_size
|
|
|
732
|
+ in mkSizeNoDiscount bOMB_OUT_SIZE acc_size acc_args `addSizeNSD` call_size
|
|
725
|
733
|
|
|
726
|
734
|
------------
|
|
727
|
|
- -- size_up_alt returns on the alternatives size, not counting the accumulated
|
|
|
735
|
+ -- size_up_alt returns only the alternatives size, not counting the accumulated
|
|
728
|
736
|
-- size passed in unless we reach TooBig. This is to facility better discount
|
|
729
|
737
|
-- calculation based on the size of only the alternative.
|
|
730
|
|
- size_up_alt TooBig _ = TooBig
|
|
731
|
|
- size_up_alt (SizeIs {_es_size_is=s}) (Alt _con _bndrs rhs) =
|
|
732
|
|
- size_up (sizeN s) rhs
|
|
|
738
|
+ -- size_up_alt acc_size acc_args = TooBig
|
|
|
739
|
+ size_up_alt acc_size (Alt _con _bndrs rhs) =
|
|
|
740
|
+ size_up acc_size rhs
|
|
733
|
741
|
-- Why add and then subtract s?
|
|
734
|
742
|
-- If the expression large enough this will ensure we bomb out early.
|
|
735
|
|
- `addSizeND` (10 -s)
|
|
|
743
|
+ `addSizeND` (10 -acc_size)
|
|
736
|
744
|
|
|
737
|
745
|
-- Don't charge for args, so that wrappers look cheap
|
|
738
|
746
|
-- (See comments about wrappers with Case)
|
| ... |
... |
@@ -758,10 +766,9 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr |
|
758
|
766
|
addSizeND TooBig _ = TooBig
|
|
759
|
767
|
addSizeND (SizeIs n xs d) m = mkSizeDiscount bOMB_OUT_SIZE (n + m) xs d
|
|
760
|
768
|
|
|
761
|
|
- addSizeN :: ExprSize NoDiscount -> Int -> ExprSize NoDiscount
|
|
762
|
|
- addSizeN TooBig _ = TooBig
|
|
763
|
|
- addSizeN (SizeIs n xs _d) m = mkSizeNoDiscount bOMB_OUT_SIZE (n + m) xs
|
|
764
|
|
-
|
|
|
769
|
+ addSizeB :: ExprSize a -> Bag (Id,Int) -> ExprSize a
|
|
|
770
|
+ addSizeB TooBig _ = TooBig
|
|
|
771
|
+ addSizeB (SizeIs sz bg1 dc) bg2 = SizeIs sz (bg1 `unionBags` bg2) dc
|
|
765
|
772
|
-- addAltSize is used to add the sizes of case alternatives
|
|
766
|
773
|
addAltSize TooBig _ = TooBig
|
|
767
|
774
|
addAltSize _ TooBig = TooBig
|