diff options
| author | Simon Peyton Jones <simonpj@microsoft.com> | 2013-08-28 15:12:17 +0100 | 
|---|---|---|
| committer | Simon Peyton Jones <simonpj@microsoft.com> | 2013-08-29 16:45:19 +0100 | 
| commit | a1efe57ed2b5e90c0a562ead754f44821c5434c8 (patch) | |
| tree | 6a2970658b1bc22d81c589da5a3418914f8fde7d | |
| parent | a34300cba525c07164a77f6802a1a957aa63c969 (diff) | |
| download | haskell-a1efe57ed2b5e90c0a562ead754f44821c5434c8.tar.gz | |
Display the full type environment when reporting type holes
This fixes Trac #8191.
The patch also adds and documents a new flag -fmax-relevant-bindings=N
which lets you control how many bindings in the type environment are shown.
| -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>  | 
