Subsequent strictness defeats pseq
Summary
Today, pseq x y
expands to case x of !_ -> lazy y
. We reason that the use of lazy
will prevent us from moving the evaluation of y
before the evaluation of x
. Even if that much is true (CSE could potentially defeat it), if x
is used strictly later on we may defer the eval on x
.
Se also #22935
Steps to reproduce
compile and run with -O
{-# LANGUAGE BangPatterns #-}
module Main (main) where
import GHC.Conc
import GHC.Exts
import Debug.Trace
data StrictPair a b = SP !a !b
deriving Show
f :: a -> Int -> StrictPair a Int
{-# NOINLINE f #-}
f x y = SP x (y * y)
fun :: a -> b -> (b -> Bool) -> StrictPair a Int
fun x y g = case pseq x y of
!u -> case g u of
True -> f x 12
False -> f x 14
p :: Int
{-# NOINLINE p #-}
p = trace "eval p" 3
q :: Int
{-# NOINLINE q #-}
q = trace "eval q" 4
main :: IO ()
main = print (fun p q even)
In this program, q
should never be evaluated unless p
has already been evaluated, because it is only ever used as the second arg to pseq
. But when it is run with optimizations, q
will be evaluated first.
Environment
- GHC version used: any version 8.0-9.6.1