diff options
-rw-r--r-- | compiler/main/DynFlags.hs | 6 | ||||
-rw-r--r-- | compiler/typecheck/TcErrors.lhs | 77 | ||||
-rw-r--r-- | docs/users_guide/flags.xml | 31 | ||||
-rw-r--r-- | docs/users_guide/using.xml | 564 |
4 files changed, 376 insertions, 302 deletions
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs index 4d19519845..4175dc9afb 100644 --- a/compiler/main/DynFlags.hs +++ b/compiler/main/DynFlags.hs @@ -580,6 +580,8 @@ data DynFlags = DynFlags { ruleCheck :: Maybe String, strictnessBefore :: [Int], -- ^ Additional demand analysis + maxRelevantBinds :: Maybe Int, -- ^ Maximum number of bindings from the type envt + -- to show in type error messages simplTickFactor :: Int, -- ^ Multiplier for simplifier ticks specConstrThreshold :: Maybe Int, -- ^ Threshold for SpecConstr specConstrCount :: Maybe Int, -- ^ Max number of specialisations for any one function @@ -1247,6 +1249,7 @@ defaultDynFlags mySettings = maxSimplIterations = 4, shouldDumpSimplPhase = Nothing, ruleCheck = Nothing, + maxRelevantBinds = Just 6, simplTickFactor = 100, specConstrThreshold = Just 2000, specConstrCount = Just 3, @@ -2288,6 +2291,9 @@ dynamic_flags = [ , Flag "O" (optIntSuffixM (\mb_n -> setOptLevel (mb_n `orElse` 1))) -- If the number is missing, use 1 + + , Flag "fmax-relevant-binds" (intSuffix (\n d -> d{ maxRelevantBinds = Just n })) + , Flag "fno-max-relevant-binds" (noArg (\d -> d{ maxRelevantBinds = Nothing })) , Flag "fsimplifier-phases" (intSuffix (\n d -> d{ simplPhases = n })) , Flag "fmax-simplifier-iterations" (intSuffix (\n d -> d{ maxSimplIterations = n })) , Flag "fsimpl-tick-factor" (intSuffix (\n d -> d{ simplTickFactor = n })) diff --git a/compiler/typecheck/TcErrors.lhs b/compiler/typecheck/TcErrors.lhs index 4023311d3a..307e922633 100644 --- a/compiler/typecheck/TcErrors.lhs +++ b/compiler/typecheck/TcErrors.lhs @@ -500,7 +500,7 @@ solve it. \begin{code} mkIrredErr :: ReportErrCtxt -> [Ct] -> TcM ErrMsg mkIrredErr ctxt cts - = do { (ctxt, binds_msg) <- relevantBindings ctxt ct1 + = do { (ctxt, binds_msg) <- relevantBindings True ctxt ct1 ; mkErrorMsg ctxt ct1 (msg $$ binds_msg) } where (ct1:_) = cts @@ -516,7 +516,8 @@ mkHoleError ctxt ct@(CHoleCan { cc_occ = occ }) msg = vcat [ hang (ptext (sLit "Found hole") <+> quotes (ppr occ)) 2 (ptext (sLit "with type:") <+> pprType (ctEvPred (cc_ev ct))) , ppUnless (null tyvars_msg) (ptext (sLit "Where:") <+> vcat tyvars_msg) ] - ; (ctxt, binds_doc) <- relevantBindings ctxt ct + ; (ctxt, binds_doc) <- relevantBindings False ctxt ct + -- The 'False' means "don't filter the bindings; see Trac #8191 ; mkErrorMsg ctxt ct (msg $$ binds_doc) } where loc_msg tv @@ -532,7 +533,7 @@ mkHoleError _ ct = pprPanic "mkHoleError" (ppr ct) ---------------- mkIPErr :: ReportErrCtxt -> [Ct] -> TcM ErrMsg mkIPErr ctxt cts - = do { (ctxt, bind_msg) <- relevantBindings ctxt ct1 + = do { (ctxt, bind_msg) <- relevantBindings True ctxt ct1 ; mkErrorMsg ctxt ct1 (msg $$ bind_msg) } where (ct1:_) = cts @@ -583,7 +584,7 @@ mkEqErr1 :: ReportErrCtxt -> Ct -> TcM ErrMsg -- Wanted constraints only! mkEqErr1 ctxt ct | isGiven ev - = do { (ctxt, binds_msg) <- relevantBindings ctxt ct + = do { (ctxt, binds_msg) <- relevantBindings True ctxt ct ; let (given_loc, given_msg) = mk_given (cec_encl ctxt) ; dflags <- getDynFlags ; mkEqErr_help dflags ctxt (given_msg $$ binds_msg) @@ -591,7 +592,7 @@ mkEqErr1 ctxt ct Nothing ty1 ty2 } | otherwise -- Wanted or derived - = do { (ctxt, binds_msg) <- relevantBindings ctxt ct + = do { (ctxt, binds_msg) <- relevantBindings True ctxt ct ; (ctxt, tidy_orig) <- zonkTidyOrigin ctxt (ctLocOrigin (cc_loc ct)) ; let (is_oriented, wanted_msg) = mk_wanted_extra tidy_orig ; dflags <- getDynFlags @@ -931,7 +932,7 @@ mk_dict_err :: ReportErrCtxt -> (Ct, ClsInstLookupResult) mk_dict_err ctxt (ct, (matches, unifiers, safe_haskell)) | null matches -- No matches but perhaps several unifiers = do { let (is_ambig, ambig_msg) = mkAmbigMsg ct - ; (ctxt, binds_msg) <- relevantBindings ctxt ct + ; (ctxt, binds_msg) <- relevantBindings True ctxt ct ; traceTc "mk_dict_err" (ppr ct $$ ppr is_ambig $$ ambig_msg) ; return (ctxt, cannot_resolve_msg is_ambig binds_msg ambig_msg) } @@ -1171,17 +1172,25 @@ getSkolemInfo (implic:implics) tv -- careful to zonk the Id's type first, so it has to be in the monad. -- We must be careful to pass it a zonked type variable, too. -relevantBindings :: ReportErrCtxt -> Ct +relevantBindings :: Bool -- True <=> filter by tyvar; False <=> no filtering + -- See Trac #8191 + -> ReportErrCtxt -> Ct -> TcM (ReportErrCtxt, SDoc) -relevantBindings ctxt ct - = do { (tidy_env', docs) <- go (cec_tidy ctxt) (6, emptyVarSet) - (reverse (tcl_bndrs lcl_env)) +relevantBindings want_filtering ctxt ct + = do { dflags <- getDynFlags + ; (tidy_env', docs, discards) + <- go (cec_tidy ctxt) (maxRelevantBinds dflags) + emptyVarSet [] False + (reverse (tcl_bndrs lcl_env)) -- The 'reverse' makes us work from outside in - -- Blargh; maybe have a flag for this "6" ; traceTc "relevantBindings" (ppr [id | TcIdBndr id _ <- tcl_bndrs lcl_env]) ; let doc = hang (ptext (sLit "Relevant bindings include")) - 2 (vcat docs) + 2 (vcat docs $$ max_msg) + max_msg | discards + = ptext (sLit "(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)") + | otherwise = empty + ; if null docs then return (ctxt, empty) else do { traceTc "rb" doc @@ -1190,28 +1199,38 @@ relevantBindings ctxt ct lcl_env = ctLocEnv (cc_loc ct) ct_tvs = tyVarsOfCt ct - go :: TidyEnv -> (Int, TcTyVarSet) - -> [TcIdBinder] -> TcM (TidyEnv, [SDoc]) - go tidy_env (_,_) [] - = return (tidy_env, []) - go tidy_env (n_left,tvs_seen) (TcIdBndr id _ : tc_bndrs) - | n_left <= 0, ct_tvs `subVarSet` tvs_seen - = -- We have run out of n_left, and we - -- already have bindings mentioning all of ct_tvs - go tidy_env (n_left,tvs_seen) tc_bndrs - | otherwise + run_out :: Maybe Int -> Bool + run_out Nothing = False + run_out (Just n) = n <= 0 + + dec_max :: Maybe Int -> Maybe Int + dec_max = fmap (\n -> n - 1) + + go :: TidyEnv -> Maybe Int -> TcTyVarSet -> [SDoc] -> Bool + -> [TcIdBinder] + -> TcM (TidyEnv, [SDoc], Bool) -- The bool says if we filtered any out + -- because of lack of fuel + go tidy_env _ _ docs discards [] + = return (tidy_env, reverse docs, discards) + go tidy_env n_left tvs_seen docs discards (TcIdBndr id _ : tc_bndrs) = do { (tidy_env', tidy_ty) <- zonkTidyTcType tidy_env (idType id) ; let id_tvs = tyVarsOfType tidy_ty doc = sep [ pprPrefixOcc id <+> dcolon <+> ppr tidy_ty , nest 2 (parens (ptext (sLit "bound at") <+> ppr (getSrcLoc id)))] - ; if id_tvs `intersectsVarSet` ct_tvs - && (n_left > 0 || not (id_tvs `subVarSet` tvs_seen)) - -- Either we n_left is big enough, - -- or this binding mentions a new type variable - then do { (env', docs) <- go tidy_env' (n_left - 1, tvs_seen `unionVarSet` id_tvs) tc_bndrs - ; return (env', doc:docs) } - else go tidy_env (n_left, tvs_seen) tc_bndrs } + new_seen = tvs_seen `unionVarSet` id_tvs + + ; if (want_filtering && id_tvs `disjointVarSet` ct_tvs) + -- We want to filter out this binding anyway + then go tidy_env n_left tvs_seen docs discards tc_bndrs + + else if run_out n_left && id_tvs `subVarSet` tvs_seen + -- We've run out of n_left fuel and this binding only + -- mentions aleady-seen type variables, so discard it + then go tidy_env n_left tvs_seen docs True tc_bndrs + + -- Keep this binding, decrement fuel + else go tidy_env' (dec_max n_left) new_seen (doc:docs) discards tc_bndrs } ----------------------- warnDefaulting :: Cts -> Type -> TcM () diff --git a/docs/users_guide/flags.xml b/docs/users_guide/flags.xml index 03252c26a3..18f8beb563 100644 --- a/docs/users_guide/flags.xml +++ b/docs/users_guide/flags.xml @@ -1501,7 +1501,7 @@ <sect2> <title>Optimisation levels</title> - <para><xref linkend="options-optimise"/></para> + <para>These options are described in more detail in <xref linkend="options-optimise"/></para> <informaltable> <tgroup cols="4" align="left" colsep="1" rowsep="1"> @@ -1531,10 +1531,10 @@ </informaltable> </sect2> - <sect2> + <sect2 id="options-f-compact"> <title>Individual optimisations</title> - <para><xref linkend="options-f"/></para> + <para>These options are described in more detail in <xref linkend="options-f"/>.</para> <informaltable> <tgroup cols="4" align="left" colsep="1" rowsep="1"> @@ -1558,7 +1558,7 @@ <entry><option>-fcse</option></entry> <entry>Turn on common sub-expression elimination. Implied by <option>-O</option>.</entry> <entry>dynamic</entry> - <entry>-fno-cse</entry> + <entry><option>-fno-cse</option></entry> </row> <row> @@ -1634,14 +1634,14 @@ <entry><option>-ffloat-in</option></entry> <entry>Turn on the float-in transformation. Implied by <option>-O</option>.</entry> <entry>dynamic</entry> - <entry>-fno-float-in</entry> + <entry><option>-fno-float-in</option></entry> </row> <row> <entry><option>-ffull-laziness</option></entry> <entry>Turn on full laziness (floating bindings outwards). Implied by <option>-O</option>.</entry> <entry>dynamic</entry> - <entry>-fno-full-laziness</entry> + <entry><option>-fno-full-laziness</option></entry> </row> <row> @@ -1673,14 +1673,21 @@ </row> <row> - <entry><option>-fmax-simplifier-iterations</option></entry> + <entry><option>-fmax-relevant-bindings=N</option></entry> + <entry>Set the maximum number of bindings to display in type error messages (default 6).</entry> + <entry>dynamic</entry> + <entry><option>-fno-max-relevant-bindings</option></entry> + </row> + + <row> + <entry><option>-fmax-simplifier-iterations=N</option></entry> <entry>Set the max iterations for the simplifier</entry> <entry>dynamic</entry> <entry>-</entry> </row> <row> - <entry><option>-fmax-worker-args</option></entry> + <entry><option>-fmax-worker-args=N</option></entry> <entry>If a worker has that many arguments, none will be unpacked anymore (default: 10)</entry> <entry>dynamic</entry> @@ -1744,7 +1751,7 @@ <entry><option>-fspec-constr</option></entry> <entry>Turn on the SpecConstr transformation. Implied by <option>-O2</option>.</entry> <entry>dynamic</entry> - <entry>-fno-spec-constr</entry> + <entry><option>-fno-spec-constr</option></entry> </row> <row> @@ -1767,14 +1774,14 @@ <entry><option>-fspecialise</option></entry> <entry>Turn on specialisation of overloaded functions. Implied by <option>-O</option>.</entry> <entry>dynamic</entry> - <entry>-fno-specialise</entry> + <entry><option>-fno-specialise</option></entry> </row> <row> <entry><option>-fstrictness</option></entry> <entry>Turn on strictness analysis. Implied by <option>-O</option>.</entry> <entry>dynamic</entry> - <entry>-fno-strictness</entry> + <entry><option>-fno-strictness</option></entry> </row> <row> @@ -1789,7 +1796,7 @@ <entry><option>-fstatic-argument-transformation</option></entry> <entry>Turn on the static argument transformation. Implied by <option>-O2</option>.</entry> <entry>dynamic</entry> - <entry>-fno-static-argument-transformation</entry> + <entry><option>-fno-static-argument-transformation</option></entry> </row> <row> diff --git a/docs/users_guide/using.xml b/docs/users_guide/using.xml index 7540279504..4440eec7dd 100644 --- a/docs/users_guide/using.xml +++ b/docs/users_guide/using.xml @@ -1885,12 +1885,59 @@ f "2" = 2 them explicitly (indeed, doing so could lead to unexpected results). A flag <option>-fwombat</option> can be negated by saying <option>-fno-wombat</option>. The flags below are off - by default, except where noted below. + by default, except where noted below. See <xref linkend="options-f-compact"/> + for a compact list. </para> <variablelist> <varlistentry> <term> + <option>-favoid-vect</option> + <indexterm><primary><option></option></primary></indexterm> + </term> + <listitem> + <para>Part of <link linkend="dph">Data Parallel Haskell + (DPH)</link>.</para> + + <para><emphasis>Off by default.</emphasis> Enable the + <emphasis>vectorisation</emphasis> avoidance optimisation. This + optimisation only works when used in combination with the + <option>-fvectorise</option> transformation.</para> + + <para>While vectorisation of code using DPH is often a big win, it + can also produce worse results for some kinds of code. This + optimisation modifies the vectorisation transformation to try to + determine if a function would be better of unvectorised and if + so, do just that.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <option>-fcase-merge</option> + <indexterm><primary><option></option></primary></indexterm> + </term> + <listitem> + <para><emphasis>On by default.</emphasis> + Merge immediately-nested case expressions that scrutinse the same variable. Example +<programlisting> + case x of + Red -> e1 + _ -> case x of + Blue -> e2 + Green -> e3 +==> + case x of + Red -> e1 + Blue -> e2 + Green -> e2 +</programlisting> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> <option>-fcse</option> <indexterm><primary><option>-fcse</option></primary></indexterm> </term> @@ -1904,170 +1951,88 @@ f "2" = 2 <varlistentry> <term> - <option>-fstrictness</option> + <option>-fdicts-cheap</option> <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para> <emphasis>On by default.</emphasis>. - Switch on the strictness analyser. There is a very old paper about GHC's - strictness analyser, <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/simple-strictnes-analyser.ps.gz"> - Measuring the effectiveness of a simple strictness analyser</ulink>, - but the current one is quite a bit different. - </para> - - <para>The strictness analyser figures out when arguments and - variables in a function can be treated 'strictly' (that is they - are always evaluated in the function at some point). This allow - GHC to apply certain optimisations such as unboxing that - otherwise don't apply as they change the semantics of the program - when applied to lazy arguments. + <para>A very experimental flag that makes dictionary-valued + expressions seem cheap to the optimiser. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-funbox-strict-fields</option>: - <indexterm><primary><option>-funbox-strict-fields</option></primary></indexterm> - <indexterm><primary>strict constructor fields</primary></indexterm> - <indexterm><primary>constructor fields, strict</primary></indexterm> + <option>-fdo-lambda-eta-expansion</option> + <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para>This option causes all constructor fields which are marked - strict (i.e. “!”) to be unpacked if possible. It is - equivalent to adding an <literal>UNPACK</literal> pragma to every - strict constructor field (see <xref linkend="unpack-pragma"/>). + <para><emphasis>On by default.</emphasis> + Eta-expand let-bindings to increase their arity. </para> - - <para>This option is a bit of a sledgehammer: it might sometimes - make things worse. Selectively unboxing fields by using - <literal>UNPACK</literal> pragmas might be better. An alternative - is to use <option>-funbox-strict-fields</option> to turn on - unboxing by default but disable it for certain constructor - fields using the <literal>NOUNPACK</literal> pragma (see - <xref linkend="nounpack-pragma"/>).</para> </listitem> </varlistentry> <varlistentry> <term> - <option>-funbox-small-strict-fields</option>: - <indexterm><primary><option>-funbox-small-strict-fields</option></primary></indexterm> - <indexterm><primary>strict constructor fields</primary></indexterm> - <indexterm><primary>constructor fields, strict</primary></indexterm> + <option>-fdo-eta-reduction</option> + <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para><emphasis>On by default.</emphasis>. This option - causes all constructor fields which are marked strict - (i.e. “!”) and which representation is smaller - or equal to the size of a pointer to be unpacked, if - possible. It is equivalent to adding an - <literal>UNPACK</literal> pragma (see <xref - linkend="unpack-pragma"/>) to every strict constructor - field that fulfils the size restriction. - </para> - - <para>For example, the constructor fields in the following - data types -<programlisting> -data A = A !Int -data B = B !A -newtype C = C B -data D = D !C -</programlisting> - would all be represented by a single - <literal>Int#</literal> (see <xref linkend="primitives"/>) - value with - <option>-funbox-small-strict-fields</option> enabled. - </para> - - <para>This option is less of a sledgehammer than - <option>-funbox-strict-fields</option>: it should rarely make things - worse. If you use <option>-funbox-small-strict-fields</option> - to turn on unboxing by default you can disable it for certain - constructor fields using the <literal>NOUNPACK</literal> pragma (see - <xref linkend="nounpack-pragma"/>).</para> - - <para> - Note that for consistency <literal>Double</literal>, - <literal>Word64</literal>, and <literal>Int64</literal> constructor - fields are unpacked on 32-bit platforms, even though they are - technically larger than a pointer on those platforms. + <para><emphasis>On by default.</emphasis> + Eta-reduce lambda expressions, if doing so gets rid of a whole + group of lambdas. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fspec-constr</option> - <indexterm><primary><option>-fspec-constr</option></primary></indexterm> + <option>-feager-blackholing</option> + <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para><emphasis>Off by default, but enabled by -O2.</emphasis> - Turn on call-pattern specialisation; see - <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/spec-constr/index.htm"> - Call-pattern specialisation for Haskell programs</ulink>. - </para> - - <para>This optimisation specializes recursive functions according to - their argument "shapes". This is best explained by example so - consider: -<programlisting> -last :: [a] -> a -last [] = error "last" -last (x : []) = x -last (x : xs) = last xs -</programlisting> - In this code, once we pass the initial check for an empty list we - know that in the recursive case this pattern match is redundant. As - such <option>-fspec-constr</option> will transform the above code - to: -<programlisting> -last :: [a] -> a -last [] = error "last" -last (x : xs) = last' x xs - where - last' x [] = x - last' x (y : ys) = last' y ys -</programlisting> - </para> - - <para>As well avoid unnecessary pattern matching it also helps avoid - unnecessary allocation. This applies when a argument is strict in - the recursive call to itself but not on the initial entry. As - strict recursive branch of the function is created similar to the - above example. + <para>Usually GHC black-holes a thunk only when it switches + threads. This flag makes it do so as soon as the thunk is + entered. See <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/"> + Haskell on a shared-memory multiprocessor</ulink>. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fspecialise</option> - <indexterm><primary><option>-fspecialise</option></primary></indexterm> + <option>-fexcess-precision</option> + <indexterm><primary><option>-fexcess-precision</option></primary></indexterm> </term> <listitem> - <para><emphasis>On by default.</emphasis> - Specialise each type-class-overloaded function defined in this - module for the types at which it is called in this module. Also - specialise imported functions that have an INLINABLE pragma - (<xref linkend="inlinable-pragma"/>) for the types at which they - are called in this module. + <para>When this option is given, intermediate floating + point values can have a <emphasis>greater</emphasis> + precision/range than the final type. Generally this is a + good thing, but some programs may rely on the exact + precision/range of + <literal>Float</literal>/<literal>Double</literal> values + and should not use this option for their compilation.</para> + + <para> + Note that the 32-bit x86 native code generator only + supports excess-precision mode, so neither + <option>-fexcess-precision</option> nor + <option>-fno-excess-precision</option> has any effect. + This is a known bug, see <xref linkend="bugs-ghc" />. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fstatic-argument-transformation</option> - <indexterm><primary><option>-fstatic-argument-transformation</option></primary></indexterm> + <option>-fexpose-all-unfoldings</option> + <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para>Turn on the static argument transformation, which turns a - recursive function into a non-recursive one with a local - recursive loop. See Chapter 7 of - <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/santos-thesis.ps.gz"> - Andre Santos's PhD thesis</ulink> + <para>An experimental flag to expose all unfoldings, even for very + large or recursive functions. This allows for all functions to be + inlined while usually GHC would avoid inlining larger functions. </para> </listitem> </varlistentry> @@ -2130,50 +2095,45 @@ last (x : xs) = last' x xs <varlistentry> <term> - <option>-fdo-lambda-eta-expansion</option> - <indexterm><primary><option></option></primary></indexterm> + <option>--ffun-to-thunk</option> + <indexterm><primary><option>-fignore-asserts</option></primary></indexterm> </term> <listitem> - <para><emphasis>On by default.</emphasis> - Eta-expand let-bindings to increase their arity. + <para>Worker-wrapper removes unused arguments, but usually we + do not remove them all, lest it turn a function closure into a thunk, + thereby perhaps causing extra allocation (since let-no-escape can't happen) + and/or a space leak. This flag + allows worker/wrapper to remove <emphasis>all</emphasis> value lambdas. + Off by default. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fdo-eta-reduction</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fignore-asserts</option> + <indexterm><primary><option>-fignore-asserts</option></primary></indexterm> </term> <listitem> - <para><emphasis>On by default.</emphasis> - Eta-reduce lambda expressions, if doing so gets rid of a whole - group of lambdas. + <para>Causes GHC to ignore uses of the function + <literal>Exception.assert</literal> in source code (in + other words, rewriting <literal>Exception.assert p + e</literal> to <literal>e</literal> (see <xref + linkend="assertions"/>). This flag is turned on by + <option>-O</option>. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fcase-merge</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fignore-interface-pragmas</option> + <indexterm><primary><option>-fignore-interface-pragmas</option></primary></indexterm> </term> <listitem> - <para><emphasis>On by default.</emphasis> - Merge immediately-nested case expressions that scrutinse the same variable. Example -<programlisting> - case x of - Red -> e1 - _ -> case x of - Blue -> e2 - Green -> e3 -==> - case x of - Red -> e1 - Blue -> e2 - Green -> e2 -</programlisting> - </para> + <para>Tells GHC to ignore all inessential information when reading interface files. + That is, even if <filename>M.hi</filename> contains unfolding or strictness information + for a function, GHC will ignore that information.</para> </listitem> </varlistentry> @@ -2195,26 +2155,25 @@ last (x : xs) = last' x xs <varlistentry> <term> - <option>-fdicts-cheap</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fliberate-case-threshold=N</option> + <indexterm><primary><option>-fliberate-case-threshold</option></primary></indexterm> </term> <listitem> - <para>A very experimental flag that makes dictionary-valued - expressions seem cheap to the optimiser. + <para>Set the size threshold for the liberate-case transformation. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-feager-blackholing</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fmax-relevant-bindings=N</option> + <indexterm><primary><option>-fmax-relevant-bindings</option></primary></indexterm> </term> <listitem> - <para>Usually GHC black-holes a thunk only when it switches - threads. This flag makes it do so as soon as the thunk is - entered. See <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/"> - Haskell on a shared-memory multiprocessor</ulink>. + <para>The type checker sometimes displays a fragment of the type environment + in error messages, but only up to some maximum number, set by this flag. + The default is 6. Turning it off with <option>-fno-max-relevant-bindings</option> + gives an unlimited number. </para> </listitem> </varlistentry> @@ -2236,6 +2195,42 @@ last (x : xs) = last' x xs <varlistentry> <term> + <option>-fomit-interface-pragmas</option> + <indexterm><primary><option>-fomit-interface-pragmas</option></primary></indexterm> + </term> + <listitem> + <para>Tells GHC to omit all inessential information from the + interface file generated for the module being compiled (say M). + This means that a module importing M will see only the + <emphasis>types</emphasis> of the functions that M exports, but + not their unfoldings, strictness info, etc. Hence, for example, + no function exported by M will be inlined into an importing module. + The benefit is that modules that import M will need to be + recompiled less often (only when M's exports change their type, not + when they change their implementation).</para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <option>-fomit-yields</option> + <indexterm><primary><option>-fomit-yields</option></primary></indexterm> + </term> + <listitem> + <para><emphasis>On by default.</emphasis> Tells GHC to omit + heap checks when no allocation is being performed. While this improves + binary sizes by about 5%, it also means that threads run in + tight non-allocating loops will not get preempted in a timely + fashion. If it is important to always be able to interrupt such + threads, you should turn this optimization off. Consider also + recompiling all libraries with this optimization turned off, if you + need to guarantee interruptibility. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> <option>-fpedantic-bottoms</option> <indexterm><primary><option>-fpedantic-bottoms</option></primary></indexterm> </term> @@ -2251,6 +2246,38 @@ last (x : xs) = last' x xs <varlistentry> <term> + <option>-fregs-graph</option> + <indexterm><primary><option></option></primary></indexterm> + </term> + <listitem> + <para><emphasis>Off by default, but enabled by -O2. Only applies in + combination with the native code generator.</emphasis> + Use the graph colouring register allocator for register allocation + in the native code generator. By default, GHC uses a simpler, + faster linear register allocator. The downside being that the + linear register allocator usually generates worse code. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> + <option>-fregs-iterative</option> + <indexterm><primary><option></option></primary></indexterm> + </term> + <listitem> + <para><emphasis>Off by default, only applies in combination with + the native code generator.</emphasis> + Use the iterative coalescing graph colouring register allocator for + register allocation in the native code generator. This is the same + register allocator as the <option>-freg-graph</option> one but also + enables iterative coalescing during register allocation. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> <option>-fsimpl-tick-factor=<replaceable>n</replaceable></option> <indexterm><primary><option>-fsimpl-tick-factor</option></primary></indexterm> </term> @@ -2332,19 +2359,6 @@ last (x : xs) = last' x xs <varlistentry> <term> - <option>-fexpose-all-unfoldings</option> - <indexterm><primary><option></option></primary></indexterm> - </term> - <listitem> - <para>An experimental flag to expose all unfoldings, even for very - large or recursive functions. This allows for all functions to be - inlined while usually GHC would avoid inlining larger functions. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> <option>-fvectorise</option> <indexterm><primary><option></option></primary></indexterm> </term> @@ -2363,142 +2377,170 @@ last (x : xs) = last' x xs <varlistentry> <term> - <option>-favoid-vect</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fspec-constr</option> + <indexterm><primary><option>-fspec-constr</option></primary></indexterm> </term> <listitem> - <para>Part of <link linkend="dph">Data Parallel Haskell - (DPH)</link>.</para> + <para><emphasis>Off by default, but enabled by -O2.</emphasis> + Turn on call-pattern specialisation; see + <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/spec-constr/index.htm"> + Call-pattern specialisation for Haskell programs</ulink>. + </para> - <para><emphasis>Off by default.</emphasis> Enable the - <emphasis>vectorisation</emphasis> avoidance optimisation. This - optimisation only works when used in combination with the - <option>-fvectorise</option> transformation.</para> + <para>This optimisation specializes recursive functions according to + their argument "shapes". This is best explained by example so + consider: +<programlisting> +last :: [a] -> a +last [] = error "last" +last (x : []) = x +last (x : xs) = last xs +</programlisting> + In this code, once we pass the initial check for an empty list we + know that in the recursive case this pattern match is redundant. As + such <option>-fspec-constr</option> will transform the above code + to: +<programlisting> +last :: [a] -> a +last [] = error "last" +last (x : xs) = last' x xs + where + last' x [] = x + last' x (y : ys) = last' y ys +</programlisting> + </para> - <para>While vectorisation of code using DPH is often a big win, it - can also produce worse results for some kinds of code. This - optimisation modifies the vectorisation transformation to try to - determine if a function would be better of unvectorised and if - so, do just that.</para> + <para>As well avoid unnecessary pattern matching it also helps avoid + unnecessary allocation. This applies when a argument is strict in + the recursive call to itself but not on the initial entry. As + strict recursive branch of the function is created similar to the + above example. + </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fregs-graph</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fspecialise</option> + <indexterm><primary><option>-fspecialise</option></primary></indexterm> </term> <listitem> - <para><emphasis>Off by default, but enabled by -O2. Only applies in - combination with the native code generator.</emphasis> - Use the graph colouring register allocator for register allocation - in the native code generator. By default, GHC uses a simpler, - faster linear register allocator. The downside being that the - linear register allocator usually generates worse code. + <para><emphasis>On by default.</emphasis> + Specialise each type-class-overloaded function defined in this + module for the types at which it is called in this module. Also + specialise imported functions that have an INLINABLE pragma + (<xref linkend="inlinable-pragma"/>) for the types at which they + are called in this module. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fregs-iterative</option> - <indexterm><primary><option></option></primary></indexterm> + <option>-fstatic-argument-transformation</option> + <indexterm><primary><option>-fstatic-argument-transformation</option></primary></indexterm> </term> <listitem> - <para><emphasis>Off by default, only applies in combination with - the native code generator.</emphasis> - Use the iterative coalescing graph colouring register allocator for - register allocation in the native code generator. This is the same - register allocator as the <option>-freg-graph</option> one but also - enables iterative coalescing during register allocation. + <para>Turn on the static argument transformation, which turns a + recursive function into a non-recursive one with a local + recursive loop. See Chapter 7 of + <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/santos-thesis.ps.gz"> + Andre Santos's PhD thesis</ulink> </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fexcess-precision</option> - <indexterm><primary><option>-fexcess-precision</option></primary></indexterm> + <option>-fstrictness</option> + <indexterm><primary><option></option></primary></indexterm> </term> <listitem> - <para>When this option is given, intermediate floating - point values can have a <emphasis>greater</emphasis> - precision/range than the final type. Generally this is a - good thing, but some programs may rely on the exact - precision/range of - <literal>Float</literal>/<literal>Double</literal> values - and should not use this option for their compilation.</para> + <para> <emphasis>On by default.</emphasis>. + Switch on the strictness analyser. There is a very old paper about GHC's + strictness analyser, <ulink url="http://research.microsoft.com/en-us/um/people/simonpj/papers/simple-strictnes-analyser.ps.gz"> + Measuring the effectiveness of a simple strictness analyser</ulink>, + but the current one is quite a bit different. + </para> - <para> - Note that the 32-bit x86 native code generator only - supports excess-precision mode, so neither - <option>-fexcess-precision</option> nor - <option>-fno-excess-precision</option> has any effect. - This is a known bug, see <xref linkend="bugs-ghc" />. + <para>The strictness analyser figures out when arguments and + variables in a function can be treated 'strictly' (that is they + are always evaluated in the function at some point). This allow + GHC to apply certain optimisations such as unboxing that + otherwise don't apply as they change the semantics of the program + when applied to lazy arguments. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fignore-asserts</option> - <indexterm><primary><option>-fignore-asserts</option></primary></indexterm> + <option>-funbox-strict-fields</option>: + <indexterm><primary><option>-funbox-strict-fields</option></primary></indexterm> + <indexterm><primary>strict constructor fields</primary></indexterm> + <indexterm><primary>constructor fields, strict</primary></indexterm> </term> <listitem> - <para>Causes GHC to ignore uses of the function - <literal>Exception.assert</literal> in source code (in - other words, rewriting <literal>Exception.assert p - e</literal> to <literal>e</literal> (see <xref - linkend="assertions"/>). This flag is turned on by - <option>-O</option>. + <para>This option causes all constructor fields which are marked + strict (i.e. “!”) to be unpacked if possible. It is + equivalent to adding an <literal>UNPACK</literal> pragma to every + strict constructor field (see <xref linkend="unpack-pragma"/>). </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <option>-fignore-interface-pragmas</option> - <indexterm><primary><option>-fignore-interface-pragmas</option></primary></indexterm> - </term> - <listitem> - <para>Tells GHC to ignore all inessential information when reading interface files. - That is, even if <filename>M.hi</filename> contains unfolding or strictness information - for a function, GHC will ignore that information.</para> + <para>This option is a bit of a sledgehammer: it might sometimes + make things worse. Selectively unboxing fields by using + <literal>UNPACK</literal> pragmas might be better. An alternative + is to use <option>-funbox-strict-fields</option> to turn on + unboxing by default but disable it for certain constructor + fields using the <literal>NOUNPACK</literal> pragma (see + <xref linkend="nounpack-pragma"/>).</para> </listitem> </varlistentry> <varlistentry> <term> - <option>-fomit-interface-pragmas</option> - <indexterm><primary><option>-fomit-interface-pragmas</option></primary></indexterm> + <option>-funbox-small-strict-fields</option>: + <indexterm><primary><option>-funbox-small-strict-fields</option></primary></indexterm> + <indexterm><primary>strict constructor fields</primary></indexterm> + <indexterm><primary>constructor fields, strict</primary></indexterm> </term> <listitem> - <para>Tells GHC to omit all inessential information from the - interface file generated for the module being compiled (say M). - This means that a module importing M will see only the - <emphasis>types</emphasis> of the functions that M exports, but - not their unfoldings, strictness info, etc. Hence, for example, - no function exported by M will be inlined into an importing module. - The benefit is that modules that import M will need to be - recompiled less often (only when M's exports change their type, not - when they change their implementation).</para> - </listitem> - </varlistentry> + <para><emphasis>On by default.</emphasis>. This option + causes all constructor fields which are marked strict + (i.e. “!”) and which representation is smaller + or equal to the size of a pointer to be unpacked, if + possible. It is equivalent to adding an + <literal>UNPACK</literal> pragma (see <xref + linkend="unpack-pragma"/>) to every strict constructor + field that fulfils the size restriction. + </para> - <varlistentry> - <term> - <option>-fomit-yields</option> - <indexterm><primary><option>-fomit-yields</option></primary></indexterm> - </term> - <listitem> - <para><emphasis>On by default.</emphasis> Tells GHC to omit - heap checks when no allocation is being performed. While this improves - binary sizes by about 5%, it also means that threads run in - tight non-allocating loops will not get preempted in a timely - fashion. If it is important to always be able to interrupt such - threads, you should turn this optimization off. Consider also - recompiling all libraries with this optimization turned off, if you - need to guarantee interruptibility. + <para>For example, the constructor fields in the following + data types +<programlisting> +data A = A !Int +data B = B !A +newtype C = C B +data D = D !C +</programlisting> + would all be represented by a single + <literal>Int#</literal> (see <xref linkend="primitives"/>) + value with + <option>-funbox-small-strict-fields</option> enabled. + </para> + + <para>This option is less of a sledgehammer than + <option>-funbox-strict-fields</option>: it should rarely make things + worse. If you use <option>-funbox-small-strict-fields</option> + to turn on unboxing by default you can disable it for certain + constructor fields using the <literal>NOUNPACK</literal> pragma (see + <xref linkend="nounpack-pragma"/>).</para> + + <para> + Note that for consistency <literal>Double</literal>, + <literal>Word64</literal>, and <literal>Int64</literal> constructor + fields are unpacked on 32-bit platforms, even though they are + technically larger than a pointer on those platforms. </para> </listitem> </varlistentry> |