Cheng Shao pushed to branch wip/o0-fmax-simplifier-iterations-2 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • changelog.d/ghc-o0-fmax-simplifier-iterations-2
    1
    +section: compiler
    
    2
    +synopsis: Set ``-fmax-simplifier-iterations=2`` for ``-O0``
    
    3
    +issues: #27326
    
    4
    +mrs: !16136
    
    5
    +
    
    6
    +description: {
    
    7
    +  The maximum number of simplifier iterations
    
    8
    +  (``-fmax-simplifier-iterations``) is now tied to the optimisation
    
    9
    +  level: at most 2 iterations at ``-O0`` (previously 4) and still 4 at
    
    10
    +  ``-O1``/``-O2``. This speeds up unoptimised compilation. An explicit
    
    11
    +  ``-fmax-simplifier-iterations=⟨n⟩`` still overrides the default, as
    
    12
    +  long as it appears after the ``-O`` flag on the command line.
    
    13
    +}

  • compiler/GHC/Driver/DynFlags.hs
    ... ... @@ -576,7 +576,8 @@ defaultDynFlags mySettings =
    576 576
             verbosity               = 0,
    
    577 577
             debugLevel              = 0,
    
    578 578
             simplPhases             = 2,
    
    579
    -        maxSimplIterations      = 4,
    
    579
    +        maxSimplIterations      = 2,  -- The -O0 default. 'updOptLevel' raises this to 4 at -O1/-O2. See
    
    580
    +                                      -- Note [Simplifier iterations and the optimisation level].
    
    580 581
             ruleCheck               = Nothing,
    
    581 582
             binBlobThreshold        = Just 500000, -- 500K is a good default (see #16190)
    
    582 583
             maxRelevantBinds        = Just 6,
    

  • compiler/GHC/Driver/Session.hs
    ... ... @@ -786,15 +786,45 @@ setInteractivePrint f d = d { interactivePrint = Just f}
    786 786
     -----------------------------------------------------------------------------
    
    787 787
     -- Setting the optimisation level
    
    788 788
     
    
    789
    +{- Note [Simplifier iterations and the optimisation level]
    
    790
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    791
    +At -O0 the only Core-to-Core pass that runs is the final simplifier pass (see
    
    792
    +'GHC.Core.Opt.Pipeline.getCoreToDo'); every optimisation-specific pass is gated
    
    793
    +off. We therefore want as few simplifier iterations as possible at -O0, since
    
    794
    +the later iterations only chase optimisation opportunities the user opted out of
    
    795
    +by choosing -O0.
    
    796
    +
    
    797
    +We cannot drop to a *single* iteration, though. The final simplifier pass is
    
    798
    +still load-bearing for correctness: a single iteration can leave a recursive
    
    799
    +superclass dictionary with an unreduced superclass selector applied to it, which
    
    800
    +then builds an infinite dictionary tower and diverges (<<loop>> at -O, OOM at
    
    801
    +-O0). See #21973 and test T21973b. The fix needs (at least) two iterations: the
    
    802
    +first inlines the dictionary functions to expose a constructor, and the second
    
    803
    +reduces the superclass selector against it, making the recursive dictionary
    
    804
    +dead. Empirically two iterations suffice across the known reproducers; the
    
    805
    +simplifier offers no proof of a fixed bound, so we keep a small margin rather
    
    806
    +than the bare minimum.
    
    807
    +
    
    808
    +So we tie 'maxSimplIterations' to the optimisation level: 2 iterations at -O0
    
    809
    +and 4 at -O1/-O2. This is a noticeable win for unoptimised compilation, and most
    
    810
    +noticeable for the byte-code interpreter (GHCi), which defaults to -O0 and codegen
    
    811
    +does less work compared to other backends.
    
    812
    +
    
    813
    +An explicit -fmax-simplifier-iterations=⟨n⟩ still overrides this, as long as it
    
    814
    +appears after the -O flag on the command line (the usual flag-ordering rule for
    
    815
    +options that -O adjusts).
    
    816
    +-}
    
    817
    +
    
    789 818
     updOptLevelChanged :: Int -> DynFlags -> (DynFlags, Bool)
    
    790 819
     -- ^ Sets the 'DynFlags' to be appropriate to the optimisation level and signals if any changes took place
    
    791 820
     updOptLevelChanged n dfs
    
    792
    -  = (dfs3, changed1 || changed2 || changed3)
    
    821
    +  = (dfs4, changed1 || changed2 || changed3 || changed4)
    
    793 822
       where
    
    794 823
        final_n = max 0 (min 2 n)    -- Clamp to 0 <= n <= 2
    
    795 824
        (dfs1, changed1) = foldr unset (dfs , False) remove_gopts
    
    796 825
        (dfs2, changed2) = foldr set   (dfs1, False) extra_gopts
    
    797 826
        (dfs3, changed3) = setLlvmOptLevel dfs2
    
    827
    +   (dfs4, changed4) = setSimplIterations dfs3
    
    798 828
     
    
    799 829
        extra_gopts  = [ f | (ns,f) <- optLevelFlags, final_n `elem` ns ]
    
    800 830
        remove_gopts = [ f | (ns,f) <- optLevelFlags, final_n `notElem` ns ]
    
    ... ... @@ -814,6 +844,14 @@ updOptLevelChanged n dfs
    814 844
          | llvmOptLevel dfs /= llvm_n = (dfs{ llvmOptLevel = llvm_n }, True)
    
    815 845
          | otherwise = (dfs, False)
    
    816 846
     
    
    847
    +   -- See Note [Simplifier iterations and the optimisation level]
    
    848
    +   simpl_iters = if final_n == 0 then 2 else 4
    
    849
    +
    
    850
    +   setSimplIterations dfs
    
    851
    +     | maxSimplIterations dfs /= simpl_iters =
    
    852
    +         (dfs{ maxSimplIterations = simpl_iters }, True)
    
    853
    +     | otherwise = (dfs, False)
    
    854
    +
    
    817 855
     updOptLevel :: Int -> DynFlags -> DynFlags
    
    818 856
     -- ^ Sets the 'DynFlags' to be appropriate to the optimisation level
    
    819 857
     updOptLevel n = fst . updOptLevelChanged n
    

  • docs/users_guide/using-optimisation.rst
    ... ... @@ -914,11 +914,12 @@ as such you shouldn't need to set any of them explicitly. A flag
    914 914
         :ghc-flag:`-Wincomplete-patterns` and :ghc-flag:`-Wincomplete-uni-patterns`.
    
    915 915
     
    
    916 916
     .. ghc-flag:: -fmax-simplifier-iterations=⟨n⟩
    
    917
    -    :shortdesc: *default: 4.* Set the max iterations for the simplifier.
    
    917
    +    :shortdesc: *default: 2 at :ghc-flag:`-O0`, 4 otherwise.* Set the max iterations
    
    918
    +        for the simplifier.
    
    918 919
         :type: dynamic
    
    919 920
         :category:
    
    920 921
     
    
    921
    -    :default: 4
    
    922
    +    :default: 2 at :ghc-flag:`-O0`, 4 at :ghc-flag:`-O1` and :ghc-flag:`-O2`
    
    922 923
     
    
    923 924
         Sets the maximal number of iterations for the simplifier.
    
    924 925