DmdAnal: unlifted but ok-for-spec is still used
Consider
{-# LANGUAGE MagicHash #-}
module Lib where
import GHC.Exts
f :: Int# -> Int
f x = 0
{-# OPAQUE f #-}
g1 :: Int# -> Int
g1 x = f (42# `quotInt#` x)
g2 :: Int# -> Int
g2 x = f (uncheckedIShiftL# 1# x)
f
is absent in its parameter, but the arguments at its call sites still need to be computed.
Yet today we get
Lib.f: <A>
Lib.g1: <L>
Lib.g2: <A>
g1
says it uses its argument. And good thing at that, because if we weren't, then we could replace a call site g1 1#
by g1 RUBBISH
and the latter may well lead to a division-by-zero exception, depending on what value we pick for RUBBISH
(remember that we may pick any).
But g2
says it is absent in its argument. Ergo we would rewrite a call site g2 3#
by g2 RUBBISH
, and when we pick 240598#
as the value for RUBBISH
(which we well could), then we'd trigger undefined behavior in the shift instruction. Which is not too bad either way, given that the Int#
is absent.
g1
and g2
would no longer differ if we fixed #24698, but DmdAnal sort of assumes that the transformation in #24698 happens today, in that uncheckedIShiftL# 1# x
will be replaced by a RUBBISH
lit and thus the value of x
will never be needed.
If we wanted to change the outcome, we would need to touch anticipateANF
in DmdAnal, specifically remove exprOkForSpeculation
from https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Core/Opt/DmdAnal.hs#L409 to have <L>
unconditionally.