#10401: state hack-related regression -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Runtime Unknown/Multiple | performance bug Test Case: | Blocked By: Blocking: | Related Tickets: Differential Revisions: | -------------------------------------+------------------------------------- Consider the following program `exp.hs`: {{{ import Control.Monad import Debug.Trace expensive :: String -> String expensive x = trace "$$$" x {-# NOINLINE expensive #-} main :: IO () main = do str <- fmap expensive getLine replicateM_ 3 $ print str }}} When run as `echo hi | ./exp`, it might print either {{{ $$$ "hi" "hi" "hi" }}} or {{{ $$$ "hi" $$$ "hi" $$$ "hi" }}} depending on the compiler version and optimization settings. In 7.8.4, building with `-O2` produces the second (bad) output, while building with `-O2 -fno-state-hack` produces the first output, not surprisingly. However in 7.10.1 and in HEAD both `-O2` and `-O2 -fno-state-hack` produce the second output. It seems this difference in behavior between 7.8.4 and 7.10.1 may be due to the following difference in the unfolding for IO's fmap. In 7.8.4 {{{ ba867929df0910f70431843781ad014d $fFunctorIO2 :: (a -> b) -> GHC.Types.IO a -> GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, b #) {- Arity: 3, HasNoCafRefs, Strictness: <L,1*C1(U)><C(S),1*C1(U(U,U))><L,U>, Unfolding: (\ @ a @ b f :: a -> b x :: GHC.Types.IO a s :: GHC.Prim.State# GHC.Prim.RealWorld -> case x `cast` (GHC.Types.NTCo:IO[0] <a>_R) s of ds { (#,#) ipv ipv1 -> (# ipv, f ipv1 #) }) -} }}} while in 7.10.1 {{{ d645bee15151bb50f2bad5912d533b38 $fFunctorIO2 :: (a -> b) -> IO a -> State# RealWorld -> (# State# RealWorld, b #) {- Arity: 3, HasNoCafRefs, Strictness: <L,1*C1(U)><C(S),1*C1(U(U,U))><L,U>, Unfolding: InlineRule (3, True, False) (\ @ a @ b f :: a -> b x :: IO a s :: State# RealWorld[OneShot] -> -- ^^^^^^^ case x `cast` (NTCo:IO[0] <a>_R) s of ds { (#,#) ipv ipv1 -> (# ipv, f ipv1 #) }) -} }}} I didn't completely confirm this, though, nor determine how that difference arose in the first place (I assume the libraries were built with `-O2` for both versions?) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10401> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler