Simon Peyton Jones pushed to branch wip/T26615 at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/Core/Opt/SpecConstr.hs
    ... ... @@ -1781,7 +1781,8 @@ specRec :: ScEnv
    1781 1781
                                                --     plus details of specialisations
    
    1782 1782
     
    
    1783 1783
     specRec env body_calls rhs_infos
    
    1784
    -  = go 1 body_calls nullUsage (map initSpecInfo rhs_infos) []
    
    1784
    +  = -- pprTrace "specRec" (ppr (map ri_fn rhs_infos) $$ ppr body_calls) $
    
    1785
    +    go 1 body_calls nullUsage (map initSpecInfo rhs_infos) []
    
    1785 1786
         -- body_calls: see Note [Seeding recursive groups]
    
    1786 1787
         -- NB: 'go' always calls 'specialise' once, which in turn unleashes
    
    1787 1788
         --     si_mb_unspec if there are any boring calls in body_calls,
    
    ... ... @@ -1801,7 +1802,7 @@ specRec env body_calls rhs_infos
    1801 1802
         go n_iter seed_calls usg_so_far spec_infos ws_so_far
    
    1802 1803
           = -- pprTrace "specRec3" (vcat [ text "bndrs" <+> ppr (map ri_fn rhs_infos)
    
    1803 1804
             --                           , text "iteration" <+> int n_iter
    
    1804
    -        --                          , text "spec_infos" <+> ppr (map (map os_pat . si_specs) spec_infos)
    
    1805
    +        --                           , text "spec_infos" <+> ppr (map (map os_pat . si_specs) spec_infos)
    
    1805 1806
             --                    ]) $
    
    1806 1807
             do  { specs_w_usg <- zipWithM (specialise env seed_calls) rhs_infos spec_infos
    
    1807 1808
     
    

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -68,7 +68,6 @@ import GHC.Unit.Module.ModGuts
    68 68
     import GHC.Core.Unfold
    
    69 69
     
    
    70 70
     import Data.List( partition )
    
    71
    --- import Data.List.NonEmpty ( NonEmpty (..) )
    
    72 71
     
    
    73 72
     {-
    
    74 73
     ************************************************************************
    
    ... ... @@ -1617,11 +1616,12 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1617 1616
         fn_type   = idType fn
    
    1618 1617
         fn_arity  = idArity fn
    
    1619 1618
         fn_unf    = realIdUnfolding fn  -- Ignore loop-breaker-ness here
    
    1620
    -    inl_prag  = idInlinePragma fn
    
    1621
    -    inl_act   = inlinePragmaActivation inl_prag
    
    1619
    +    fn_prag   = idInlinePragma fn
    
    1620
    +    rule_act  = inlinePragmaActivation fn_prag
    
    1621
    +                -- rule_act: see Note [Auto-specialisation and RULES]
    
    1622 1622
         is_active :: Activation -> Bool
    
    1623
    -    is_active = isActive (SimplPhaseRange (beginPhase inl_act) (endPhase inl_act))
    
    1624
    -         -- is_active: inl_act is the activation we are going to put in the new
    
    1623
    +    is_active = isActive (SimplPhaseRange (beginPhase rule_act) (endPhase rule_act))
    
    1624
    +         -- is_active: rule_act is the activation we are going to put in the new
    
    1625 1625
              --   SPEC rule; so we want to see if it is covered by another rule with
    
    1626 1626
              --   that same activation.
    
    1627 1627
         is_local  = isLocalId fn
    
    ... ... @@ -1643,7 +1643,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1643 1643
           , isStrongLoopBreaker (idOccInfo fn) -- in GHC.Core.Opt.OccurAnal
    
    1644 1644
           = neverInlinePragma
    
    1645 1645
           | otherwise
    
    1646
    -      = inl_prag
    
    1646
    +      = fn_prag
    
    1647 1647
     
    
    1648 1648
         not_in_scope :: InterestingVarFun
    
    1649 1649
         not_in_scope v = isLocalVar v && not (v `elemInScopeSet` in_scope)
    
    ... ... @@ -1785,7 +1785,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1785 1785
                            | otherwise = -- Specialising local fn
    
    1786 1786
                                          text "SPEC"
    
    1787 1787
     
    
    1788
    -                spec_rule = mkSpecRule dflags this_mod True inl_act
    
    1788
    +                spec_rule = mkSpecRule dflags this_mod True rule_act
    
    1789 1789
                                         herald fn all_rule_bndrs rule_lhs_args
    
    1790 1790
                                         (mkVarApps (Var spec_fn) rule_rhs_args1)
    
    1791 1791
     
    
    ... ... @@ -1795,9 +1795,10 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1795 1795
                                            , ppr spec_rule
    
    1796 1796
                                            , text "acc" <+> ppr rules_acc
    
    1797 1797
                                            , text "existing" <+> ppr existing_rules
    
    1798
    +                                       , text "rule_act" <+> ppr rule_act
    
    1798 1799
                                            ]
    
    1799 1800
     
    
    1800
    -           ; -- pprTrace "spec_call: rule" _rule_trace_doc
    
    1801
    +           ; pprTrace "spec_call: rule" _rule_trace_doc
    
    1801 1802
                  return ( spec_rule            : rules_acc
    
    1802 1803
                         , (spec_fn, spec_rhs1) : pairs_acc
    
    1803 1804
                         , rhs_uds2 `thenUDs` uds_acc
    
    ... ... @@ -2380,12 +2381,13 @@ Thus when adding
    2380 2381
     also add
    
    2381 2382
             RULE f g_spec = 0
    
    2382 2383
     
    
    2383
    -But that's a bit complicated.  For now we ask the programmer's help,
    
    2384
    -by *copying the INLINE activation pragma* to the auto-specialised
    
    2385
    -rule.  So if g says {-# NOINLINE[2] g #-}, then the auto-spec rule
    
    2386
    -will also not be active until phase 2.  And that's what programmers
    
    2387
    -should jolly well do anyway, even aside from specialisation, to ensure
    
    2388
    -that g doesn't inline too early.
    
    2384
    +But that's a bit complicated.  For now we lean on the programmer:
    
    2385
    + * Set the activation of the RULE is the same as the activation of the Id,
    
    2386
    +   i.e. (idInlineActivation g)
    
    2387
    +
    
    2388
    +So if `g` says {-# NOINLINE[2] g #-}, then the auto-spec rule will also not be
    
    2389
    +active until phase 2.  And that's what programmers should jolly well do anyway,
    
    2390
    +even aside from specialisation, to ensure that `g` doesn't inline too early.
    
    2389 2391
     
    
    2390 2392
     This in turn means that the RULE would never fire for a NOINLINE
    
    2391 2393
     thing so not much point in generating a specialisation at all.
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -703,8 +703,14 @@ mergeCaseAlts outer_bndr (Alt DEFAULT _ deflt_rhs : outer_alts)
    703 703
           = do { (joins, alts) <- go body
    
    704 704
     
    
    705 705
                  -- Check for capture; but only if we could otherwise do a merge
    
    706
    -           ; let capture = outer_bndr `elem` bindersOf bind
    
    707
    -                           || outer_bndr `elemVarSet` bindFreeVars bind
    
    706
    +             --    (i.e. the recursive `go` succeeds)
    
    707
    +             -- "Capture" means
    
    708
    +             --    (a) case x of r { DEFAULT -> join r = ... in ...r... }
    
    709
    +             --    (b) case x of r { DEFAULT -> join j = ...r.. in ... }
    
    710
    +             -- In both cases we can't float the join point out
    
    711
    +             -- because r changes its meaning
    
    712
    +           ; let capture = outer_bndr `elem` bindersOf bind          -- (a)
    
    713
    +                        || outer_bndr `elemVarSet` bindFreeVars bind -- (b)
    
    708 714
                ; guard (not capture)
    
    709 715
     
    
    710 716
                ; return (bind:joins, alts ) }