X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fstranal%2FDmdAnal.lhs;h=3fc84773af953823e92b89a5eeaf125dd1612aac;hb=2f6ad11fa0c2995d950c91fd4301f23aceeb443b;hp=c5cfb7b4bdedde682e5b88669b8305dfef7c07ab;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/compiler/stranal/DmdAnal.lhs b/compiler/stranal/DmdAnal.lhs index c5cfb7b..3fc8477 100644 --- a/compiler/stranal/DmdAnal.lhs +++ b/compiler/stranal/DmdAnal.lhs @@ -40,7 +40,8 @@ import TysWiredIn ( unboxedPairDataCon ) import TysPrim ( realWorldStatePrimTy ) import UniqFM ( plusUFM_C, addToUFM_Directly, lookupUFM_Directly, keysUFM, minusUFM, ufmToList, filterUFM ) -import Type ( isUnLiftedType, coreEqType ) +import Type ( isUnLiftedType, coreEqType, splitTyConApp_maybe ) +import Coercion ( coercionKind ) import CoreLint ( showPass, endPass ) import Util ( mapAndUnzip, mapAccumL, mapAccumR, lengthIs ) import BasicTypes ( Arity, TopLevelFlag(..), isTopLevel, isNeverActive, @@ -164,16 +165,25 @@ dmdAnal sigs dmd (Lit lit) dmdAnal sigs dmd (Var var) = (dmdTransform sigs var dmd, Var var) +dmdAnal sigs dmd (Cast e co) + = (dmd_ty, Cast e' co) + where + (dmd_ty, e') = dmdAnal sigs dmd' e + to_co = snd (coercionKind co) + dmd' + | Just (tc, args) <- splitTyConApp_maybe to_co + , isRecursiveTyCon tc = evalDmd + | otherwise = dmd + -- This coerce usually arises from a recursive + -- newtype, and we don't want to look inside them + -- for exactly the same reason that we don't look + -- inside recursive products -- we might not reach + -- a fixpoint. So revert to a vanilla Eval demand + dmdAnal sigs dmd (Note n e) = (dmd_ty, Note n e') where - (dmd_ty, e') = dmdAnal sigs dmd' e - dmd' = case n of - Coerce _ _ -> evalDmd -- This coerce usually arises from a recursive - other -> dmd -- newtype, and we don't want to look inside them - -- for exactly the same reason that we don't look - -- inside recursive products -- we might not reach - -- a fixpoint. So revert to a vanilla Eval demand + (dmd_ty, e') = dmdAnal sigs dmd e dmdAnal sigs dmd (App fun (Type ty)) = (fun_ty, App fun' (Type ty)) @@ -530,34 +540,6 @@ by dmdAnalTopBind. \begin{code} mk_sig_ty never_inline thunk_cpr_ok rhs (DmdType fv dmds res) - | never_inline && not (isBotRes res) - -- HACK ALERT - -- Don't strictness-analyse NOINLINE things. Why not? Because - -- the NOINLINE says "don't expose any of the inner workings at the call - -- site" and the strictness is certainly an inner working. - -- - -- More concretely, the demand analyser discovers the following strictness - -- for unsafePerformIO: C(U(AV)) - -- But then consider - -- unsafePerformIO (\s -> let r = f x in - -- case writeIORef v r s of (# s1, _ #) -> - -- (# s1, r #) - -- The strictness analyser will find that the binding for r is strict, - -- (becuase of uPIO's strictness sig), and so it'll evaluate it before - -- doing the writeIORef. This actually makes tests/lib/should_run/memo002 - -- get a deadlock! - -- - -- Solution: don't expose the strictness of unsafePerformIO. - -- - -- But we do want to expose the strictness of error functions, - -- which are also often marked NOINLINE - -- {-# NOINLINE foo #-} - -- foo x = error ("wubble buggle" ++ x) - -- So (hack, hack) we only drop the strictness for non-bottom things - -- This is all very unsatisfactory. - = (deferEnv fv, topSig) - - | otherwise = (lazy_fv, mkStrictSig dmd_ty) where dmd_ty = DmdType strict_fv final_dmds res'