diff --git a/compiler/coreSyn/CoreUtils.lhs b/compiler/coreSyn/CoreUtils.lhs index dfa568bedbe39d6741f5f815d6201b9b94536e52..01af9817a036014f8509a255eb32e87f151a7801 100644 --- a/compiler/coreSyn/CoreUtils.lhs +++ b/compiler/coreSyn/CoreUtils.lhs @@ -688,7 +688,9 @@ it's applied only to dictionaries. -- -- We can only do this if the @y + 1@ is ok for speculation: it has no -- side effects, and can't diverge or raise an exception. -exprOkForSpeculation :: CoreExpr -> Bool +exprOkForSpeculation :: Expr b -> Bool + -- Polymorphic in binder type + -- There is one call at a non-Id binder type, in SetLevels exprOkForSpeculation (Lit _) = True exprOkForSpeculation (Type _) = True exprOkForSpeculation (Coercion _) = True @@ -706,6 +708,7 @@ exprOkForSpeculation (Cast e _) = exprOkForSpeculation e exprOkForSpeculation (Case e _ _ alts) = exprOkForSpeculation e -- Note [exprOkForSpeculation: case expressions] && all (\(_,_,rhs) -> exprOkForSpeculation rhs) alts + && altsAreExhaustive alts -- Note [exprOkForSpeculation: exhaustive alts] exprOkForSpeculation other_expr = case collectArgs other_expr of @@ -740,6 +743,21 @@ exprOkForSpeculation other_expr spec_ok _ _ = False +altsAreExhaustive :: [Alt b] -> Bool +-- True <=> the case alterantives are definiely exhaustive +-- False <=> they may or may not be +altsAreExhaustive [] + = False -- Should not happen +altsAreExhaustive ((con1,_,_) : alts) + = case con1 of + DEFAULT -> True + LitAlt {} -> False + DataAlt c -> 1 + length alts == tyConFamilySize (dataConTyCon c) + -- It is possible to have an exhaustive case that does not + -- enumerate all constructors, notably in a GADT match, but + -- we behave conservatively here -- I don't think it's important + -- enough to deserve special treatment + -- | True of dyadic operators that can fail only if the second arg is zero! isDivOp :: PrimOp -> Bool -- This function probably belongs in PrimOp, or even in @@ -782,6 +800,27 @@ If exprOkForSpeculation doesn't look through case expressions, you get this: The inner case is redundant, and should be nuked. +Note [exprOkForSpeculation: exhaustive alts] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We might have something like + case x of { + A -> ... + _ -> ...(case x of { B -> ...; C -> ... })... +Here, the inner case is fine, becuase the A alternative +can't happen, but it's not ok to float the inner case outside +the outer one (even if we know x is evaluated outside), because +then it would be non-exhaustive. See Trac #5453. + +Similarly, this is a valid program (albeit a slightly dodgy one) + let v = case x of { B -> ...; C -> ... } + in case x of + A -> ... + _ -> ...v...v.... +But we don't want to speculate the v binding. + +One could try to be clever, but the easy fix is simpy to regard +a non-exhaustive case as *not* okForSpeculation. + Note [dataToTag speculation] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Is this OK? diff --git a/compiler/simplCore/FloatOut.lhs b/compiler/simplCore/FloatOut.lhs index 4f6d7b4690e8c30b966c828f52b7a887949fe5a6..bbc6c311d5bd09ab0debb202870f800052e2f6f8 100644 --- a/compiler/simplCore/FloatOut.lhs +++ b/compiler/simplCore/FloatOut.lhs @@ -440,7 +440,9 @@ partitionByMajorLevel. \begin{code} data FloatBind = FloatLet FloatLet - | FloatCase CoreExpr Id DataCon [Var] -- case e of y { C ys -> ... } + | FloatCase CoreExpr Id DataCon [Var] + -- case e of y { C ys -> ... } + -- See Note [Floating cases] in SetLevels type FloatLet = CoreBind -- INVARIANT: a FloatLet is always lifted type MajorEnv = M.IntMap MinorEnv -- Keyed by major level diff --git a/compiler/simplCore/SetLevels.lhs b/compiler/simplCore/SetLevels.lhs index 618bf35ab97b0dcf61caef0e332f1482a6a68cff..42abb8ebe55751a018151235bcc35d2436ecbe88 100644 --- a/compiler/simplCore/SetLevels.lhs +++ b/compiler/simplCore/SetLevels.lhs @@ -341,12 +341,24 @@ lvlExpr ctxt_lvl env (_, AnnLet bind body) = do return (Let bind' body') lvlExpr ctxt_lvl env (_, AnnCase scrut@(scrut_fvs,_) case_bndr ty alts) + = do { scrut' <- lvlMFE True ctxt_lvl env scrut + ; lvlCase ctxt_lvl env scrut_fvs scrut' case_bndr ty alts } + +------------------------------------------- +lvlCase :: Level -- ctxt_lvl: Level of enclosing expression + -> LevelEnv -- Level of in-scope names/tyvars + -> VarSet -- Free vars of input scrutinee + -> LevelledExpr -- Processed scrutinee + -> Id -> Type -- Case binder and result type + -> [AnnAlt Id VarSet] -- Input alternatives + -> LvlM LevelledExpr -- Result expression +lvlCase ctxt_lvl env scrut_fvs scrut' case_bndr ty alts | [(con@(DataAlt {}), bs, rhs)] <- alts - , exprOkForSpeculation (deAnnotate scrut) - , not (isTopLvl dest_lvl) -- Can't have top-level cases - = -- Float the case - do { scrut' <- lvlMFE True ctxt_lvl env scrut - ; (rhs_env, (case_bndr':bs')) <- cloneVars env (case_bndr:bs) dest_lvl + , exprOkForSpeculation scrut' -- See Note [Check the output scrutinee for okForSpec] + , not (isTopLvl dest_lvl) -- Can't have top-level cases + = -- See Note [Case floating] + -- Always float the case if possible + do { (rhs_env, (case_bndr':bs')) <- cloneVars env (case_bndr:bs) dest_lvl -- We don't need to use extendCaseBndrLvlEnv here -- because we are floating the case outwards so -- no need to do the binder-swap thing @@ -355,8 +367,7 @@ lvlExpr ctxt_lvl env (_, AnnCase scrut@(scrut_fvs,_) case_bndr ty alts) ; return (Case scrut' (TB case_bndr' (FloatMe dest_lvl)) ty [alt']) } | otherwise -- Stays put - = do { scrut' <- lvlMFE True ctxt_lvl env scrut - ; let case_bndr' = TB case_bndr bndr_spec + = do { let case_bndr' = TB case_bndr bndr_spec alts_env = extendCaseBndrLvlEnv env scrut' case_bndr' ; alts' <- mapM (lvl_alt alts_env) alts ; return (Case scrut' case_bndr' ty alts') } @@ -374,51 +385,46 @@ lvlExpr ctxt_lvl env (_, AnnCase scrut@(scrut_fvs,_) case_bndr ty alts) new_env = extendLvlEnv alts_env bs' \end{code} -@lvlMFE@ is just like @lvlExpr@, except that it might let-bind -the expression, so that it can itself be floated. - -Note [Unlifted MFEs] -~~~~~~~~~~~~~~~~~~~~ -We don't float unlifted MFEs, which potentially loses big opportunites. -For example: - \x -> f (h y) -where h :: Int -> Int# is expensive. We'd like to float the (h y) outside -the \x, but we don't because it's unboxed. Possible solution: box it. - -Note [Bottoming floats] -~~~~~~~~~~~~~~~~~~~~~~~ -If we see - f = \x. g (error "urk") -we'd like to float the call to error, to get - lvl = error "urk" - f = \x. g lvl -Furthermore, we want to float a bottoming expression even if it has free -variables: - f = \x. g (let v = h x in error ("urk" ++ v)) -Then we'd like to abstact over 'x' can float the whole arg of g: - lvl = \x. let v = h x in error ("urk" ++ v) - f = \x. g (lvl x) -See Maessen's paper 1999 "Bottom extraction: factoring error handling out -of functional programs" (unpublished I think). - -When we do this, we set the strictness and arity of the new bottoming -Id, so that it's properly exposed as such in the interface file, even if -this is all happening after strictness analysis. - -Note [Bottoming floats: eta expansion] c.f Note [Bottoming floats] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Tiresomely, though, the simplifier has an invariant that the manifest -arity of the RHS should be the same as the arity; but we can't call -etaExpand during SetLevels because it works over a decorated form of -CoreExpr. So we do the eta expansion later, in FloatOut. - -Note [Case MFEs] -~~~~~~~~~~~~~~~~ -We don't float a case expression as an MFE from a strict context. Why not? -Because in doing so we share a tiny bit of computation (the switch) but -in exchange we build a thunk, which is bad. This case reduces allocation -by 7% in spectral/puzzle (a rather strange benchmark) and 1.2% in real/fem. -Doesn't change any other allocation at all. +Note [Floating cases] +~~~~~~~~~~~~~~~~~~~~~ +Consider this: + data T a = MkT !a + f :: T Int -> blah + f x vs = case x of { MkT y -> + let f vs = ...(case y of I# w -> e)...f.. + in f vs +Here we can float the (case y ...) out , because y is sure +to be evaluated, to give + f x vs = case x of { MkT y -> + caes y of I# w -> + let f vs = ...(e)...f.. + in f vs + +That saves unboxing it every time round the loop. It's important in +some DPH stuff where we really want to avoid that repeated unboxing in +the inner loop. + +Things to note + * We can't float a case to top level + * It's worth doing this float even if we don't float + the case outside a value lambda + * We only do this with a single-alternative case + +Note [Check the output scrutinee for okForSpec] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider this: + case x of y { + A -> ....(case y of alts).... + } +Because of the binder-swap, the inner case will get substituted to +(case x of ..). So when testing whether the scrutinee is +okForSpecuation we must be careful to test the *result* scrutinee ('x' +in this case), not the *input* one 'y'. The latter *is* ok for +speculation here, but the former is not -- and ideed we can't float +the inner case out, at least not unless x is also evaluated at its +binding site. + +That's why we apply exprOkForSpeculation to scrut' and not to scrut. \begin{code} lvlMFE :: Bool -- True <=> strict context [body of case or let] @@ -426,6 +432,8 @@ lvlMFE :: Bool -- True <=> strict context [body of case or let] -> LevelEnv -- Level of in-scope names/tyvars -> CoreExprWithFVs -- input expression -> LvlM LevelledExpr -- Result expression +-- lvlMFE is just like lvlExpr, except that it might let-bind +-- the expression, so that it can itself be floated. lvlMFE _ _ _ (_, AnnType ty) = return (Type ty) @@ -491,7 +499,52 @@ lvlMFE strict_ctxt ctxt_lvl env ann_expr@(fvs, _) -- -- Also a strict contxt includes uboxed values, and they -- can't be bound at top level +\end{code} + +Note [Unlifted MFEs] +~~~~~~~~~~~~~~~~~~~~ +We don't float unlifted MFEs, which potentially loses big opportunites. +For example: + \x -> f (h y) +where h :: Int -> Int# is expensive. We'd like to float the (h y) outside +the \x, but we don't because it's unboxed. Possible solution: box it. + +Note [Bottoming floats] +~~~~~~~~~~~~~~~~~~~~~~~ +If we see + f = \x. g (error "urk") +we'd like to float the call to error, to get + lvl = error "urk" + f = \x. g lvl +Furthermore, we want to float a bottoming expression even if it has free +variables: + f = \x. g (let v = h x in error ("urk" ++ v)) +Then we'd like to abstact over 'x' can float the whole arg of g: + lvl = \x. let v = h x in error ("urk" ++ v) + f = \x. g (lvl x) +See Maessen's paper 1999 "Bottom extraction: factoring error handling out +of functional programs" (unpublished I think). + +When we do this, we set the strictness and arity of the new bottoming +Id, so that it's properly exposed as such in the interface file, even if +this is all happening after strictness analysis. + +Note [Bottoming floats: eta expansion] c.f Note [Bottoming floats] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Tiresomely, though, the simplifier has an invariant that the manifest +arity of the RHS should be the same as the arity; but we can't call +etaExpand during SetLevels because it works over a decorated form of +CoreExpr. So we do the eta expansion later, in FloatOut. +Note [Case MFEs] +~~~~~~~~~~~~~~~~ +We don't float a case expression as an MFE from a strict context. Why not? +Because in doing so we share a tiny bit of computation (the switch) but +in exchange we build a thunk, which is bad. This case reduces allocation +by 7% in spectral/puzzle (a rather strange benchmark) and 1.2% in real/fem. +Doesn't change any other allocation at all. + +\begin{code} annotateBotStr :: Id -> Maybe (Arity, StrictSig) -> Id annotateBotStr id Nothing = id annotateBotStr id (Just (arity,sig)) = id `setIdArity` arity diff --git a/docs/users_guide/7.2.2-notes.xml b/docs/users_guide/7.2.2-notes.xml index 5ccf640a62f8493a10ad15a02848777d8680ded5..b73746f1a4727a044435333f3322a33213a99dae 100644 --- a/docs/users_guide/7.2.2-notes.xml +++ b/docs/users_guide/7.2.2-notes.xml @@ -9,6 +9,14 @@ </para> <itemizedlist> + <listitem> + <para> + An optimiser bug + (<ulink url="http://hackage.haskell.org/trac/ghc/ticket/5453">#5453</ulink>) + which can cause segfaults has been fixed. + </para> + </listitem> + <listitem> <para> A native code generator bug