... |
... |
@@ -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
|