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

Commits:

3 changed files:

Changes:

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -29,13 +29,11 @@ import GHC.Core.Utils ( exprIsTrivial, exprIsTopLevelBindable
    29 29
                               , mkCast, exprType
    
    30 30
                               , stripTicksTop, mkInScopeSetBndrs )
    
    31 31
     import GHC.Core.FVs
    
    32
    -import GHC.Core.TyCo.FVs ( tyCoVarsOfTypeList )
    
    33 32
     import GHC.Core.Opt.Arity( collectBindersPushingCo )
    
    34
    --- import GHC.Core.Ppr( pprIds )
    
    35 33
     
    
    36 34
     import GHC.Builtin.Types  ( unboxedUnitTy )
    
    37 35
     
    
    38
    -import GHC.Data.Maybe     ( maybeToList, isJust )
    
    36
    +import GHC.Data.Maybe     ( isJust )
    
    39 37
     import GHC.Data.Bag
    
    40 38
     import GHC.Data.OrdList
    
    41 39
     import GHC.Data.List.SetOps
    
    ... ... @@ -46,7 +44,7 @@ import GHC.Types.Unique.DFM
    46 44
     import GHC.Types.Name
    
    47 45
     import GHC.Types.Tickish
    
    48 46
     import GHC.Types.Id.Make  ( voidArgId, voidPrimId )
    
    49
    -import GHC.Types.Var      ( PiTyBinder(..), isLocalVar, isInvisibleFunArg, mkLocalVar )
    
    47
    +import GHC.Types.Var
    
    50 48
     import GHC.Types.Var.Set
    
    51 49
     import GHC.Types.Var.Env
    
    52 50
     import GHC.Types.Id
    
    ... ... @@ -56,6 +54,7 @@ import GHC.Types.Error
    56 54
     import GHC.Utils.Error ( mkMCDiagnostic )
    
    57 55
     import GHC.Utils.Monad    ( foldlM )
    
    58 56
     import GHC.Utils.Misc
    
    57
    +import GHC.Utils.FV
    
    59 58
     import GHC.Utils.Outputable
    
    60 59
     import GHC.Utils.Panic
    
    61 60
     
    
    ... ... @@ -1612,12 +1611,17 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1612 1611
         is_dfun   = isDFunId fn
    
    1613 1612
         dflags    = se_dflags env
    
    1614 1613
         this_mod  = se_module env
    
    1614
    +    subst     = se_subst env
    
    1615
    +    in_scope  = Core.substInScopeSet subst
    
    1615 1616
             -- Figure out whether the function has an INLINE pragma
    
    1616 1617
             -- See Note [Inline specialisations]
    
    1617 1618
     
    
    1618 1619
         (rhs_bndrs, rhs_body) = collectBindersPushingCo rhs
    
    1619 1620
                                 -- See Note [Account for casts in binding]
    
    1620 1621
     
    
    1622
    +    not_in_scope :: InterestingVarFun
    
    1623
    +    not_in_scope v = isLocalVar v && not (v `elemInScopeSet` in_scope)
    
    1624
    +
    
    1621 1625
         ----------------------------------------------------------
    
    1622 1626
             -- Specialise to one particular call pattern
    
    1623 1627
         spec_call :: SpecInfo                         -- Accumulating parameter
    
    ... ... @@ -1628,25 +1632,40 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1628 1632
             do { let all_call_args | is_dfun   = saturating_call_args -- See Note [Specialising DFuns]
    
    1629 1633
                                    | otherwise = call_args
    
    1630 1634
                      saturating_call_args = call_args ++ map mk_extra_dfun_arg (dropList call_args rhs_bndrs)
    
    1631
    -                 mk_extra_dfun_arg bndr | isTyVar bndr = UnspecType (tyVarKind bndr)  -- ToDo: right?
    
    1632
    -                                        | otherwise    = UnspecArg (idType bndr)
    
    1633
    -
    
    1634
    -           ; (useful, rule_bndrs, rule_lhs_args, spec_bndrs1, spec_args) <- specHeader env all_call_args
    
    1635
    -
    
    1636
    ---           ; pprTrace "spec_call" (vcat
    
    1637
    ---                [ text "fun:       "  <+> ppr fn
    
    1638
    ---                , text "call info: "  <+> ppr _ci
    
    1639
    ---                , text "useful:    "  <+> ppr useful
    
    1640
    ---                , text "rule_bndrs:"  <+> ppr rule_bndrs
    
    1641
    ---                , text "lhs_args:  "  <+> ppr rule_lhs_args
    
    1642
    ---                , text "spec_bndrs1:" <+> ppr spec_bndrs1
    
    1643
    ---                , text "spec_args: "  <+> ppr spec_args
    
    1644
    ---                , text "dx_binds:  "  <+> ppr dx_binds
    
    1645
    ---                , text "rhs_bndrs"     <+> ppr rhs_bndrs
    
    1646
    ---                , text "rhs_body"     <+> ppr rhs_body
    
    1647
    ---                , text "rhs_env2:  "  <+> ppr (se_subst rhs_env2)
    
    1648
    ---                , ppr dx_binds ]) $
    
    1649
    ---             return ()
    
    1635
    +                 mk_extra_dfun_arg bndr | isTyVar bndr = UnspecType
    
    1636
    +                                        | otherwise    = UnspecArg
    
    1637
    +
    
    1638
    +             -- Find qvars, the type variables to add to the binders for the rule
    
    1639
    +             -- Namely those free in `ty` that aren't in scope
    
    1640
    +             -- See (MP2) in Note [Specialising polymorphic dictionaries]
    
    1641
    +           ; let poly_qvars = scopedSort $ fvVarList $ specArgsFVs not_in_scope call_args
    
    1642
    +                 poly_qvar_es = map varToCoreExpr poly_qvars  -- Account for CoVars
    
    1643
    +
    
    1644
    +                 subst' = subst `Core.extendSubstInScopeList` poly_qvars
    
    1645
    +                          -- Maybe we should clone the poly_qvars telescope?
    
    1646
    +
    
    1647
    +             -- Any free Ids will have caused the call to be dropped
    
    1648
    +           ; massertPpr (all isTyCoVar poly_qvars)
    
    1649
    +                        (ppr fn $$ ppr all_call_args $$ ppr poly_qvars)
    
    1650
    +
    
    1651
    +           ; (useful, subst'', rule_bndrs, rule_lhs_args, spec_bndrs, spec_args)
    
    1652
    +                 <- specHeader subst' rhs_bndrs all_call_args
    
    1653
    +           ; (rule_bndrs, rule_lhs_args, spec_bndrs, spec_args)
    
    1654
    +                 <- return ( poly_qvars ++ rule_bndrs, poly_qvar_es ++ rule_lhs_args
    
    1655
    +                           , poly_qvars ++ spec_bndrs, poly_qvar_es ++ spec_args )
    
    1656
    +
    
    1657
    +           ; pprTrace "spec_call" (vcat
    
    1658
    +                [ text "fun:       "  <+> ppr fn
    
    1659
    +                , text "call info: "  <+> ppr _ci
    
    1660
    +                , text "poly_qvars: " <+> ppr poly_qvars
    
    1661
    +                , text "useful:    "  <+> ppr useful
    
    1662
    +                , text "rule_bndrs:"  <+> ppr rule_bndrs
    
    1663
    +                , text "rule_lhs_args:"  <+> ppr rule_lhs_args
    
    1664
    +                , text "spec_bndrs:" <+> ppr spec_bndrs
    
    1665
    +                , text "spec_args: "  <+> ppr spec_args
    
    1666
    +                , text "rhs_bndrs"    <+> ppr rhs_bndrs
    
    1667
    +                , text "rhs_body"     <+> ppr rhs_body ]) $
    
    1668
    +             return ()
    
    1650 1669
     
    
    1651 1670
                ; let all_rules = rules_acc ++ existing_rules
    
    1652 1671
                      -- all_rules: we look both in the rules_acc (generated by this invocation
    
    ... ... @@ -1657,27 +1676,28 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1657 1676
                  then return spec_acc
    
    1658 1677
                  else
    
    1659 1678
             do { -- Run the specialiser on the specialised RHS
    
    1660
    -             -- The "1" suffix is before we maybe add the void arg
    
    1661
    -           ; (rhs_body', rhs_uds) <- specRhs env rhs_bndrs rhs_body spec_args
    
    1679
    +             (rhs_body', rhs_uds) <- specExpr (env { se_subst = subst'' }) $
    
    1680
    +                                     mkLams (dropList spec_args rhs_bndrs) rhs_body
    
    1681
    +
    
    1662 1682
                     -- Add the { d1' = dx1; d2' = dx2 } usage stuff
    
    1663 1683
                     -- to the rhs_uds; see Note [Specialising Calls]
    
    1664 1684
                ; let (spec_uds, dumped_dbs) = dumpUDs spec_bndrs1 rhs_uds
    
    1665
    -                 spec_rhs1 = mkLams spec_bndrs1 $
    
    1666
    -                             wrapDictBindsE dumped_dbs rhs_body'
    
    1667
    -                 spec_fn_ty1 = exprType spec_rhs1
    
    1685
    +                 spec_rhs = mkLams spec_bndrs $
    
    1686
    +                            wrapDictBindsE dumped_dbs rhs_body'
    
    1687
    +                 spec_fn_ty = exprType spec_rhs
    
    1668 1688
     
    
    1669 1689
                      -- Maybe add a void arg to the specialised function,
    
    1670 1690
                      -- to avoid unlifted bindings
    
    1671 1691
                      -- See Note [Specialisations Must Be Lifted]
    
    1672 1692
                      -- C.f. GHC.Core.Opt.WorkWrap.Utils.needsVoidWorkerArg
    
    1673
    -                 add_void_arg = isUnliftedType spec_fn_ty1 && not (isJoinId fn)
    
    1674
    -                 (spec_bndrs, spec_rhs, spec_fn_ty)
    
    1675
    -                   | add_void_arg = ( voidPrimId : spec_bndrs1
    
    1676
    -                                    , Lam voidArgId spec_rhs1
    
    1677
    -                                    , mkVisFunTyMany unboxedUnitTy spec_fn_ty1)
    
    1678
    -                   | otherwise   = (spec_bndrs1, spec_rhs1, spec_fn_ty1)
    
    1693
    +                 add_void_arg = isUnliftedType spec_fn_ty && not (isJoinId fn)
    
    1694
    +                 (spec_bndrs1, spec_rhs1, spec_fn_ty1)
    
    1695
    +                   | add_void_arg = ( voidPrimId : spec_bndrs
    
    1696
    +                                    , Lam voidArgId spec_rhs
    
    1697
    +                                    , mkVisFunTyMany unboxedUnitTy spec_fn_ty)
    
    1698
    +                   | otherwise   = (spec_bndrs, spec_rhs, spec_fn_ty)
    
    1679 1699
     
    
    1680
    -                 join_arity_decr = length rule_lhs_args - length spec_bndrs
    
    1700
    +                 join_arity_decr = length rule_lhs_args - length spec_bndrs1
    
    1681 1701
     
    
    1682 1702
                      --------------------------------------
    
    1683 1703
                      -- Add a suitable unfolding; see Note [Inline specialisations]
    
    ... ... @@ -1685,7 +1705,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1685 1705
                      -- arguments, not forgetting to wrap the dx_binds around the outside (#22358)
    
    1686 1706
                      simpl_opts = initSimpleOpts dflags
    
    1687 1707
                      wrap_unf_body body = body `mkApps` spec_args
    
    1688
    -                 spec_unf = specUnfolding simpl_opts spec_bndrs wrap_unf_body
    
    1708
    +                 spec_unf = specUnfolding simpl_opts spec_bndrs1 wrap_unf_body
    
    1689 1709
                                               rule_lhs_args fn_unf
    
    1690 1710
     
    
    1691 1711
                      --------------------------------------
    
    ... ... @@ -1693,7 +1713,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1693 1713
                      --      See Note [Arity decrease] in GHC.Core.Opt.Simplify
    
    1694 1714
                      -- Copy InlinePragma information from the parent Id.
    
    1695 1715
                      -- So if f has INLINE[1] so does spec_fn
    
    1696
    -                 arity_decr     = count isValArg rule_lhs_args - count isId spec_bndrs
    
    1716
    +                 arity_decr     = count isValArg rule_lhs_args - count isId spec_bndrs1
    
    1697 1717
     
    
    1698 1718
                      spec_inl_prag
    
    1699 1719
                        | not is_local     -- See Note [Specialising imported functions]
    
    ... ... @@ -1715,7 +1735,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1715 1735
                            DFunId unary        -> DFunId unary
    
    1716 1736
                            _                   -> VanillaId
    
    1717 1737
     
    
    1718
    -           ; spec_fn <- newSpecIdSM (idName fn) spec_fn_ty spec_fn_details spec_fn_info
    
    1738
    +           ; spec_fn <- newSpecIdSM (idName fn) spec_fn_ty1 spec_fn_details spec_fn_info
    
    1719 1739
                ; let
    
    1720 1740
                     -- The rule to put in the function's specialisation is:
    
    1721 1741
                     --      forall x @b d1' d2'.
    
    ... ... @@ -1728,12 +1748,12 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1728 1748
     
    
    1729 1749
                     spec_rule = mkSpecRule dflags this_mod True inl_act
    
    1730 1750
                                         herald fn rule_bndrs rule_lhs_args
    
    1731
    -                                    (mkVarApps (Var spec_fn) spec_bndrs)
    
    1751
    +                                    (mkVarApps (Var spec_fn) spec_bndrs1)
    
    1732 1752
     
    
    1733 1753
                     spec_f_w_arity = spec_fn
    
    1734 1754
     
    
    1735 1755
                     _rule_trace_doc = vcat [ ppr fn <+> dcolon <+> ppr fn_type
    
    1736
    -                                       , ppr spec_fn  <+> dcolon <+> ppr spec_fn_ty
    
    1756
    +                                       , ppr spec_fn  <+> dcolon <+> ppr spec_fn_ty1
    
    1737 1757
                                            , ppr rhs_bndrs, ppr call_args
    
    1738 1758
                                            , ppr spec_rule
    
    1739 1759
                                            , text "acc" <+> ppr rules_acc
    
    ... ... @@ -1742,7 +1762,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
    1742 1762
     
    
    1743 1763
                ; -- pprTrace "spec_call: rule" _rule_trace_doc
    
    1744 1764
                  return ( spec_rule                  : rules_acc
    
    1745
    -                    , (spec_f_w_arity, spec_rhs) : pairs_acc
    
    1765
    +                    , (spec_f_w_arity, spec_rhs1) : pairs_acc
    
    1746 1766
                         , spec_uds           `thenUDs` uds_acc
    
    1747 1767
                         ) } }
    
    1748 1768
     
    
    ... ... @@ -1763,13 +1783,16 @@ alreadyCovered env bndrs fn args is_active rules
    1763 1783
       where
    
    1764 1784
         in_scope = substInScopeSet (se_subst env)
    
    1765 1785
     
    
    1766
    -specRhs :: SpecEnv -> [Var] -> CoreExpr -> [CoreExpr]
    
    1767
    -        -> SpecM (CoreExpr, UsageDetails)
    
    1786
    +{-
    
    1787
    +specRhs :: SpecEnv -> [InVar] -> InExpr -> [OutExpr]
    
    1788
    +        -> SpecM (OutExpr, UsageDetails)
    
    1768 1789
     
    
    1769
    -specRhs env bndrs body []
    
    1770
    -  = specLam env bndrs body
    
    1790
    +specRhs env bndrs body []  -- Like specExpr (Lam bndrs body)
    
    1791
    +  = specLam env' bndrs' body
    
    1792
    +  where
    
    1793
    +    (env', bndrs') = substBndrs env bndrs
    
    1771 1794
     
    
    1772
    -specRhs env [] body args
    
    1795
    +specRhs _env [] body args
    
    1773 1796
       = -- The caller should have ensured that there are no more
    
    1774 1797
         -- args than we have binders on the RHS
    
    1775 1798
         pprPanic "specRhs:too many args" (ppr args $$ ppr body)
    
    ... ... @@ -1781,15 +1804,22 @@ specRhs env@(SE { se_subst = subst }) (bndr:bndrs) body (arg:args)
    1781 1804
     
    
    1782 1805
     
    
    1783 1806
       | otherwise  -- Non-trivial argument; it must be a dictionary
    
    1784
    -  = do { fresh_dict_id <- newIdBndr "dx" (idType bndr)
    
    1785
    -       ; let fresh_dict_id' = fresh_dict_id `addDictUnfolding` arg
    
    1786
    -             dict_bind = mkDB (NonRec fresh_dict_id' arg)
    
    1787
    -             env2 = env1 { se_subst = Core.extendSubst subst bndr (Var fresh_dict_id')
    
    1788
    -                                      `Core.extendSubstInScope` fresh_dict_id' }
    
    1807
    +  = do { fresh_id <- newIdBndr "dx" (exprType arg)
    
    1808
    +       ; let fresh_id' = fresh_id `addDictUnfolding` arg
    
    1809
    +             dict_bind = mkDB (NonRec fresh_id' arg)
    
    1810
    +             env' = env { se_subst = Core.extendSubst subst bndr (Var fresh_id')
    
    1811
    +                                      `Core.extendSubstInScope` fresh_id' }
    
    1789 1812
                                           -- Ensure the new unfolding is in the in-scope set
    
    1790
    -       ; (body', uds) <- specRhs env2 bndrs body args
    
    1813
    +       ; (body', uds) <- specRhs env' bndrs body args
    
    1791 1814
            ; return (body', dict_bind `consDictBind` uds) }
    
    1792 1815
     
    
    1816
    +consDictBind :: DictBind -> UsageDetails -> UsageDetails
    
    1817
    +consDictBind db uds@MkUD{ud_binds=FDB{fdb_binds = binds, fdb_bndrs = bs}}
    
    1818
    +  = uds { ud_binds = FDB{ fdb_binds = db `consOL` binds
    
    1819
    +                        , fdb_bndrs = bs `extendVarSetList` bindersOfDictBind db } }
    
    1820
    +
    
    1821
    +-}
    
    1822
    +
    
    1793 1823
     -- Convenience function for invoking lookupRule from Specialise
    
    1794 1824
     -- The SpecEnv's InScopeSet should include all the Vars in the [CoreExpr]
    
    1795 1825
     specLookupRule :: SpecEnv -> Id -> [CoreExpr]
    
    ... ... @@ -2105,17 +2135,20 @@ defeated specialisation! Hence the use of collectBindersPushingCo.
    2105 2135
     Note [Evidence foralls]
    
    2106 2136
     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    2107 2137
     Suppose (#12212) that we are specialising
    
    2108
    -   f :: forall a b. (Num a, F a ~ F b) => blah
    
    2138
    +   f :: forall a b. (Num a, F a ~# F b) => blah
    
    2109 2139
     with a=b=Int. Then the RULE will be something like
    
    2110
    -   RULE forall (d:Num Int) (g :: F Int ~ F Int).
    
    2140
    +   RULE forall (d:Num Int) (g :: F Int ~# F Int).
    
    2111 2141
             f Int Int d g = f_spec
    
    2142
    +where that `g` is really (Coercion (CoVar g)), since `g` is a
    
    2143
    +coercion variable and can't appear as (Var g).
    
    2144
    +
    
    2112 2145
     But both varToCoreExpr (when constructing the LHS args), and the
    
    2113 2146
     simplifier (when simplifying the LHS args), will transform to
    
    2114 2147
        RULE forall (d:Num Int) (g :: F Int ~ F Int).
    
    2115 2148
             f Int Int d <F Int> = f_spec
    
    2116 2149
     by replacing g with Refl.  So now 'g' is unbound, which results in a later
    
    2117 2150
     crash. So we use Refl right off the bat, and do not forall-quantify 'g':
    
    2118
    - * varToCoreExpr generates a Refl
    
    2151
    + * varToCoreExpr generates a (Coercion Refl)
    
    2119 2152
      * exprsFreeIdsList returns the Ids bound by the args,
    
    2120 2153
        which won't include g
    
    2121 2154
     
    
    ... ... @@ -2447,7 +2480,7 @@ data SpecArg
    2447 2480
         SpecType Type
    
    2448 2481
     
    
    2449 2482
         -- | Type arguments that should remain polymorphic.
    
    2450
    -  | UnspecType Kind
    
    2483
    +  | UnspecType
    
    2451 2484
     
    
    2452 2485
         -- | Dictionaries that should be specialised. mkCallUDs ensures
    
    2453 2486
         -- that only "interesting" dictionary arguments get a SpecDict;
    
    ... ... @@ -2455,25 +2488,25 @@ data SpecArg
    2455 2488
       | SpecDict DictExpr
    
    2456 2489
     
    
    2457 2490
         -- | Value arguments that should not be specialised.
    
    2458
    -  | UnspecArg Type
    
    2491
    +  | UnspecArg
    
    2459 2492
     
    
    2460 2493
     instance Outputable SpecArg where
    
    2461
    -  ppr (SpecType t)   = text "SpecType" <+> ppr t
    
    2462
    -  ppr (UnspecType k) = text "UnspecType"
    
    2463
    -  ppr (SpecDict d)   = text "SpecDict" <+> ppr d
    
    2464
    -  ppr (UnspecArg t)  = text "UnspecArg"
    
    2465
    -
    
    2466
    -specArgFreeIds :: SpecArg -> IdSet
    
    2467
    -specArgFreeIds (SpecType {})   = emptyVarSet
    
    2468
    -specArgFreeIds (SpecDict dx)   = exprFreeIds dx
    
    2469
    -specArgFreeIds (UnspecType {}) = emptyVarSet
    
    2470
    -specArgFreeIds (UnspecArg {})  = emptyVarSet
    
    2471
    -
    
    2472
    -specArgFreeVars :: SpecArg -> VarSet
    
    2473
    -specArgFreeVars (SpecType ty)   = tyCoVarsOfType ty
    
    2474
    -specArgFreeVars (UnspecType ki) = tyCoVarsOfType ki
    
    2475
    -specArgFreeVars (SpecDict dx)   = exprFreeVars dx
    
    2476
    -specArgFreeVars (UnspecArg ty)  = tyCoVarsOfType ty
    
    2494
    +  ppr (SpecType t)  = text "SpecType" <+> ppr t
    
    2495
    +  ppr (SpecDict d)  = text "SpecDict" <+> ppr d
    
    2496
    +  ppr UnspecType    = text "UnspecType"
    
    2497
    +  ppr UnspecArg     = text "UnspecArg"
    
    2498
    +
    
    2499
    +specArgsFVs :: InterestingVarFun -> [SpecArg] -> FV
    
    2500
    +-- Find the free vars of the SpecArgs that are not already in scope
    
    2501
    +specArgsFVs interesting args
    
    2502
    +  = filterFV interesting $
    
    2503
    +    foldr (unionFV . get) emptyFV args
    
    2504
    +  where
    
    2505
    +    get :: SpecArg -> FV
    
    2506
    +    get (SpecType ty)   = tyCoFVsOfType ty
    
    2507
    +    get (SpecDict dx)   = exprFVs dx
    
    2508
    +    get UnspecType      = emptyFV
    
    2509
    +    get UnspecArg       = emptyFV
    
    2477 2510
     
    
    2478 2511
     isSpecDict :: SpecArg -> Bool
    
    2479 2512
     isSpecDict (SpecDict {}) = True
    
    ... ... @@ -2523,12 +2556,15 @@ isSpecDict _ = False
    2523 2556
     --    , [T1, T2, c, i, dEqT1, dShow1]
    
    2524 2557
     --    )
    
    2525 2558
     specHeader
    
    2526
    -     :: SpecEnv
    
    2559
    +     :: Core.Subst  -- This substitution applies to the [InBndr]
    
    2560
    +     -> [InBndr]    -- Binders from the original function `f`
    
    2527 2561
          -> [SpecArg]   -- From the CallInfo
    
    2528 2562
          -> SpecM ( Bool     -- True <=> some useful specialisation happened
    
    2529 2563
                              -- Not the same as any (isSpecDict args) because
    
    2530 2564
                              -- the args might be longer than bndrs
    
    2531 2565
     
    
    2566
    +              , Core.Subst   -- Apply this to the body
    
    2567
    +
    
    2532 2568
                     -- RULE helpers
    
    2533 2569
                   , [OutBndr]    -- Binders for the RULE
    
    2534 2570
                   , [OutExpr]    -- Args for the LHS of the rule
    
    ... ... @@ -2539,63 +2575,57 @@ specHeader
    2539 2575
                                  -- Same length as "Args for LHS of rule"
    
    2540 2576
                   )
    
    2541 2577
     
    
    2578
    +-- If we run out of binders, stop immediately
    
    2579
    +-- See Note [Specialisation Must Preserve Sharing]
    
    2580
    +specHeader subst [] _  = pure (False, subst, [], [], [], [])
    
    2581
    +specHeader subst _  [] = pure (False, subst, [], [], [], [])
    
    2582
    +
    
    2542 2583
     -- We want to specialise on type 'T1', and so we must construct a substitution
    
    2543 2584
     -- 'a->T1', as well as a LHS argument for the resulting RULE and unfolding
    
    2544 2585
     -- details.
    
    2545
    -specHeader env (SpecType ty : args)
    
    2546
    -  = do { -- Find qvars, the type variables to add to the binders for the rule
    
    2547
    -         -- Namely those free in `ty` that aren't in scope
    
    2548
    -         -- See (MP2) in Note [Specialising polymorphic dictionaries]
    
    2549
    -         let in_scope = Core.substInScopeSet (se_subst env)
    
    2550
    -             qvars    = scopedSort $
    
    2551
    -                        filterOut (`elemInScopeSet` in_scope) $
    
    2552
    -                        tyCoVarsOfTypeList ty
    
    2553
    -       ; (useful, rule_bs, rule_args, spec_bs, spec_args) <- specHeader env args
    
    2554
    -       ; pure ( useful
    
    2555
    -              , qvars ++ rule_bs
    
    2556
    -              , Type ty : rule_args
    
    2557
    -              , qvars ++ spec_bs
    
    2558
    -              , Type ty : spec_args
    
    2559
    -              )
    
    2560
    -       }
    
    2586
    +specHeader subst (bndr:bndrs) (SpecType ty : args)
    
    2587
    +  = do { let subst1 = Core.extendTvSubst subst bndr ty
    
    2588
    +       ; (useful, subst2, rule_bs, rule_args, spec_bs, spec_args)
    
    2589
    +             <- specHeader subst1 bndrs args
    
    2590
    +       ; pure ( useful, subst2
    
    2591
    +              , rule_bs, Type ty : rule_args
    
    2592
    +              , spec_bs, Type ty : spec_args ) }
    
    2561 2593
     
    
    2562 2594
     -- Next we have a type that we don't want to specialise. We need to perform
    
    2563 2595
     -- a substitution on it (in case the type refers to 'a'). Additionally, we need
    
    2564 2596
     -- to produce a binder, LHS argument and RHS argument for the resulting rule,
    
    2565 2597
     -- /and/ a binder for the specialised body.
    
    2566
    -specHeader env (UnspecType kind : args)
    
    2567
    -  = do { (useful, rule_bs, rule_es, spec_bs, spec_args)  <- specHeader env' bndrs args
    
    2568
    -       ; tv <- newTyVarBndr kind
    
    2569
    -       ; pure ( useful
    
    2570
    -              , bndr' : rule_bs
    
    2571
    -              , varToCoreExpr bndr' : rule_es
    
    2572
    -              , bndr' : spec_bs
    
    2573
    -              , varToCoreExpr bndr' : spec_args
    
    2574
    -              )
    
    2575
    -       }
    
    2598
    +specHeader subst (bndr:bndrs) (UnspecType : args)
    
    2599
    +  = do { let (subst1, bndr') = Core.substBndr subst bndr
    
    2600
    +       ; (useful, subst2, rule_bs, rule_es, spec_bs, spec_args)
    
    2601
    +             <- specHeader subst1 bndrs args
    
    2602
    +       ; let ty_e' = Type (mkTyVarTy bndr')
    
    2603
    +       ; pure ( useful, subst2
    
    2604
    +              , bndr' : rule_bs, ty_e' : rule_es
    
    2605
    +              , bndr' : spec_bs, ty_e' : spec_args ) }
    
    2606
    +
    
    2607
    +specHeader subst (bndr:bndrs) (_ : args)
    
    2608
    +  | isDeadBinder bndr
    
    2609
    +  , let (subst1, bndr') = Core.substBndr subst bndr
    
    2610
    +  , Just rubbish_lit <- mkLitRubbish (idType bndr')
    
    2611
    +  = -- See Note [Drop dead args from specialisations]
    
    2612
    +    do { (useful, subst2, rule_bs, rule_es, spec_bs, spec_args) <- specHeader subst1 bndrs args
    
    2613
    +       ; pure ( useful, subst2
    
    2614
    +              , bndr' : rule_bs, Var bndr'   : rule_es
    
    2615
    +              , spec_bs,         rubbish_lit : spec_args ) }
    
    2576 2616
     
    
    2577 2617
     -- Next we want to specialise the 'Eq a' dict away. We need to construct
    
    2578 2618
     -- a wildcard binder to match the dictionary (See Note [Specialising Calls] for
    
    2579 2619
     -- the nitty-gritty), as a LHS rule and unfolding details.
    
    2580
    -specHeader env (SpecDict dict_arg : args)
    
    2581
    -  | not (isDeadBinder bndr)
    
    2582
    -  , allVarSet (`elemInScopeSet` in_scope) (exprFreeVars d)
    
    2583
    -    -- See Note [Weird special case for SpecDict]
    
    2584
    -  = do { (_, rule_bs, rule_es, spec_bs, spec_args) <- specHeader env bndrs args
    
    2585
    -       ; new_dict_id <- newIdBndr "dx" (exprType dict_arg)
    
    2586
    -       ; let new_dict_expr = varToCoreExpr new_dict_id
    
    2587
    -                      -- See Note [Evidence foralls]
    
    2588
    -       ; pure ( True      -- Ha!  A useful specialisation!
    
    2589
    -              , exprFreeIdsList new_dict_expr ++ rule_bs
    
    2590
    -              , new_dict_expr : rule_es
    
    2591
    -              , spec_bs
    
    2592
    -              , dict_arg : spec_args
    
    2593
    -              )
    
    2594
    -       }
    
    2620
    +specHeader subst (bndr:bndrs) (SpecDict dict_arg : args)
    
    2621
    +  = do { let (subst1, bndr') = Core.substBndr subst (zapIdOccInfo bndr)
    
    2622
    +                 -- zapIdOccInfo: see Note [Zap occ info in rule binders]
    
    2623
    +       ; (_, subst2, rule_bs, rule_es, spec_bs, spec_args) <- specHeader subst1 bndrs args
    
    2624
    +       ; pure ( True, subst2      -- Ha!  A useful specialisation!
    
    2625
    +              , bndr' : rule_bs, Var bndr' : rule_es
    
    2626
    +              , spec_bs,         dict_arg : spec_args ) }
    
    2595 2627
     
    
    2596 2628
     -- Finally, we don't want to specialise on this argument 'i':
    
    2597
    ---   - It's an UnSpecArg, or
    
    2598
    ---   - It's a dead dictionary
    
    2599 2629
     -- We need to produce a binder, LHS and RHS argument for the RULE, and
    
    2600 2630
     -- a binder for the specialised body.
    
    2601 2631
     --
    
    ... ... @@ -2603,46 +2633,21 @@ specHeader env (SpecDict dict_arg : args)
    2603 2633
     -- why 'i' doesn't appear in our RULE above. But we have no guarantee that
    
    2604 2634
     -- there aren't 'UnspecArg's which come /before/ all of the dictionaries, so
    
    2605 2635
     -- this case must be here.
    
    2606
    -specHeader env (arg : args)
    
    2607
    -    -- The "_" can be UnSpecArg, or SpecDict where the bndr is dead
    
    2608
    -  = do { -- see Note [Zap occ info in rule binders]
    
    2609
    -       ; (useful, rule_bs, rule_es, spec_bs, spec_args) <- specHeader env bndrs args
    
    2610
    -
    
    2611
    -       ; spec_bndr <- case arg of
    
    2612
    -                        SpecDict d  -> newIdBndr "dx" (exprType d)
    
    2613
    -                        UnspecArg t -> newIdBndr "x"  t
    
    2614
    -       ; let bndr_ty = idType bndr'
    
    2615
    -
    
    2616
    -             -- See Note [Drop dead args from specialisations]
    
    2617
    -             -- C.f. GHC.Core.Opt.WorkWrap.Utils.mk_absent_let
    
    2618
    -             (mb_spec_bndr, spec_arg)
    
    2619
    -                | isDeadBinder bndr
    
    2620
    -                , Just lit_expr <- mkLitRubbish bndr_ty
    
    2621
    -                = (Nothing, lit_expr)
    
    2622
    -                | otherwise
    
    2623
    -                = (Just bndr', varToCoreExpr bndr')
    
    2624
    -
    
    2625
    -       ; pure ( useful
    
    2626
    -              , bndr' : rule_bs
    
    2627
    -              , varToCoreExpr bndr' : rule_es
    
    2628
    -              , case mb_spec_bndr of
    
    2629
    -                  Just b  -> b : spec_bs
    
    2630
    -                  Nothing -> spec_bs
    
    2631
    -              , spec_arg : spec_args
    
    2632
    -              )
    
    2633
    -       }
    
    2636
    +specHeader subst (bndr:bndrs) (UnspecArg : args)
    
    2637
    +  = do { let (subst1, bndr') = Core.substBndr subst (zapIdOccInfo bndr)
    
    2638
    +                 -- zapIdOccInfo: see Note [Zap occ info in rule binders]
    
    2639
    +       ; (useful, subst2, rule_bs, rule_es, spec_bs, spec_args) <- specHeader subst1 bndrs args
    
    2634 2640
     
    
    2635
    --- If we run out of binders, stop immediately
    
    2636
    --- See Note [Specialisation Must Preserve Sharing]
    
    2637
    -specHeader env [] _ = pure (False, env, [], [], [], [], [], [])
    
    2641
    +       ; let dummy_arg = varToCoreExpr bndr'
    
    2642
    +               -- dummy_arg is usually just (Var bndr),
    
    2643
    +               -- but if bndr :: t1 ~# t2, it'll be (Coercion (CoVar bndr))
    
    2644
    +               --     or even Coercion Refl (if t1=t2)
    
    2645
    +               -- See Note [Evidence foralls]
    
    2646
    +             bndrs = exprFreeIdsList dummy_arg
    
    2638 2647
     
    
    2639
    --- Return all remaining binders from the original function. These have the
    
    2640
    --- invariant that they should all correspond to unspecialised arguments, so
    
    2641
    --- it's safe to stop processing at this point.
    
    2642
    -specHeader env bndrs []
    
    2643
    -  = pure (False, env', bndrs', [], [], [], [], [])
    
    2644
    -  where
    
    2645
    -    (env', bndrs') = substBndrs env bndrs
    
    2648
    +       ; pure ( useful, subst2
    
    2649
    +              , bndrs ++ rule_bs, dummy_arg : rule_es
    
    2650
    +              , bndrs ++ spec_bs, dummy_arg : spec_args ) }
    
    2646 2651
     
    
    2647 2652
     
    
    2648 2653
     {-
    
    ... ... @@ -2672,12 +2677,12 @@ bindAuxiliaryDict env@(SE { se_subst = subst })
    2672 2677
                                     -- Ensure the new unfolding is in the in-scope set
    
    2673 2678
         in -- pprTrace "bindAuxiliaryDict:non-trivial" (ppr orig_dict_id <+> ppr fresh_dict_id') $
    
    2674 2679
            (env', Just dict_bind, Var fresh_dict_id')
    
    2675
    --}
    
    2676 2680
     addDictUnfolding :: Id -> CoreExpr -> Id
    
    2677 2681
     -- Add unfolding for freshly-bound Ids: see Note [Make the new dictionaries interesting]
    
    2678 2682
     -- and Note [Specialisation modulo dictionary selectors]
    
    2679 2683
     addDictUnfolding id rhs
    
    2680 2684
       = id `setIdUnfolding` mkSimpleUnfolding defaultUnfoldingOpts rhs
    
    2685
    +-}
    
    2681 2686
     
    
    2682 2687
     {-
    
    2683 2688
     Note [Make the new dictionaries interesting]
    
    ... ... @@ -2985,14 +2990,12 @@ singleCall spec_env id args
    2985 2990
       = MkUD {ud_binds = emptyFDBs,
    
    2986 2991
               ud_calls = unitDVarEnv id $ CIS id $
    
    2987 2992
                          unitBag (CI { ci_key  = args
    
    2988
    -                                 , ci_fvs  = call_fvs }) }
    
    2993
    +                                 , ci_fvs  = fvVarSet call_fvs }) }
    
    2989 2994
       where
    
    2990
    -    call_fvs = foldr (unionVarSet . free_var_fn) emptyVarSet args
    
    2991
    -
    
    2992
    -    free_var_fn =
    
    2993
    -      if gopt Opt_PolymorphicSpecialisation (se_dflags spec_env)
    
    2994
    -        then specArgFreeIds
    
    2995
    -        else specArgFreeVars
    
    2995
    +    call_fvs | gopt Opt_PolymorphicSpecialisation (se_dflags spec_env)
    
    2996
    +             = specArgsFVs isLocalVar args
    
    2997
    +             | otherwise
    
    2998
    +             = specArgsFVs isLocalId args
    
    2996 2999
     
    
    2997 3000
             -- specArgFreeIds: we specifically look for free Ids, not TyVars
    
    2998 3001
             --    see (MP1) in Note [Specialising polymorphic dictionaries]
    
    ... ... @@ -3033,9 +3036,9 @@ mkCallUDs' env f args
    3033 3036
           |  binderVar bndr `elemVarSet` constrained_tyvars
    
    3034 3037
           = SpecType ty
    
    3035 3038
           | otherwise
    
    3036
    -      = UnspecType (typeKind ty)
    
    3039
    +      = UnspecType
    
    3037 3040
         mk_spec_arg non_type_arg (Named bndr)
    
    3038
    -      = = pprPanic "ci_key" $ (ppr non_type_arg $$ ppr bndr)
    
    3041
    +      = pprPanic "ci_key" $ (ppr non_type_arg $$ ppr bndr)
    
    3039 3042
     
    
    3040 3043
         -- For "invisibleFunArg", which are the type-class dictionaries,
    
    3041 3044
         -- we decide on a case by case basis if we want to specialise
    
    ... ... @@ -3046,7 +3049,7 @@ mkCallUDs' env f args
    3046 3049
                   -- See Note [Interesting dictionary arguments]
    
    3047 3050
           = SpecDict arg
    
    3048 3051
     
    
    3049
    -      | otherwise = UnspecArg (exprType arg)
    
    3052
    +      | otherwise = UnspecArg
    
    3050 3053
     
    
    3051 3054
     {-
    
    3052 3055
     Note [Ticks on applications]
    
    ... ... @@ -3285,11 +3288,6 @@ snocDictBinds uds@MkUD{ud_binds=FDB{ fdb_binds = binds, fdb_bndrs = bs }} dbs
    3285 3288
       = uds { ud_binds = FDB { fdb_binds = binds `appOL`        (toOL dbs)
    
    3286 3289
                              , fdb_bndrs = bs    `extendVarSetList` bindersOfDictBinds dbs } }
    
    3287 3290
     
    
    3288
    -consDictBind :: DictBind -> UsageDetails -> UsageDetails
    
    3289
    -consDictBind db uds@MkUD{ud_binds=FDB{fdb_binds = binds, fdb_bndrs = bs}}
    
    3290
    -  = uds { ud_binds = FDB{ fdb_binds = db `consOL` binds
    
    3291
    -                        , fdb_bndrs = bs `extendVarSetList` bindersOfDictBind db } }
    
    3292
    -
    
    3293 3291
     wrapDictBinds :: FloatedDictBinds -> [CoreBind] -> [CoreBind]
    
    3294 3292
     wrapDictBinds (FDB { fdb_binds = dbs }) binds
    
    3295 3293
       = foldr add binds dbs
    
    ... ... @@ -3402,10 +3400,10 @@ beats_or_same (CI { ci_key = args1 }) (CI { ci_key = args2 })
    3402 3400
         go  _ _ = False
    
    3403 3401
     
    
    3404 3402
         go_arg (SpecType ty1) (SpecType ty2) = isJust (tcMatchTy ty1 ty2)
    
    3405
    -    go_arg (UnspecType {}) (UnspecType {}) = True
    
    3406
    -    go_arg (SpecDict {})   (SpecDict {})   = True
    
    3407
    -    go_arg (UnspecArg {})  (UnspecArg {})  = True
    
    3408
    -    go_arg _               _               = False
    
    3403
    +    go_arg (SpecDict {})  (SpecDict {})  = True
    
    3404
    +    go_arg UnspecType     UnspecType     = True
    
    3405
    +    go_arg UnspecArg      UnspecArg      = True
    
    3406
    +    go_arg _               _             = False
    
    3409 3407
     
    
    3410 3408
     ----------------------
    
    3411 3409
     splitDictBinds :: FloatedDictBinds -> IdSet -> (FloatedDictBinds, OrdList DictBind, IdSet)
    
    ... ... @@ -3471,9 +3469,9 @@ mapAndCombineSM f (x:xs) = do (y, uds1) <- f x
    3471 3469
                                   (ys, uds2) <- mapAndCombineSM f xs
    
    3472 3470
                                   return (y:ys, uds1 `thenUDs` uds2)
    
    3473 3471
     
    
    3474
    -extendTvSubst :: SpecEnv -> TyVar -> Type -> SpecEnv
    
    3475
    -extendTvSubst env tv ty
    
    3476
    -  = env { se_subst = Core.extendTvSubst (se_subst env) tv ty }
    
    3472
    +-- extendTvSubst :: SpecEnv -> TyVar -> Type -> SpecEnv
    
    3473
    +-- extendTvSubst env tv ty
    
    3474
    +--   = env { se_subst = Core.extendTvSubst (se_subst env) tv ty }
    
    3477 3475
     
    
    3478 3476
     extendInScope :: SpecEnv -> OutId -> SpecEnv
    
    3479 3477
     extendInScope env@(SE { se_subst = subst }) bndr
    
    ... ... @@ -3521,18 +3519,6 @@ newSpecIdSM old_name new_ty details info
    3521 3519
             ; return (assert (not (isCoVarType new_ty)) $
    
    3522 3520
                       mkLocalVar details new_name ManyTy new_ty info) }
    
    3523 3521
     
    
    3524
    -newIdBndr :: String -> Type -> SpecM (SpecEnv, CoreBndr)
    
    3525
    --- Make up completely fresh binders for the dictionaries
    
    3526
    --- Their bindings are going to float outwards
    
    3527
    -newIdBndr env@(SE { se_subst = subst }) str ty
    
    3528
    -  = do { uniq <- getUniqueM
    
    3529
    -       ; return (mkUserLocal (mkVarOcc str) uniq ManyTy ty noSrcSpan) }
    
    3530
    -
    
    3531
    -newTyVarBndr :: Kind -> SpecM TyVar
    
    3532
    -newTyVarBndr kind
    
    3533
    -  = do { uniq <- getUniqueM
    
    3534
    -       ; let name = mkInternalName uniq (mkTyVarOcc "a") noSrcSpan
    
    3535
    -       ; return (mkTyVar name kind }
    
    3536 3522
     
    
    3537 3523
     {-
    
    3538 3524
                     Old (but interesting) stuff about unboxed bindings
    

  • compiler/GHC/Core/Subst.hs
    ... ... @@ -163,12 +163,14 @@ extendIdSubstList (Subst in_scope ids tvs cvs) prs
    163 163
     -- | Add a substitution appropriate to the thing being substituted
    
    164 164
     --   (whether an expression, type, or coercion). See also
    
    165 165
     --   'extendIdSubst', 'extendTvSubst', 'extendCvSubst'
    
    166
    -extendSubst :: Subst -> Var -> CoreArg -> Subst
    
    166
    +extendSubst :: HasDebugCallStack => Subst -> Var -> CoreArg -> Subst
    
    167 167
     extendSubst subst var arg
    
    168 168
       = case arg of
    
    169
    -      Type ty     -> assert (isTyVar var) $ extendTvSubst subst var ty
    
    170
    -      Coercion co -> assert (isCoVar var) $ extendCvSubst subst var co
    
    171
    -      _           -> assert (isId    var) $ extendIdSubst subst var arg
    
    169
    +      Type ty     -> assertPpr (isTyVar var) doc $ extendTvSubst subst var ty
    
    170
    +      Coercion co -> assertPpr (isCoVar var) doc $ extendCvSubst subst var co
    
    171
    +      _           -> assertPpr (isId    var) doc $ extendIdSubst subst var arg
    
    172
    +  where
    
    173
    +   doc = ppr var <+> text ":=" <+> ppr arg
    
    172 174
     
    
    173 175
     extendSubstWithVar :: Subst -> Var -> Var -> Subst
    
    174 176
     extendSubstWithVar subst v1 v2
    

  • compiler/GHC/HsToCore/Binds.hs
    ... ... @@ -1056,25 +1056,6 @@ dsSpec poly_rhs (SpecPrag poly_id spec_co spec_inl)
    1056 1056
         dsSpec_help (idName poly_id) poly_id poly_rhs
    
    1057 1057
                     spec_inl spec_bndrs (core_app (Var poly_id))
    
    1058 1058
     
    
    1059
    -{-
    
    1060
    -    do { dflags <- getDynFlags
    
    1061
    -       ; case decomposeRuleLhs dflags spec_bndrs (core_app (Var poly_id))
    
    1062
    -                                                 (mkVarSet spec_bndrs) of {
    
    1063
    -           Left msg -> do { diagnosticDs msg; return Nothing } ;
    
    1064
    -           Right (rule_bndrs, poly_id, rule_lhs_args) ->
    
    1065
    -
    
    1066
    -    do { tracePm "dsSpec(old route)" $
    
    1067
    -         vcat [ text "poly_id" <+> ppr poly_id
    
    1068
    -              , text "spec_bndrs" <+> ppr spec_bndrs
    
    1069
    -              , text "the_call" <+> ppr (core_app (Var poly_id))
    
    1070
    -              , text "rule_bndrs" <+> ppr rule_bndrs
    
    1071
    -              , text "rule_lhs_args" <+> ppr rule_lhs_args ]
    
    1072
    -
    
    1073
    -       ; finishSpecPrag (idName poly_id) poly_rhs
    
    1074
    -                               rule_bndrs poly_id rule_lhs_args
    
    1075
    -                               spec_bndrs core_app spec_inl } } }
    
    1076
    --}
    
    1077
    -
    
    1078 1059
     dsSpec poly_rhs (SpecPragE { spe_fn_nm = poly_nm
    
    1079 1060
                                , spe_fn_id = poly_id
    
    1080 1061
                                , spe_inl   = inl