Convincing GHC not to produce unfoldings during simplification

I'm currently trying to get the interface file bulk imposed by TTypeable down. The branch will currently produce two top-level bindings for each TyCon. For instance, given the type, data Proxy (a :: k) = Proxy the branch will produce (ignoring the promoted datacon for a moment), $tcProxy :: TyCon $tcProxy = GHC.Types.TyCon fpr1 fpr2 -- fingerprints $trModule (GHC.Types.TrNameS "Proxy"#) 1 krep_aebr krep_aebr :: KindRep krep_aebr [InlPrag=NOINLINE CONLIKE] = GHC.Types.KindRepFun (GHC.Types.KindRepVar 0) (GHC.Types.KindRepTYPE GHC.Types.LiftedRep) Note that the KindRep has been marked as NOINLINE; I do this intentionally as these things can grow quite large (consider, for instance, the kind of a promoted tuple constructor). This is especially true as the simplifier tends to float out the constituents of the KindRep. After the first simplifier phase we end up with, krep_sebQ :: GHC.Types.KindRep [LclId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] krep_sebQ = GHC.Types.$WKindRepVar (GHC.Types.I# 0#) krep_sebR :: GHC.Types.KindRep [LclId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] krep_sebR = GHC.Types.$WKindRepTYPE GHC.Types.LiftedRep krep_aebr [InlPrag=NOINLINE CONLIKE] :: GHC.Types.KindRep [LclId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 30}] krep_aebr = GHC.Types.KindRepFun krep_sebQ krep_sebR This means that GHC will now include each of the bindings floated out from krep_aebr in the interface file, despite the NOINLINE pragma, as they are all depended upon by the exported $tcProxy through their unfoldings. This is Quite Bad. I have observed that the floated bindings are not included in the interface file with -O0. Moreover, the core2core output clearly shows the unfoldings being added after the first simplifier phase. I haven't yet determined where in the simplifier these unfoldings are being introduced, but if anyone has ideas I'd love to hear them. Cheers, - Ben

Ben Gamari
I have observed that the floated bindings are not included in the interface file with -O0. Moreover, the core2core output clearly shows the unfoldings being added after the first simplifier phase. I haven't yet determined where in the simplifier these unfoldings are being introduced, but if anyone has ideas I'd love to hear them.
Ahhh, the inline pragma I was applying was wrong; I wanted neverInlinePragma but instead rolled my own (incorrect) version of it. It's interesting that neverInlinePragma has a NeverActive activation with EmptyInlineSpec. My intuition had lead me to an AlwaysActive activation of a NoInline InlineSpec. Cheers, - Ben

Yes, inl_act :: Activation controls what inlining takes place
inl_inline :: InlineSpec says what the user originally wrote
Perhaps I should beef up the comments.
Simon
| -----Original Message-----
| From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Ben
| Gamari
| Sent: 12 February 2017 17:48
| To: ghc-devs@haskell.org
| Subject: Re: Convincing GHC not to produce unfoldings during
| simplification
|
| Ben Gamari

Can you tell me how to repro this? I can't. I tried module Foo( foo ) where {-# NOINLINE foo #-} foo = ("fred" , True, ('c', 'e')) And just as expected, I see foo in the interface file, but none of its components. Simon | -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Ben | Gamari | Sent: 12 February 2017 17:26 | To: ghc-devs@haskell.org | Subject: Convincing GHC not to produce unfoldings during simplification | | I'm currently trying to get the interface file bulk imposed by TTypeable | down. The branch will currently produce two top-level bindings for each | TyCon. | For instance, given the type, | | data Proxy (a :: k) = Proxy | | the branch will produce (ignoring the promoted datacon for a moment), | | $tcProxy :: TyCon | $tcProxy | = GHC.Types.TyCon | fpr1 fpr2 -- fingerprints | $trModule | (GHC.Types.TrNameS "Proxy"#) | 1 | krep_aebr | | krep_aebr :: KindRep | krep_aebr [InlPrag=NOINLINE CONLIKE] | = GHC.Types.KindRepFun | (GHC.Types.KindRepVar 0) | (GHC.Types.KindRepTYPE GHC.Types.LiftedRep) | | Note that the KindRep has been marked as NOINLINE; I do this | intentionally as these things can grow quite large (consider, for | instance, the kind of a promoted tuple constructor). This is especially | true as the simplifier tends to float out the constituents of the | KindRep. After the first simplifier phase we end up with, | | | krep_sebQ :: GHC.Types.KindRep | [LclId, | Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, | WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] | krep_sebQ = GHC.Types.$WKindRepVar (GHC.Types.I# 0#) | | krep_sebR :: GHC.Types.KindRep | [LclId, | Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, | WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] | krep_sebR = GHC.Types.$WKindRepTYPE GHC.Types.LiftedRep | | krep_aebr [InlPrag=NOINLINE CONLIKE] :: GHC.Types.KindRep | [LclId, | Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, | WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 30}] | krep_aebr = GHC.Types.KindRepFun krep_sebQ krep_sebR | | This means that GHC will now include each of the bindings floated out | from krep_aebr in the interface file, despite the NOINLINE pragma, as | they are all depended upon by the exported $tcProxy through their | unfoldings. This is Quite Bad. | | I have observed that the floated bindings are not included in the | interface file with -O0. Moreover, the core2core output clearly shows the | unfoldings being added after the first simplifier phase. I haven't yet | determined where in the simplifier these unfoldings are being introduced, | but if anyone has ideas I'd love to hear them. | | Cheers, | | - Ben
participants (2)
-
Ben Gamari
-
Simon Peyton Jones