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

Commits:

3 changed files:

Changes:

  • compiler/GHC/Core/Opt/Simplify/Env.hs
    ... ... @@ -823,8 +823,8 @@ andFF FltOkSpec _ = FltOkSpec
    823 823
     andFF FltLifted  flt        = flt
    
    824 824
     
    
    825 825
     
    
    826
    -doFloatFromRhs :: SimplEnv -> TopLevelFlag -> RecFlag -> Bool
    
    827
    -               -> [OutTyVar] -> SimplFloats -> OutExpr -> Bool
    
    826
    +doFloatFromRhs :: SimplEnv -> TopLevelFlag -> RecFlag -> Bool -> [OutTyVar]
    
    827
    +               -> SimplFloats -> OutExpr -> Bool
    
    828 828
     -- If you change this function look also at FloatIn.noFloatIntoRhs
    
    829 829
     doFloatFromRhs env lvl rec strict_bind tvs (SimplFloats { sfLetFloats = LetFloats fs ff }) rhs
    
    830 830
       = not (isNilOL fs)
    

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -2626,17 +2626,23 @@ specHeader subst (bndr:bndrs) (SpecType ty : args)
    2626 2626
              -- See (MP2) in Note [Specialising polymorphic dictionaries]
    
    2627 2627
              let in_scope = Core.substInScopeSet subst
    
    2628 2628
                  not_in_scope tv = not (tv `elemInScopeSet` in_scope)
    
    2629
    +
    
    2630
    +             expanded_ty = expandSomeTyVarUnfoldings not_in_scope ty
    
    2631
    +                  -- expanded_ty: consider f @(Maybe (a{=Int})
    
    2632
    +                  -- We don't want to abstract over `a`!  So, expand
    
    2633
    +                  -- unfoldings of any not-in-scope tyavars
    
    2634
    +
    
    2629 2635
                  free_tvs = scopedSort $ fvVarList $
    
    2630 2636
                             filterFV not_in_scope  $
    
    2631
    -                        tyCoFVsOfType ty
    
    2637
    +                        tyCoFVsOfType expanded_ty
    
    2632 2638
                  subst1 = subst `Core.extendSubstInScopeList` free_tvs
    
    2633 2639
     
    
    2634
    -       ; let subst2 = Core.extendTvSubst subst1 bndr ty
    
    2640
    +       ; let subst2 = Core.extendTvSubst subst1 bndr expanded_ty
    
    2635 2641
            ; (useful, subst3, rule_bs, rule_args, spec_bs, dx, spec_args)
    
    2636 2642
                  <- specHeader subst2 bndrs args
    
    2637 2643
            ; pure ( useful, subst3
    
    2638
    -              , free_tvs ++ rule_bs,     Type ty : rule_args
    
    2639
    -              , free_tvs ++ spec_bs, dx, Type ty : spec_args ) }
    
    2644
    +              , free_tvs ++ rule_bs,     Type expanded_ty : rule_args
    
    2645
    +              , free_tvs ++ spec_bs, dx, Type expanded_ty : spec_args ) }
    
    2640 2646
     
    
    2641 2647
     -- Next we have a type that we don't want to specialise. We need to perform
    
    2642 2648
     -- a substitution on it (in case the type refers to 'a'). Additionally, we need
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -1618,6 +1618,101 @@ in this (which it previously was):
    1618 1618
                                   in g
    
    1619 1619
                           False -> \x. x
    
    1620 1620
                 in \w. v True
    
    1621
    +
    
    1622
    +Note [isCheapApp: bottoming functions]
    
    1623
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1624
    +I'm not sure why we have a special case for bottoming
    
    1625
    +functions in isCheapApp.  Maybe we don't need it.
    
    1626
    +
    
    1627
    +Note [exprIsExpandable]
    
    1628
    +~~~~~~~~~~~~~~~~~~~~~~~
    
    1629
    +An expression is "expandable" if we are willing to duplicate it, if doing
    
    1630
    +so might make a RULE or case-of-constructor fire.  Consider
    
    1631
    +   let x = (a,b)
    
    1632
    +       y = build g
    
    1633
    +   in ....(case x of (p,q) -> rhs)....(foldr k z y)....
    
    1634
    +
    
    1635
    +We don't inline 'x' or 'y' (see Note [Lone variables] in GHC.Core.Unfold),
    
    1636
    +but we do want
    
    1637
    +
    
    1638
    + * the case-expression to simplify
    
    1639
    +   (via exprIsConApp_maybe, exprIsLiteral_maybe)
    
    1640
    +
    
    1641
    + * the foldr/build RULE to fire
    
    1642
    +   (by expanding the unfolding during rule matching)
    
    1643
    +
    
    1644
    +So we classify the unfolding of a let-binding as "expandable" (via the
    
    1645
    +uf_expandable field) if we want to do this kind of on-the-fly
    
    1646
    +expansion.  Specifically:
    
    1647
    +
    
    1648
    +* True of constructor applications (K a b)
    
    1649
    +
    
    1650
    +* True of applications of a "CONLIKE" Id; see Note [CONLIKE pragma] in GHC.Types.Basic.
    
    1651
    +  (NB: exprIsCheap might not be true of this)
    
    1652
    +
    
    1653
    +* False of case-expressions.  If we have
    
    1654
    +    let x = case ... in ...(case x of ...)...
    
    1655
    +  we won't simplify.  We have to inline x.  See #14688.
    
    1656
    +
    
    1657
    +* False of let-expressions (same reason); and in any case we
    
    1658
    +  float lets out of an RHS if doing so will reveal an expandable
    
    1659
    +  application (see SimplEnv.doFloatFromRhs).
    
    1660
    +
    
    1661
    +* Take care: exprIsExpandable should /not/ be true of primops.  I
    
    1662
    +  found this in test T5623a:
    
    1663
    +    let q = /\a. Ptr a (a +# b)
    
    1664
    +    in case q @ Float of Ptr v -> ...q...
    
    1665
    +
    
    1666
    +  q's inlining should not be expandable, else exprIsConApp_maybe will
    
    1667
    +  say that (q @ Float) expands to (Ptr a (a +# b)), and that will
    
    1668
    +  duplicate the (a +# b) primop, which we should not do lightly.
    
    1669
    +  (It's quite hard to trigger this bug, but T13155 does so for GHC 8.0.)
    
    1670
    +
    
    1671
    +NB: exprIsWorkFree implies exprIsExpandable.
    
    1672
    +
    
    1673
    +Note [isExpandableApp: bottoming functions]
    
    1674
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1675
    +It's important that isExpandableApp does not respond True to bottoming
    
    1676
    +functions.  Recall  undefined :: HasCallStack => a
    
    1677
    +Suppose isExpandableApp responded True to (undefined d), and we had:
    
    1678
    +
    
    1679
    +  x = undefined <dict-expr>
    
    1680
    +
    
    1681
    +Then Simplify.prepareRhs would ANF the RHS:
    
    1682
    +
    
    1683
    +  d = <dict-expr>
    
    1684
    +  x = undefined d
    
    1685
    +
    
    1686
    +This is already bad: we gain nothing from having x bound to (undefined
    
    1687
    +var), unlike the case for data constructors.  Worse, we get the
    
    1688
    +simplifier loop described in OccurAnal Note [Cascading inlines].
    
    1689
    +Suppose x occurs just once; OccurAnal.occAnalNonRecRhs decides x will
    
    1690
    +certainly_inline; so we end up inlining d right back into x; but in
    
    1691
    +the end x doesn't inline because it is bottom (preInlineUnconditionally);
    
    1692
    +so the process repeats.. We could elaborate the certainly_inline logic
    
    1693
    +some more, but it's better just to treat bottoming bindings as
    
    1694
    +non-expandable, because ANFing them is a bad idea in the first place.
    
    1695
    +
    
    1696
    +Note [Record selection]
    
    1697
    +~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1698
    +I'm experimenting with making record selection
    
    1699
    +look cheap, so we will substitute it inside a
    
    1700
    +lambda.  Particularly for dictionary field selection.
    
    1701
    +
    
    1702
    +BUT: Take care with (sel d x)!  The (sel d) might be cheap, but
    
    1703
    +there's no guarantee that (sel d x) will be too.  Hence (n_val_args == 1)
    
    1704
    +
    
    1705
    +Note [Expandable overloadings]
    
    1706
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1707
    +Suppose the user wrote this
    
    1708
    +   {-# RULE  forall x. foo (negate x) = h x #-}
    
    1709
    +   f x = ....(foo (negate x))....
    
    1710
    +They'd expect the rule to fire. But since negate is overloaded, we might
    
    1711
    +get this:
    
    1712
    +    f = \d -> let n = negate d in \x -> ...foo (n x)...
    
    1713
    +So we treat the application of a function (negate in this case) to a
    
    1714
    +*dictionary* as expandable.  In effect, every function is CONLIKE when
    
    1715
    +it's applied only to dictionaries.
    
    1621 1716
     -}
    
    1622 1717
     
    
    1623 1718
     -------------------------------------
    
    ... ... @@ -1690,6 +1785,10 @@ isWorkFreeApp fn n_val_args
    1690 1785
           _                -> False
    
    1691 1786
     
    
    1692 1787
     isCheapApp :: CheapAppFun
    
    1788
    +-- Like isWorkFreeApp, but add:
    
    1789
    +--   - bottoming applications
    
    1790
    +--   - cheap (rather than just work-free) primops
    
    1791
    +--   - record selectors applied to just the record
    
    1693 1792
     isCheapApp fn n_val_args
    
    1694 1793
       | isWorkFreeApp fn n_val_args = True
    
    1695 1794
       | isDeadEndId fn              = True  -- See Note [isCheapApp: bottoming functions]
    
    ... ... @@ -1706,6 +1805,10 @@ isCheapApp fn n_val_args
    1706 1805
             -- to bother to check the number of args
    
    1707 1806
     
    
    1708 1807
     isExpandableApp :: CheapAppFun
    
    1808
    +-- Like isWorkFreeApp, but add:
    
    1809
    +--   - record selectors applied to just the record
    
    1810
    +--   - ConLike Ids (if not bottoming)
    
    1811
    +--   - a function applied to dictionaries
    
    1709 1812
     isExpandableApp fn n_val_args
    
    1710 1813
       | isWorkFreeApp fn n_val_args = True
    
    1711 1814
       | otherwise
    
    ... ... @@ -1737,101 +1840,6 @@ isExpandableApp fn n_val_args
    1737 1840
            | otherwise
    
    1738 1841
            = False
    
    1739 1842
     
    
    1740
    -{- Note [isCheapApp: bottoming functions]
    
    1741
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1742
    -I'm not sure why we have a special case for bottoming
    
    1743
    -functions in isCheapApp.  Maybe we don't need it.
    
    1744
    -
    
    1745
    -Note [exprIsExpandable]
    
    1746
    -~~~~~~~~~~~~~~~~~~~~~~~
    
    1747
    -An expression is "expandable" if we are willing to duplicate it, if doing
    
    1748
    -so might make a RULE or case-of-constructor fire.  Consider
    
    1749
    -   let x = (a,b)
    
    1750
    -       y = build g
    
    1751
    -   in ....(case x of (p,q) -> rhs)....(foldr k z y)....
    
    1752
    -
    
    1753
    -We don't inline 'x' or 'y' (see Note [Lone variables] in GHC.Core.Unfold),
    
    1754
    -but we do want
    
    1755
    -
    
    1756
    - * the case-expression to simplify
    
    1757
    -   (via exprIsConApp_maybe, exprIsLiteral_maybe)
    
    1758
    -
    
    1759
    - * the foldr/build RULE to fire
    
    1760
    -   (by expanding the unfolding during rule matching)
    
    1761
    -
    
    1762
    -So we classify the unfolding of a let-binding as "expandable" (via the
    
    1763
    -uf_expandable field) if we want to do this kind of on-the-fly
    
    1764
    -expansion.  Specifically:
    
    1765
    -
    
    1766
    -* True of constructor applications (K a b)
    
    1767
    -
    
    1768
    -* True of applications of a "CONLIKE" Id; see Note [CONLIKE pragma] in GHC.Types.Basic.
    
    1769
    -  (NB: exprIsCheap might not be true of this)
    
    1770
    -
    
    1771
    -* False of case-expressions.  If we have
    
    1772
    -    let x = case ... in ...(case x of ...)...
    
    1773
    -  we won't simplify.  We have to inline x.  See #14688.
    
    1774
    -
    
    1775
    -* False of let-expressions (same reason); and in any case we
    
    1776
    -  float lets out of an RHS if doing so will reveal an expandable
    
    1777
    -  application (see SimplEnv.doFloatFromRhs).
    
    1778
    -
    
    1779
    -* Take care: exprIsExpandable should /not/ be true of primops.  I
    
    1780
    -  found this in test T5623a:
    
    1781
    -    let q = /\a. Ptr a (a +# b)
    
    1782
    -    in case q @ Float of Ptr v -> ...q...
    
    1783
    -
    
    1784
    -  q's inlining should not be expandable, else exprIsConApp_maybe will
    
    1785
    -  say that (q @ Float) expands to (Ptr a (a +# b)), and that will
    
    1786
    -  duplicate the (a +# b) primop, which we should not do lightly.
    
    1787
    -  (It's quite hard to trigger this bug, but T13155 does so for GHC 8.0.)
    
    1788
    -
    
    1789
    -NB: exprIsWorkFree implies exprIsExpandable.
    
    1790
    -
    
    1791
    -Note [isExpandableApp: bottoming functions]
    
    1792
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1793
    -It's important that isExpandableApp does not respond True to bottoming
    
    1794
    -functions.  Recall  undefined :: HasCallStack => a
    
    1795
    -Suppose isExpandableApp responded True to (undefined d), and we had:
    
    1796
    -
    
    1797
    -  x = undefined <dict-expr>
    
    1798
    -
    
    1799
    -Then Simplify.prepareRhs would ANF the RHS:
    
    1800
    -
    
    1801
    -  d = <dict-expr>
    
    1802
    -  x = undefined d
    
    1803
    -
    
    1804
    -This is already bad: we gain nothing from having x bound to (undefined
    
    1805
    -var), unlike the case for data constructors.  Worse, we get the
    
    1806
    -simplifier loop described in OccurAnal Note [Cascading inlines].
    
    1807
    -Suppose x occurs just once; OccurAnal.occAnalNonRecRhs decides x will
    
    1808
    -certainly_inline; so we end up inlining d right back into x; but in
    
    1809
    -the end x doesn't inline because it is bottom (preInlineUnconditionally);
    
    1810
    -so the process repeats.. We could elaborate the certainly_inline logic
    
    1811
    -some more, but it's better just to treat bottoming bindings as
    
    1812
    -non-expandable, because ANFing them is a bad idea in the first place.
    
    1813
    -
    
    1814
    -Note [Record selection]
    
    1815
    -~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1816
    -I'm experimenting with making record selection
    
    1817
    -look cheap, so we will substitute it inside a
    
    1818
    -lambda.  Particularly for dictionary field selection.
    
    1819
    -
    
    1820
    -BUT: Take care with (sel d x)!  The (sel d) might be cheap, but
    
    1821
    -there's no guarantee that (sel d x) will be too.  Hence (n_val_args == 1)
    
    1822
    -
    
    1823
    -Note [Expandable overloadings]
    
    1824
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1825
    -Suppose the user wrote this
    
    1826
    -   {-# RULE  forall x. foo (negate x) = h x #-}
    
    1827
    -   f x = ....(foo (negate x))....
    
    1828
    -They'd expect the rule to fire. But since negate is overloaded, we might
    
    1829
    -get this:
    
    1830
    -    f = \d -> let n = negate d in \x -> ...foo (n x)...
    
    1831
    -So we treat the application of a function (negate in this case) to a
    
    1832
    -*dictionary* as expandable.  In effect, every function is CONLIKE when
    
    1833
    -it's applied only to dictionaries.
    
    1834
    --}
    
    1835 1843
     
    
    1836 1844
     isUnaryClassId :: Id -> Bool
    
    1837 1845
     -- True of (a) the method selector (classop)
    
    ... ... @@ -3265,8 +3273,8 @@ So:
    3265 3273
     * When we make an AbsVars list, we close over the free vars of the unfoldings
    
    3266 3274
       of any tyvars in it.  So if `b{=Maybe a}` is in the list then so is `a`
    
    3267 3275
     
    
    3268
    -* `mkCoreAbsLams` (more generally `mkPolyAbsLams`) forms a lambda abstraction pushing
    
    3269
    -   the tyvar bindings into the body:
    
    3276
    +* `mkCoreAbsLams` (more generally `mkPolyAbsLams`) forms a lambda abstraction
    
    3277
    +   pushing the tyvar bindings into the body:
    
    3270 3278
           mkCoreAbsLams [a, b=[a], x:b] body
    
    3271 3279
              = \a. \(x:[a]). let @b = [a] in
    
    3272 3280
                              let x:b = x in   -- See (AFV1)
    
    ... ... @@ -3301,8 +3309,10 @@ type TaggedAbsVars t = [TaggedBndr t]
    3301 3309
     
    
    3302 3310
     mkPolyAbsLams :: forall b. (b -> AbsVar, Var -> b -> b)
    
    3303 3311
                             -> [b] -> Expr b -> Expr b
    
    3304
    --- `mkPolyAbsLams` is polymorphic in (get,set) so that we can
    
    3305
    --- use it for both CoreExpr and LevelledExpr
    
    3312
    +-- `mkPolyAbsLams` is polymorphic in (get,set) so that we
    
    3313
    +-- can use it for both CoreExpr and LevelledExpr.  See
    
    3314
    +--     - mkCoreAbsLams
    
    3315
    +--     - mkTaggedAbsLams
    
    3306 3316
     {-# INLINE mkPolyAbsLams #-}
    
    3307 3317
     mkPolyAbsLams (getter,setter) bndrs body
    
    3308 3318
       = go emptyVarSet [] bndrs