#16197: Strictness is not preserved under -O1 -------------------------------------+------------------------------------- Reporter: alang9 | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.4.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): I can reproduce this with 8.6, but not with HEAD, so I think perhaps it is fixed. Hooray. Indeed we have made some recent changes to the handling of strictness on data constructors: {{{ commit d77501cd5b9060e38acd50e11e0c5aae89d75b65 Author: Simon Peyton Jones <simonpj@microsoft.com> Date: Wed Dec 12 17:22:07 2018 +0000 Improvements to demand analysis This patch collects a few improvements triggered by Trac #15696, and fixing Trac #16029 * Stop making toCleanDmd behave specially for unlifted types. This special case was the cause of stupid behaviour in Trac #16029. And to my joy I discovered the let/app invariant rendered it unnecessary. (Maybe the special case pre-dated the let/app invariant.) Result: less special-case handling in the compiler, and better perf for the compiled code. * In WwLib.mkWWstr_one, treat seqDmd like U(AAA). It was not being so treated before, which again led to stupid code. * Update and improve Notes There are .stderr test wibbles because we get slightly different strictness signatures for an argumment of unlifted type: <L,U> rather than <S,U> for Int# <S,U> rather than <S(S),U(U)> for Int commit d549c081f19925dd0e4c70d45bded0497c649d49 Author: Ben Gamari <bgamari.foss@gmail.com> Date: Tue Dec 11 13:34:47 2018 -0500 dmdAnal: Move handling of datacon strictness to mkWWstr_one Previously datacon strictness was accounted for when we demand analysed a case analysis. However, this results in pessimistic demands in some cases. For instance, consider the program (from T10482) data family Bar a data instance Bar (a, b) = BarPair !(Bar a) !(Bar b) newtype instance Bar Int = Bar Int foo :: Bar ((Int, Int), Int) -> Int -> Int foo f k = case f of BarPair x y -> case burble of True -> case x of BarPair p q -> ... False -> ... We really should be able to assume that `p` is already evaluated since it came from a strict field of BarPair. However, as written the demand analyser can not conclude this since we may end up in the False branch of the case on `burble` (which places no demand on `x`). By accounting for the data con strictness later, applied to the demand of the RHS, we get the strict demand signature we want. See Note [Add demands for strict constructors] for a more comprehensive discussion. commit c5b477c29127d8375b3f23d37f877278b52547f6 Author: Ömer Sinan Ağacan <omeragacan@gmail.com> Date: Mon Oct 15 13:48:53 2018 -0400 Fix cardinality change of fields in addDataConStrictness }}} And indeed the strictness of `f` is now {{{ Str=<S,1*U(U)><S,1*U(U)>m, }}} I had previously regarded these patches as clean-ups, improving the generated code, rather than actual bug fixes. So your example is very interesting: it shows that the "clean-up" actually fixed a bug. Ben/Omer: could you add comment:4 as a regression test? -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16197#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler