Cast worker/wrapper does not respect -fno-worker-wrapper
Summary
The cast worker/wrapper transformation does not respect the -fno-worker-wrapper
flag.
I discovered this when 6d49d5be started replacing the NOINLINE
annotation on the wrapper with NOUSERINLINE
.
This is a problem for the Clash Haskell-to-Hardware compiler because we mark/it recognizes certain functions as "primitives", and those functions should not be inlined by GHC.
Steps to reproduce
Compiling the following with ghc -O0 -fno-worker-wrapper Test9.hs
{-# LANGUAGE TypeOperators, DataKinds, KindSignatures #-}
{-# OPTIONS_GHC -O0 -fforce-recomp -fno-worker-wrapper -dverbose-core2core -ddump-ds -ddump-simpl -ddump-to-file #-}
module Test9 where
import GHC.TypeLits
newtype Signed (n :: Nat) = S Integer
{-# NOINLINE times #-}
times :: Signed m -> Signed n -> Signed (m + n)
times (S a) (S b) = S (a * b)
shows this desugar output:
-- RHS size: {terms: 8, types: 7, coercions: 9, joins: 0/0}
times [InlPrag=NOINLINE]
:: forall (m :: Nat) (n :: Nat).
Signed m -> Signed n -> Signed (m + n)
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [0 0] 40 0}]
times
= \ (@(m_aBd :: Nat))
(@(n_aBe :: Nat))
(ds_dBO :: Signed m_aBd)
(ds_dBP :: Signed n_aBe) ->
(* @Integer
GHC.Num.$fNumInteger
(ds_dBO
`cast` (Test9.N:Signed[0] <m_aBd>_P :: Signed m_aBd ~R# Integer))
(ds_dBP
`cast` (Test9.N:Signed[0] <n_aBe>_P :: Signed n_aBe ~R# Integer)))
`cast` (Sym (Test9.N:Signed[0] <m_aBd + n_aBe>_P)
:: Integer ~R# Signed (m_aBd + n_aBe))
but shows this for the simplifier output:
-- RHS size: {terms: 8, types: 7, coercions: 4, joins: 0/0}
times1_rBI
:: forall {m :: Nat} {n :: Nat}. Signed m -> Signed n -> Integer
[GblId, Arity=2, Unf=OtherCon []]
times1_rBI
= \ (@(m_aBe :: Nat))
(@(n_aBf :: Nat))
(ds_dBP :: Signed m_aBe)
(ds1_dBQ :: Signed n_aBf) ->
* @Integer
GHC.Num.$fNumInteger
(ds_dBP
`cast` (Test9.N:Signed[0] <m_aBe>_P :: Signed m_aBe ~R# Integer))
(ds1_dBQ
`cast` (Test9.N:Signed[0] <n_aBf>_P :: Signed n_aBf ~R# Integer))
-- RHS size: {terms: 1, types: 0, coercions: 17, joins: 0/0}
times [InlPrag=NOUSERINLINE[final]]
:: forall (m :: Nat) (n :: Nat).
Signed m -> Signed n -> Signed (m + n)
[GblId, Arity=2, Unf=OtherCon []]
times
= times1_rBI
`cast` (forall (m :: <Nat>_N) (n :: <Nat>_N).
<Signed m>_R
%<'Many>_N ->_R <Signed n>_R
%<'Many>_N ->_R Sym (Test9.N:Signed[0] <m + n>_P)
:: (forall {m :: Nat} {n :: Nat}. Signed m -> Signed n -> Integer)
~R# (forall {m :: Nat} {n :: Nat}.
Signed m -> Signed n -> Signed (m + n)))
Expected behavior
I am expecting the cast W/W transformation not to occur and keep a single binding called times
having a NOINLINE
pragma.
Basically, I expected an additional condition in https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Core/Opt/Simplify.hs#L525-534 that checks whether W/W is disabled through -fno-worker-wrapper
.
Environment
- GHC version used: 9.0.1
Optional:
- Operating System:
Linux 4.19.84-microsoft-standard #1 SMP Wed Nov 13 11:44:37 UTC 2019 x86_64 GNU/Linux
- System Architecture:
x86_64