Unexpected failure to inline, even with pragma

Dear GHC-ers, It seems I do not quite understand the behaviour of the inliner. Consider these two modules: module Foo.Bar where foo :: Char -> IO () foo = putChar {-# INLINE bar #-} bar :: String -> IO () bar = mapM_ foo module Main where import Foo.Bar main = bar "done" I would expect the inliner to produce at least (considering the pragma) main = mapM_ foo "done" or maybe even main=mapM_ putChar "done" However, when I compile this code, that inlining does not seem to happen: $ ghc -ddump-inlinings -fforce-recomp Main.hs [1 of 2] Compiling Foo.Bar ( Foo/Bar.hs, Foo/Bar.o ) Inlining done: Foo.Bar.foo [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main ... Indeed, when I use -ddump-simpl, ghc reports: ==================== Tidy Core ==================== Result size of Tidy Core = {terms: 7, types: 5, coercions: 0} Main.main :: GHC.Types.IO () [GblId, Str=DmdType] Main.main = Foo.Bar.bar (GHC.CString.unpackCString# "done"#) :Main.main :: GHC.Types.IO () [GblId, Str=DmdType] :Main.main = GHC.TopHandler.runMainIO @ () Main.main Can anyone explain why Foo.Bar.bar isn't inlined in Main.main? Regards, Philip

Hi, Am Donnerstag, den 01.05.2014, 12:59 +0000 schrieb p.k.f.holzenspies@utwente.nl:
$ ghc -ddump-inlinings -fforce-recomp Main.hs
You need to pass "-O" to ghc. (I didn’t check if that fixes it, but without it the optimizer does very very little.) Greetings, Joachim -- Joachim “nomeata” Breitner mail@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nomeata@debian.org

Dear Joachim, et al., Yes, you were right, this does fix it. This confuses me even more as to why it *did* inline Foo.Bar.foo in Foo.Bar.bar without -O, though. Is -O required for optimization across module bounds? Also, since I really want a certain level of inlining for a plugin I'm working on; is there a way to force (from the plugin, i.e. using the API) to force inlining of a term at its call-site? Alternatively (weaker), can I force - from a compiler plugin - the inliner to behave as if -O was set even if it wasn't? I may be doing things in a roundabout way, but here's my thinking: I want to write a combinatory-library with a plugin that optimizes uses of this library using non-trivial domain knowledge. However, the primitive combinators for which my plugin is defined are hard to use. I want to offer users higher-level combinators that are expressed in terms of those primitive ones, but I don't want to complicate my plugin too much. If, somehow, I could make absolutely sure all the non-primitive combinators were inlined (again, this may be done using API-calls rather than pragma's), I could define my plugin-logic only in terms of the primitive ones... this would be bliss :D Regards, Philip
-----Original Message----- From: Joachim Breitner [mailto:mail@joachim-breitner.de] Sent: donderdag 1 mei 2014 16:14 To: ghc-devs@haskell.org Subject: Re: Unexpected failure to inline, even with pragma
Hi,
Am Donnerstag, den 01.05.2014, 12:59 +0000 schrieb p.k.f.holzenspies@utwente.nl:
$ ghc -ddump-inlinings -fforce-recomp Main.hs
You need to pass "-O" to ghc.
(I didn’t check if that fixes it, but without it the optimizer does very very little.)
Greetings, Joachim
-- Joachim “nomeata” Breitner mail@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nomeata@debian.org

| Is -O required for optimization across module bounds? Yes, without -O GHC doesn’t put inlinings into interface files, so an importing module can't see them. Use -fno-omit-interface-pragmas to tell GHC to put the stuff in the interface file regardless. | Also, since I really want a certain level of inlining for a plugin I'm | working on; is there a way to force (from the plugin, i.e. using the | API) to force inlining of a term at its call-site? Yes, use the magic function 'inline'. http://www.haskell.org/ghc/docs/7.8.2/html/libraries/base-4.7.0.0/GHC-Exts.h... (But I don’t know how much people have exercised this recently, and I think it's a bit fragile because it vanishes after a single inlining.) | Alternatively | (weaker), can I force - from a compiler plugin - the inliner to behave | as if -O was set even if it wasn't? Well, you could invoke the simplifier from the plugin, setting the DynFlags to -O first. But I don’t think the plugin can side-effect the DynFlags for downstream passes. Simon
participants (3)
-
Joachim Breitner
-
p.k.f.holzenspies@utwente.nl
-
Simon Peyton Jones