summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2016-08-06 22:17:09 +0100
committerMatthew Pickering <matthewtpickering@gmail.com>2017-01-09 16:04:12 +0000
commit54cee8fbc3d9c1b4b563965ce6d991535ca92815 (patch)
treed1c79f056deb001bbe1b6f4b1e4b844301a23017
parent6c869f906b879bc746ea1aa3e79e02f146d85093 (diff)
downloadhaskell-54cee8fbc3d9c1b4b563965ce6d991535ca92815.tar.gz
Always expose unfoldings for overloaded functions.
Summary: Users expect their overloaded functions to be specialised at call sites, however, this is only the case if they are either lucky and GHC chooses to include the unfolding or they mark their definition with an INLINABLE pragma. This leads to library authors marking all their functions with `INLINABLE` (or more accurately `INLINE`) so they ensure that downstream consumers pay no cost for their abstraction. A more sensible default is to do this job for the library author and give more predictable guarantees about specialisation. Empirically, I compiled a selection of 1150 packages with (a similar) patch applied. The total size of the interface files before the patch was 519mb and after 634mb. On modern machines, I think this increase is justified for the result. Reviewers: simonpj, austin, bgamari Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2929
-rw-r--r--compiler/main/TidyPgm.hs7
-rw-r--r--compiler/specialise/Specialise.hs5
2 files changed, 10 insertions, 2 deletions
diff --git a/compiler/main/TidyPgm.hs b/compiler/main/TidyPgm.hs
index 52137a4cd7..9b941d653c 100644
--- a/compiler/main/TidyPgm.hs
+++ b/compiler/main/TidyPgm.hs
@@ -61,6 +61,7 @@ import Outputable
import UniqDFM
import SrcLoc
import qualified ErrUtils as Err
+import TcType ( isOverloadedTy )
import Control.Monad
import Data.Function
@@ -738,6 +739,7 @@ addExternal expose_all id = (new_needed_ids, show_unfold)
never_active = isNeverActive (inlinePragmaActivation (inlinePragInfo idinfo))
loop_breaker = isStrongLoopBreaker (occInfo idinfo)
bottoming_fn = isBottomingSig (strictnessInfo idinfo)
+ is_overloaded = isOverloadedTy (idType id)
-- Stuff to do with the Id's unfolding
-- We leave the unfolding there even if there is a worker
@@ -749,11 +751,14 @@ addExternal expose_all id = (new_needed_ids, show_unfold)
|| isStableSource src -- Always expose things whose
-- source is an inline rule
-
|| not (bottoming_fn -- No need to inline bottom functions
|| never_active -- Or ones that say not to
|| loop_breaker -- Or that are loop breakers
|| neverUnfoldGuidance guidance)
+ || (if is_overloaded
+ then pprTrace "ADDITIONAL UNFOLDING:" (ppr id) True
+ else False) -- Always expose overloaded things so that
+ -- they can be specialised at call sites.
show_unfolding (DFunUnfolding {}) = True
show_unfolding _ = False
diff --git a/compiler/specialise/Specialise.hs b/compiler/specialise/Specialise.hs
index 257d076447..9158c2b0df 100644
--- a/compiler/specialise/Specialise.hs
+++ b/compiler/specialise/Specialise.hs
@@ -751,13 +751,16 @@ wantSpecImport dflags unf
BootUnfolding -> False
OtherCon {} -> False
DFunUnfolding {} -> True
- CoreUnfolding { uf_src = src, uf_guidance = _guidance }
+ CoreUnfolding { uf_src = src, uf_guidance = _guidance } -> True
+
+{-
| gopt Opt_SpecialiseAggressively dflags -> True
| isStableSource src -> True
-- Specialise even INLINE things; it hasn't inlined yet,
-- so perhaps it never will. Moreover it may have calls
-- inside it that we want to specialise
| otherwise -> False -- Stable, not INLINE, hence INLINABLE
+-}
{- Note [Warning about missed specialisations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~