Simplfier will simplify stable unfoldings
The users guide claims that a binding with a stable unfolding (e.g. as introduced by INLINE
pragma) should remain unsimplified. My interpretation of this claim is that the unfolding is precisely the binding's Core as emitted by the desugarer (perhaps with some simplification by the simple optimiser?).
However, this doesn't appear to be entirely true. For instance, if we write:
module Test where
hi :: Int
hi = head [1,2,3]
{-# INLINE hi #-}
and compile with -O1
(using GHC 9.0.1) we see this Core from -ddump-ds
:
-- RHS size: {terms: 15, types: 8, coercions: 0, joins: 0/0}
hi [InlPrag=INLINE (sat-args=0)] :: Int
[LclIdX,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=False, ConLike=False,
WorkFree=False, Expandable=False,
Guidance=ALWAYS_IF(arity=0,unsat_ok=False,boring_ok=False)
Tmpl= head
@ Int
(GHC.Base.build
@ Int
(\ (@ a_d1eW)
(c_d1eX [OS=OneShot] :: Int -> a_d1eW -> a_d1eW)
(n_d1eY [Occ=Once, OS=OneShot] :: a_d1eW) ->
c_d1eX
(GHC.Types.I# 1#)
(c_d1eX (GHC.Types.I# 2#) (c_d1eX (GHC.Types.I# 3#) n_d1eY))))}]
hi
= head
@ Int
(GHC.Base.build
@ Int
(\ (@ a_d1eW)
(c_d1eX [OS=OneShot] :: Int -> a_d1eW -> a_d1eW)
(n_d1eY [OS=OneShot] :: a_d1eW) ->
c_d1eX
(GHC.Types.I# 1#)
(c_d1eX (GHC.Types.I# 2#) (c_d1eX (GHC.Types.I# 3#) n_d1eY))))
There's nothing surprising here.
However, if we then look at the -ddump-simpl
output we see:
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
hi [InlPrag=INLINE (sat-args=0)] :: Int
[GblId,
Caf=NoCafRefs,
Str=m,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=0,unsat_ok=False,boring_ok=False)
Tmpl= GHC.Types.I# 1#}]
hi = GHC.Types.I# 1#
The unfolding template has clearly been touched by someone.
Looking at -dverbose-core2core
, we see that the culprit is the first simplifier phase. Moreover, looking at -ddump-rule-firings
we see that the head/build
rule fired twice: presumably once in the RHS and once in the unfolding.
This is quite surprising.