[commit: ghc] cardinality: Improve simple-minded boxity analysis for function bodies (be5fe43)

Simon Peyton Jones simonpj at microsoft.com
Mon Mar 25 14:03:03 CET 2013


Repository : http://darcs.haskell.org/ghc.git/

On branch  : cardinality

https://github.com/ghc/ghc/commit/be5fe43fcf80be87c17c7cc963c5c3b2274d52d8

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

commit be5fe43fcf80be87c17c7cc963c5c3b2274d52d8
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Mon Mar 25 13:00:15 2013 +0000

    Improve simple-minded boxity analysis for function bodies

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

 compiler/basicTypes/Demand.lhs | 34 +++-------------------------------
 compiler/stranal/DmdAnal.lhs   | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/compiler/basicTypes/Demand.lhs b/compiler/basicTypes/Demand.lhs
index 0462573..725c69d 100644
--- a/compiler/basicTypes/Demand.lhs
+++ b/compiler/basicTypes/Demand.lhs
@@ -630,48 +630,20 @@ peelCallDmd (CD {sd = s, ud = u})
        -- The last case includes UHead which seems a bit wrong
        -- because the body isn't used at all!
 
--- see Note [Default demands for right-hand sides]  
-vanillaCall :: Arity -> CleanDemand
-vanillaCall 0 = cleanEvalDmd
-vanillaCall n =
-  let strComp = nTimes n mkSCall       HeadStr
-      absComp = nTimes n (mkUCall One) Used
-   in mkCleanDmd strComp absComp
-
 cleanEvalDmd :: CleanDemand
 cleanEvalDmd = mkCleanDmd HeadStr Used
 
+cleanEvalProdDmd :: Arity -> CleanDemand
+cleanEvalProdDmd n = mkCleanDmd HeadStr (UProd (replicate n useTop))
+
 isSingleUsed :: JointDmd -> Bool
 isSingleUsed (JD {absd=a}) = is_used_once a
   where
     is_used_once Abs         = True
     is_used_once (Use One _) = True
     is_used_once _           = False
-
--- -- see Note [Threshold demands]  
--- mkThresholdDmd :: Arity -> JointDmd
--- mkThresholdDmd 0 = topDmd
--- mkThresholdDmd n =
---   let absComp = (iterate (mkUCall One) useTop) !! n
---    in mkJointDmd Lazy absComp
-
-
 \end{code}
 
-Note [Default demands for right-hand sides]  
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When analysis a right-hand side of a let binding, we create a
-"default" demand using `vanillaCall`. It is worth mentioning that for
-*thunks* the demand, under which a RHS is analysed is (Used One),
-whereas for lambdas it is C(C...(U)...).
-
-This phenomenon is due to the special nature of thunks: they "merge"
-multiple usage demands into one. This also explains the fact that the
-demand transformer for thunks is triggered by a less-precise, mere U
-demand (not U1). This is not true for lambda, therefore to analyze
-them we create a conservative demand C(C...(U)...), where the number
-of call layers is equal to syntactic arity of the lambda.
-
 Note [Threshold demands]
 ~~~~~~~~~~~~~~~~~~~~~~~~
 Threshold usage demand is generated to figure out if
diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs
index 14d6fce..e706bd3 100644
--- a/compiler/stranal/DmdAnal.lhs
+++ b/compiler/stranal/DmdAnal.lhs
@@ -23,9 +23,9 @@ import VarEnv
 import BasicTypes	
 import FastString
 import Data.List
-import DataCon		( dataConTyCon, dataConRepStrictness, isMarkedStrict )
+import DataCon
 import Id
-import CoreUtils	( exprIsHNF, exprIsTrivial )
+import CoreUtils	( exprIsHNF, exprType, exprIsTrivial )
 import PprCore	
 import TyCon
 import Pair
@@ -594,15 +594,21 @@ dmdAnalRhs top_lvl rec_flag env id rhs
   where
     (bndrs, body)        = collectBinders rhs
     env_body             = foldl extendSigsWithLam env bndrs
-    (body_dmd_ty, body') = dmdAnal env_body cleanEvalDmd body
+    (body_dmd_ty, body') = dmdAnal env_body body_dmd body
     (rhs_dmd_ty, bndrs') = annotateLamBndrs env body_dmd_ty bndrs
     id'		         = id `setIdStrictness` sig_ty
     sig_ty               = mkStrictSig (mkDmdType sig_fv rhs_dmds rhs_res')
 	-- See Note [NOINLINE and strictness]
 
+    -- See Note [Product demands for function body]
+    body_dmd = case deepSplitProductType_maybe (exprType body) of
+                 Nothing            -> cleanEvalDmd
+                 Just (dc, _, _, _) -> cleanEvalProdDmd (dataConRepArity dc)
+
     DmdType rhs_fv rhs_dmds rhs_res = rhs_dmd_ty
 
     -- See Note [Lazy and unleashable free variables]
+    -- See Note [Aggregated demand for cardinality]
     rhs_fv1 = case rec_flag of
                 Just bs -> useEnv (delVarEnvList rhs_fv bs)
                 Nothing -> rhs_fv
@@ -626,6 +632,30 @@ dmdAnalRhs top_lvl rec_flag env id rhs
           -- See Note [Optimistic CPR in the "virgin" case]
 \end{code}
 
+Note [Product demands for function body]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This example comes from shootout/binary_trees:
+
+    Main.check' = \ b z ds. case z of z' { I# ip ->
+        			case ds_d13s of
+        			  Main.Nil -> z'
+        			  Main.Node s14k s14l s14m ->
+        			    Main.check' (not b)
+        			      (Main.check' b
+        			         (case b {
+        			            False -> I# (-# s14h s14k);
+        			            True  -> I# (+# s14h s14k)
+        			          })
+        			         s14l)
+        			     s14m   }   }   }
+
+Here we *really* want to unbox z, even though it appears to be used boxed in
+the Nil case.  Partly the Nil case is not a hot path.  But more specifically,
+the whole function gets the CPR property if we do. 
+
+So for the demand on the body of a RHS we use a product demand if it's
+a product type.
+
 %************************************************************************
 %*									*
 \subsection{Strictness signatures and types}





More information about the ghc-commits mailing list