[commit: ghc] wip/nested-cpr: Limit the depth of the CPR information (9efa6f3)

git at git.haskell.org git at git.haskell.org
Fri Jan 17 23:50:05 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/nested-cpr
Link       : http://ghc.haskell.org/trac/ghc/changeset/9efa6f3cc24257779b51ba1fba95b0c459436e6d/ghc

>---------------------------------------------------------------

commit 9efa6f3cc24257779b51ba1fba95b0c459436e6d
Author: Joachim Breitner <mail at joachim-breitner.de>
Date:   Thu Dec 5 16:13:41 2013 +0000

    Limit the depth of the CPR information
    
    as otherwise, it could become infinite.


>---------------------------------------------------------------

9efa6f3cc24257779b51ba1fba95b0c459436e6d
 compiler/basicTypes/Demand.lhs |   34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/compiler/basicTypes/Demand.lhs b/compiler/basicTypes/Demand.lhs
index c0a63fe..2ef2a6d 100644
--- a/compiler/basicTypes/Demand.lhs
+++ b/compiler/basicTypes/Demand.lhs
@@ -813,8 +813,8 @@ cprSumRes tag | opt_CprOff = topRes
 
 cprProdRes :: [DmdResult] -> DmdResult
 cprProdRes arg_ress
-  | opt_CprOff = topRes
-  | otherwise  = Converges $ RetProd arg_ress
+  | opt_CprOff        = topRes
+  | otherwise         = Converges $ cutCPRResult maxCPRDepth  $ RetProd arg_ress
 
 getDmdResult :: DmdType -> DmdResult
 getDmdResult (DmdType _ [] r) = r       -- Only for data-typed arguments!
@@ -824,10 +824,31 @@ getDmdResult _                = topRes
 divergeDmdResult :: DmdResult -> DmdResult
 divergeDmdResult r = r `lubDmdResult` botRes
 
+maxCPRDepth :: Int
+maxCPRDepth = 3
+
+-- With nested CPR, DmdResult can be arbitrarily deep; consider
+-- data Rec1 = Foo Rec2 Rec2
+-- data Rec2 = Bar Rec1 Rec1
+--
+-- x = Foo y y
+-- y = Bar x x
+--
+-- So we need to forget information at a certain depth. We do that at all points
+-- where we are constructing new RetProd constructors.
+cutDmdResult :: Int -> DmdResult -> DmdResult
+cutDmdResult 0 _ = topRes
+cutDmdResult _ Diverges = Diverges
+cutDmdResult n (Converges c) = Converges (cutCPRResult n c)
+cutDmdResult n (Dunno c) = Dunno (cutCPRResult n c)
+
+cutCPRResult :: Int -> CPRResult -> CPRResult
+cutCPRResult _ NoCPR = NoCPR
+cutCPRResult n (RetProd rs) = RetProd (map (cutDmdResult (n-1)) rs)
+cutCPRResult _ (RetSum tag) = RetSum tag
+
 vanillaCprProdRes :: Arity -> DmdResult
-vanillaCprProdRes arity
-  | opt_CprOff = topRes
-  | otherwise  = Converges $ RetProd (replicate arity topRes)
+vanillaCprProdRes arity = cprProdRes (replicate arity topRes)
 
 isTopRes :: DmdResult -> Bool
 isTopRes (Dunno NoCPR) = True
@@ -1073,10 +1094,11 @@ bothDmdType (DmdType fv1 ds1 r1) (fv2, t2)
 instance Outputable DmdType where
   ppr (DmdType fv ds res) 
     = hsep [text "DmdType",
-            hcat (map ppr ds) <> ppr res,
+            hcat (map ppr ds) <> ppr_res,
             if null fv_elts then empty
             else braces (fsep (map pp_elt fv_elts))]
     where
+      ppr_res = if isTopRes res then empty else ppr res
       pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
       fv_elts = ufmToList fv
 



More information about the ghc-commits mailing list