[GHC] #13077: Worker/wrapper can break the let-app invariant
#13077: Worker/wrapper can break the let-app invariant -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider this {{{ {-# LANGUAGE MagicHash #-} module Bar where import GHC.Exts data X = A | B | C data T = MkT !X Int# Int# f (MkT x 0# _) = True f (MkT x n _) = let v = case x of A -> 1# B -> 2# C -> n in f (MkT x v v) }}} Compile with -O and (with GHC 8) you'll get {{{ *** Core Lint errors : in result of Simplifier *** Bar.hs:10:23: Warning: [RHS of v_s1IX :: Int#] The type of this binder is primitive: v_s1IX Binder's type: Int# *** Offending Program *** Rec { f [InlPrag=INLINE[0]] :: T -> Bool [LclIdX, Arity=1, Str=DmdType <S(SSL),1*U(U,1*U,A)>, Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False) Tmpl= \ (w_s1Jq [Occ=Once!] :: T) -> case w_s1Jq of _ [Occ=Dead] { MkT ww_s1Jt [Occ=Once] ww_s1Ju [Occ=Once] _ [Occ=Dead] -> $wf_s1Jx ww_s1Jt ww_s1Ju }}] f = \ (w_s1Jq :: T) -> case w_s1Jq of _ [Occ=Dead] { MkT ww_s1Jt ww_s1Ju ww_s1Jv -> $wf_s1Jx ww_s1Jt ww_s1Ju } $wf_s1Jx [InlPrag=[0], Occ=LoopBreaker] :: X -> Int# -> Bool [LclId, Arity=2, Str=DmdType <S,U><S,1*U>, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [40 30] 80 10}] $wf_s1Jx = \ (ww_s1Jt :: X) (ww_s1Ju :: Int#) -> case ww_s1Ju of ds_X1IO [Dmd=<L,1*U>] { __DEFAULT -> let { v_s1IX [Dmd=<S,U>] :: Int# [LclId, Str=DmdType, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] v_s1IX = case ww_s1Jt of _ [Occ=Dead, Dmd=<L,A>] { A -> 1; B -> 2; C -> ds_X1IO } } in $wf_s1Jx ww_s1Jt v_s1IX; 0 -> True } end Rec } }}} Reason: in the worker, the lambda-bound arguments don't say they are evaluated, so the previously ok-for-speculation RHS of the 'let' is no longer so. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13077> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13077: Worker/wrapper can break the let-app invariant -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Here's a related one where we need to record evaluted-ness on CPR result binders {{{ data X = A | B | C data T = MkT !X Int# Int# g :: Int -> T g 0 = MkT A 1# 2# g n = g (n-1) boo :: Int -> T boo k = case g k of MkT x n _ -> let v = case x of A -> 1# B -> 2# C -> n in MkT x v v }}} Here we get a wrapper for `g` like this {{{ g x = case $wg x of (# w1, w2 #) -> MkT w1 w2 w2 }}} It's important to record that `w1` is evaluated, as the use in `boo` makes clear. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13077#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13077: Worker/wrapper can break the let-app invariant -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: | stranal/should_compile/T13077, | T13077a Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * status: new => closed * testcase: => stranal/should_compile/T13077, T13077a * resolution: => fixed Comment: Fixed by {{{ commit 596dece7866006d699969f775fd97bd306aad85b Author: Simon Peyton Jones <simonpj@microsoft.com> Date: Fri Jan 13 08:56:53 2017 +0000 Record evaluated-ness on workers and wrappers Summary: This patch is a refinement of the original commit (which was reverted): commit 6b976eb89fe72827f226506d16d3721ba4e28bab Date: Fri Jan 13 08:56:53 2017 +0000 Record evaluated-ness on workers and wrappers In Trac #13027, comment:20, I noticed that wrappers created after demand analysis weren't recording the evaluated-ness of strict constructor arguments. In the ticket that led to a (debatable) Lint error but in general the more we know about evaluated-ness the better we can optimise. This commit adds that info * both in the worker (on args) * and in the wrapper (on CPR result patterns). See Note [Record evaluated-ness in worker/wrapper] in WwLib On the way I defined Id.setCaseBndrEvald, and used it to shorten the code in a few other places Then I added test T13077a to test the CPR aspect of this patch, but I found that Lint failed! Reason: simpleOptExpr was discarding evaluated-ness info on lambda binders because zapFragileIdInfo was discarding an Unfolding of (OtherCon _). But actually that's a robust unfolding; there is no need to discard it. To fix this: * zapFragileIdInfo only zaps fragile unfoldings * Replace isClosedUnfolding with isFragileUnfolding (the latter is just the negation of the former, but the nomenclature is more consistent). Better documentation too Note [Fragile unfoldings] * And Simplify.simplLamBndr can now look at isFragileUnfolding to decide whether to use the longer route of simplUnfolding. For some reason perf/compiler/T9233 improves in compile-time allocation by 10%. Hooray Nofib: essentially no change: -------------------------------------------------------------------------------- Program Size Allocs Runtime Elapsed TotalMem -------------------------------------------------------------------------------- cacheprof +0.0% -0.3% +0.9% +0.4% +0.0% -------------------------------------------------------------------------------- Min +0.0% -0.3% -2.4% -2.4% +0.0% Max +0.0% +0.0% +9.8% +11.4% +2.4% Geometric Mean +0.0% -0.0% +1.1% +1.0% +0.0% }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13077#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC