diff options
author | Kavon Farvardin <kavon@farvard.in> | 2018-09-23 15:29:37 -0500 |
---|---|---|
committer | Kavon Farvardin <kavon@farvard.in> | 2018-09-23 15:29:37 -0500 |
commit | 84c2ad99582391005b5e873198b15e9e9eb4f78d (patch) | |
tree | caa8c2f2ec7e97fbb4977263c6817c9af5025cf4 /compiler/iface/FlagChecker.hs | |
parent | 8ddb47cfcf5776e9a3c55fd37947c8a95e00fa12 (diff) | |
parent | e68b439fe5de61b9a2ca51af472185c62ccb8b46 (diff) | |
download | haskell-wip/T13904.tar.gz |
update to current master againwip/T13904
Diffstat (limited to 'compiler/iface/FlagChecker.hs')
-rw-r--r-- | compiler/iface/FlagChecker.hs | 107 |
1 files changed, 93 insertions, 14 deletions
diff --git a/compiler/iface/FlagChecker.hs b/compiler/iface/FlagChecker.hs index fd0459d6cc..2ef369a5e9 100644 --- a/compiler/iface/FlagChecker.hs +++ b/compiler/iface/FlagChecker.hs @@ -4,8 +4,12 @@ -- interface file as part of the recompilation checking infrastructure. module FlagChecker ( fingerprintDynFlags + , fingerprintOptFlags + , fingerprintHpcFlags ) where +import GhcPrelude + import Binary import BinIface () import DynFlags @@ -42,8 +46,11 @@ fingerprintDynFlags dflags@DynFlags{..} this_mod nameio = map fromEnum $ EnumSet.toList extensionFlags) -- -I, -D and -U flags affect CPP - cpp = (map normalise includePaths, opt_P dflags ++ picPOpts dflags) + cpp = ( map normalise $ flattenIncludes includePaths -- normalise: eliminate spurious differences due to "./foo" vs "foo" + , picPOpts dflags + , opt_P_signature dflags) + -- See Note [Repeated -optP hashing] -- Note [path flags and recompilation] paths = [ hcSuf ] @@ -51,25 +58,45 @@ fingerprintDynFlags dflags@DynFlags{..} this_mod nameio = -- -fprof-auto etc. prof = if gopt Opt_SccProfilingOn dflags then fromEnum profAuto else 0 - -- -O, see https://ghc.haskell.org/trac/ghc/ticket/10923 - opt = if hscTarget == HscInterpreted || - hscTarget == HscNothing - then 0 - else optLevel + flags = (mainis, safeHs, lang, cpp, paths, prof) + + in -- pprTrace "flags" (ppr flags) $ + computeFingerprint nameio flags +-- Fingerprint the optimisation info. We keep this separate from the rest of +-- the flags because GHCi users (especially) may wish to ignore changes in +-- optimisation level or optimisation flags so as to use as many pre-existing +-- object files as they can. +-- See Note [Ignoring some flag changes] +fingerprintOptFlags :: DynFlags + -> (BinHandle -> Name -> IO ()) + -> IO Fingerprint +fingerprintOptFlags DynFlags{..} nameio = + let + -- See https://ghc.haskell.org/trac/ghc/ticket/10923 + -- We used to fingerprint the optimisation level, but as Joachim + -- Breitner pointed out in comment 9 on that ticket, it's better + -- to ignore that and just look at the individual optimisation flags. + opt_flags = map fromEnum $ filter (`EnumSet.member` optimisationFlags) + (EnumSet.toList generalFlags) + + in computeFingerprint nameio opt_flags + +-- Fingerprint the HPC info. We keep this separate from the rest of +-- the flags because GHCi users (especially) may wish to use an object +-- file compiled for HPC when not actually using HPC. +-- See Note [Ignoring some flag changes] +fingerprintHpcFlags :: DynFlags + -> (BinHandle -> Name -> IO ()) + -> IO Fingerprint +fingerprintHpcFlags dflags@DynFlags{..} nameio = + let -- -fhpc, see https://ghc.haskell.org/trac/ghc/ticket/11798 -- hpcDir is output-only, so we should recompile if it changes hpc = if gopt Opt_Hpc dflags then Just hpcDir else Nothing - -- -fignore-asserts, which affects how `Control.Exception.assert` works - ignore_asserts = gopt Opt_IgnoreAsserts dflags + in computeFingerprint nameio hpc - -- Nesting just to avoid ever more Binary tuple instances - flags = (mainis, safeHs, lang, cpp, paths, - (prof, opt, hpc, ignore_asserts)) - - in -- pprTrace "flags" (ppr flags) $ - computeFingerprint nameio flags {- Note [path flags and recompilation] @@ -100,3 +127,55 @@ recompilation check; here we explain why. The only path-related flag left is -hcsuf. -} + +{- Note [Ignoring some flag changes] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Normally, --make tries to reuse only compilation products that are +the same as those that would have been produced compiling from +scratch. Sometimes, however, users would like to be more aggressive +about recompilation avoidance. This is particularly likely when +developing using GHCi (see #13604). Currently, we allow users to +ignore optimisation changes using -fignore-optim-changes, and to +ignore HPC option changes using -fignore-hpc-changes. If there's a +demand for it, we could also allow changes to -fprof-auto-* flags +(although we can't allow -prof flags to differ). The key thing about +these options is that we can still successfully link a library or +executable when some of its components differ in these ways. + +The way we accomplish this is to leave the optimization and HPC +options out of the flag hash, hashing them separately. +-} + +{- Note [Repeated -optP hashing] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We invoke fingerprintDynFlags for each compiled module to include +the hash of relevant DynFlags in the resulting interface file. +-optP (preprocessor) flags are part of that hash. +-optP flags can come from multiple places: + + 1. -optP flags directly passed on command line. + 2. -optP flags implied by other flags. Eg. -DPROFILING implied by -prof. + 3. -optP flags added with {-# OPTIONS -optP-D__F__ #-} in a file. + +When compiling many modules at once with many -optP command line arguments +the work of hashing -optP flags would be repeated. This can get expensive +and as noted on #14697 it can take 7% of time and 14% of allocations on +a real codebase. + +The obvious solution is to cache the hash of -optP flags per GHC invocation. +However, one has to be careful there, as the flags that were added in 3. way +have to be accounted for. + +The current strategy is as follows: + + 1. Lazily compute the hash of sOpt_p in sOpt_P_fingerprint whenever sOpt_p + is modified. This serves dual purpose. It ensures correctness for when + we add per file -optP flags and lets us save work for when we don't. + 2. When computing the fingerprint in fingerprintDynFlags use the cached + value *and* fingerprint the additional implied (see 2. above) -optP flags. + This is relatively cheap and saves the headache of fingerprinting all + the -optP flags and tracking all the places that could invalidate the + cache. +-} |