`NOINLINE` honored up until `Prep`, then `Prep` inlines it
Given the following program:
module NoInline (quux2) where
{-# NOINLINE quux1 #-}
quux1 :: [v]
quux1 = mempty
quux2 :: [String]
quux2 = quux1
Compiling this with -fno-ignore-interface-pragmas
, I see that quux1
is not inlined into quux2
up until Tidy
:
$ ./_build/ghc-stage1 -fforce-recomp -dno-typeable-binds input/NoInline.hs -ddump-prep -ddump-simpl -dverbose-core2core -fno-ignore-interface-pragmas
...
==================== Simplifier ====================
Max iterations = 4
SimplMode {Phase = FinalPhase [final],
inline,
no rules,
eta-expand,
cast-swizzle,
case-of-case}
Result size of Simplifier
= {terms: 4, types: 6, coercions: 0, joins: 0/0}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
quux1 [InlPrag=NOINLINE] :: forall v. [v]
[LclId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=0,unsat_ok=True,boring_ok=True)}]
quux1 = GHC.Types.[]
-- RHS size: {terms: 1, types: 1, coercions: 0, joins: 0/0}
quux2 :: [String]
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=0,unsat_ok=True,boring_ok=True)}]
quux2 = quux1 @String
==================== Tidy Core ====================
Result size of Tidy Core
= {terms: 4, types: 6, coercions: 0, joins: 0/0}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
quux1_rh1 :: forall v. [v]
[GblId, Unf=OtherCon []]
quux1_rh1 = GHC.Types.[]
-- RHS size: {terms: 1, types: 1, coercions: 0, joins: 0/0}
quux2 :: [String]
[GblId, Unf=OtherCon []]
quux2 = quux1_rh1 @String
But then Prep
inlines quux1
into quux2
:
==================== CorePrep ====================
Result size of CorePrep
= {terms: 2, types: 3, coercions: 0, joins: 0/0}
-- RHS size: {terms: 1, types: 1, coercions: 0, joins: 0/0}
NoInline.quux2 :: [GHC.Base.String]
[GblId, Unf=OtherCon []]
NoInline.quux2 = GHC.Types.[] @GHC.Base.String
Note that the Tidy
output doesn't contain the NOINLINE
pragma on quux1
anymore, but also it doesn't have an unfolding...
Is this all intentional? As a library user who cares about the Prep
output and can observe the difference between inlining or not inlining quux1
, is there a way to avoid this behaviour?