| ... |
... |
@@ -33,6 +33,7 @@ import GHC.Core.Utils ( exprIsTrivial, exprIsTopLevelBindable |
|
33
|
33
|
, mkCast, exprType, exprIsHNF
|
|
34
|
34
|
, stripTicksTop, mkInScopeSetBndrs )
|
|
35
|
35
|
import GHC.Core.FVs
|
|
|
36
|
+import GHC.Core.TyCo.FVs( someTyCoVarsOfTypeList )
|
|
36
|
37
|
import GHC.Core.Opt.Arity( collectBindersPushingCo )
|
|
37
|
38
|
import GHC.Core.Opt.Monad
|
|
38
|
39
|
import GHC.Core.Opt.Simplify.Env ( SimplPhase(..), isActive )
|
| ... |
... |
@@ -658,17 +659,17 @@ specProgram guts@(ModGuts { mg_module = this_mod |
|
658
|
659
|
, se_rules = rule_env
|
|
659
|
660
|
, se_dflags = dflags }
|
|
660
|
661
|
|
|
661
|
|
- go [] = return ([], emptyUDs)
|
|
|
662
|
+ go [] = return (nilOL, emptyUDs)
|
|
662
|
663
|
go (bind:binds) = do (bind', binds', uds') <- specBind TopLevel top_env bind $ \_ ->
|
|
663
|
664
|
go binds
|
|
664
|
|
- return (bind' ++ binds', uds')
|
|
|
665
|
+ return (bind' `appOL` binds', uds')
|
|
665
|
666
|
|
|
666
|
667
|
-- Specialise the bindings of this module
|
|
667
|
668
|
; (binds', uds) <- runSpecM (go binds)
|
|
668
|
669
|
|
|
669
|
670
|
; (spec_rules, spec_binds) <- specImports top_env uds
|
|
670
|
671
|
|
|
671
|
|
- ; return (guts { mg_binds = spec_binds ++ binds'
|
|
|
672
|
+ ; return (guts { mg_binds = spec_binds ++ fromOL binds'
|
|
672
|
673
|
, mg_rules = spec_rules ++ local_rules }) }
|
|
673
|
674
|
|
|
674
|
675
|
{-
|
| ... |
... |
@@ -677,7 +678,7 @@ Note [Wrap bindings returned by specImports] |
|
677
|
678
|
'specImports' returns a set of specialized bindings. However, these are lacking
|
|
678
|
679
|
necessary floated dictionary bindings, which are returned by
|
|
679
|
680
|
UsageDetails(ud_binds). These dictionaries need to be brought into scope with
|
|
680
|
|
-'wrapDictBinds' before the bindings returned by 'specImports' can be used. See,
|
|
|
681
|
+'wrapFloatBinds' before the bindings returned by 'specImports' can be used. See,
|
|
681
|
682
|
for instance, the 'specImports' call in 'specProgram'.
|
|
682
|
683
|
|
|
683
|
684
|
|
| ... |
... |
@@ -763,7 +764,7 @@ specImports :: SpecEnv |
|
763
|
764
|
specImports top_env (MkUD { ud_binds = dict_binds, ud_calls = calls })
|
|
764
|
765
|
| not $ gopt Opt_CrossModuleSpecialise (se_dflags top_env)
|
|
765
|
766
|
-- See Note [Disabling cross-module specialisation]
|
|
766
|
|
- = return ([], wrapDictBinds dict_binds [])
|
|
|
767
|
+ = return ([], wrapFloatBinds dict_binds [])
|
|
767
|
768
|
|
|
768
|
769
|
| otherwise
|
|
769
|
770
|
= do { let env_w_dict_bndrs = top_env `bringFloatedDictsIntoScope` dict_binds
|
| ... |
... |
@@ -771,7 +772,7 @@ specImports top_env (MkUD { ud_binds = dict_binds, ud_calls = calls }) |
|
771
|
772
|
|
|
772
|
773
|
-- Make a Rec: see Note [Glom the bindings if imported functions are specialised]
|
|
773
|
774
|
--
|
|
774
|
|
- -- wrapDictBinds: don't forget to wrap the specialized bindings with
|
|
|
775
|
+ -- wrapFloatBinds: don't forget to wrap the specialized bindings with
|
|
775
|
776
|
-- bindings for the needed dictionaries.
|
|
776
|
777
|
-- See Note [Wrap bindings returned by specImports]
|
|
777
|
778
|
--
|
| ... |
... |
@@ -780,9 +781,9 @@ specImports top_env (MkUD { ud_binds = dict_binds, ud_calls = calls }) |
|
780
|
781
|
; let (rules_for_locals, rules_for_imps) = partition isLocalRule spec_rules
|
|
781
|
782
|
local_rule_base = extendRuleBaseList emptyRuleBase rules_for_locals
|
|
782
|
783
|
final_binds
|
|
783
|
|
- | null spec_binds = wrapDictBinds dict_binds []
|
|
|
784
|
+ | null spec_binds = wrapFloatBinds dict_binds []
|
|
784
|
785
|
| otherwise = glomValBinds $
|
|
785
|
|
- wrapDictBinds dict_binds $
|
|
|
786
|
+ wrapFloatBinds dict_binds $
|
|
786
|
787
|
map (mapBindBndrs (addRulesToId local_rule_base)) $
|
|
787
|
788
|
spec_binds
|
|
788
|
789
|
|
| ... |
... |
@@ -791,10 +792,10 @@ specImports top_env (MkUD { ud_binds = dict_binds, ud_calls = calls }) |
|
791
|
792
|
|
|
792
|
793
|
-- | Specialise a set of calls to imported bindings
|
|
793
|
794
|
spec_imports :: SpecEnv -- Passed in so that all top-level Ids are in scope
|
|
794
|
|
- ---In-scope set includes the FloatedDictBinds
|
|
|
795
|
+ ---In-scope set includes the FloatBinds
|
|
795
|
796
|
-> [Id] -- Stack of imported functions being specialised
|
|
796
|
797
|
-- See Note [specImport call stack]
|
|
797
|
|
- -> FloatedDictBinds -- Dict bindings, used /only/ for filterCalls
|
|
|
798
|
+ -> FloatBinds -- Dict bindings, used /only/ for filterCalls
|
|
798
|
799
|
-- See Note [Avoiding loops in specImports]
|
|
799
|
800
|
-> CallDetails -- Calls for imported things
|
|
800
|
801
|
-> CoreM ( SpecEnv -- Env contains the new rules
|
| ... |
... |
@@ -824,10 +825,10 @@ spec_imports env callers dict_binds calls |
|
824
|
825
|
; return (env, rules1 ++ rules2, spec_binds1 ++ spec_binds2) }
|
|
825
|
826
|
|
|
826
|
827
|
spec_import :: SpecEnv -- Passed in so that all top-level Ids are in scope
|
|
827
|
|
- ---In-scope set includes the FloatedDictBinds
|
|
|
828
|
+ ---In-scope set includes the FloatBinds
|
|
828
|
829
|
-> [Id] -- Stack of imported functions being specialised
|
|
829
|
830
|
-- See Note [specImport call stack]
|
|
830
|
|
- -> FloatedDictBinds -- Dict bindings, used /only/ for filterCalls
|
|
|
831
|
+ -> FloatBinds -- Dict bindings, used /only/ for filterCalls
|
|
831
|
832
|
-- See Note [Avoiding loops in specImports]
|
|
832
|
833
|
-> CallInfoSet -- Imported function and calls for it
|
|
833
|
834
|
-> CoreM ( SpecEnv
|
| ... |
... |
@@ -889,7 +890,7 @@ spec_import env callers dict_binds cis@(CIS fn _) |
|
889
|
890
|
(dict_binds `thenFDBs` dict_binds1)
|
|
890
|
891
|
new_calls
|
|
891
|
892
|
|
|
892
|
|
- ; let final_binds = wrapDictBinds dict_binds1 $
|
|
|
893
|
+ ; let final_binds = wrapFloatBinds dict_binds1 $
|
|
893
|
894
|
spec_binds2 ++ spec_binds1
|
|
894
|
895
|
|
|
895
|
896
|
; return (env, rules2 ++ rules1, final_binds) }
|
| ... |
... |
@@ -1161,6 +1162,20 @@ And if the call is to the same type, one specialisation is enough. |
|
1161
|
1162
|
Avoiding this recursive specialisation loop is one reason for the
|
|
1162
|
1163
|
'callers' stack passed to specImports and specImport.
|
|
1163
|
1164
|
|
|
|
1165
|
+Note [Specialisation and type-variable bindings]
|
|
|
1166
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
1167
|
+GHC allows let-bindings for type variables e.g.
|
|
|
1168
|
+ a::Type = Type (Maybe b)
|
|
|
1169
|
+We need to account for these when specialising:
|
|
|
1170
|
+
|
|
|
1171
|
+(STV1) The ci_fvs field of a CallInfo includes free TyVars
|
|
|
1172
|
+
|
|
|
1173
|
+(STV2) When dumping calls, in `deleteCallsMentioning`, we ignore
|
|
|
1174
|
+ free tyvars when Opt_PolymorphicSpecialisation is on.
|
|
|
1175
|
+ See (MP1) in Note [Specialising polymorphic dictionaries]
|
|
|
1176
|
+
|
|
|
1177
|
+(STV3) A FloatBind can be a type binding; see `bindAuxiliaryTyVars`
|
|
|
1178
|
+
|
|
1164
|
1179
|
|
|
1165
|
1180
|
************************************************************************
|
|
1166
|
1181
|
* *
|
| ... |
... |
@@ -1287,8 +1302,8 @@ specLam env bndrs body |
|
1287
|
1302
|
= specExpr env body
|
|
1288
|
1303
|
| otherwise
|
|
1289
|
1304
|
= do { (body', uds) <- specExpr env body
|
|
1290
|
|
- ; let (free_uds, dumped_dbs) = dumpUDs bndrs uds
|
|
1291
|
|
- ; return (mkLams bndrs (wrapDictBindsE dumped_dbs body'), free_uds) }
|
|
|
1305
|
+ ; let (free_uds, dumped_dbs) = dumpUDs env bndrs uds
|
|
|
1306
|
+ ; return (mkLams bndrs (wrapFloatBindsE dumped_dbs body'), free_uds) }
|
|
1292
|
1307
|
|
|
1293
|
1308
|
--------------
|
|
1294
|
1309
|
specTickish :: SpecEnv -> CoreTickish -> CoreTickish
|
| ... |
... |
@@ -1313,8 +1328,8 @@ specCase env scrut case_bndr alts |
|
1313
|
1328
|
(env_alt, case_bndr') = substBndr env case_bndr
|
|
1314
|
1329
|
spec_alt (Alt con args rhs)
|
|
1315
|
1330
|
= do { (rhs', uds) <- specExpr env_rhs rhs
|
|
1316
|
|
- ; let (free_uds, dumped_dbs) = dumpUDs (case_bndr' : args') uds
|
|
1317
|
|
- ; return (Alt con args' (wrapDictBindsE dumped_dbs rhs'), free_uds) }
|
|
|
1331
|
+ ; let (free_uds, dumped_dbs) = dumpUDs env (case_bndr' : args') uds
|
|
|
1332
|
+ ; return (Alt con args' (wrapFloatBindsE dumped_dbs rhs'), free_uds) }
|
|
1318
|
1333
|
where
|
|
1319
|
1334
|
(env_rhs, args') = substBndrs env_alt args
|
|
1320
|
1335
|
|
| ... |
... |
@@ -1420,8 +1435,8 @@ End of Historical Note |
|
1420
|
1435
|
************************************************************************
|
|
1421
|
1436
|
-}
|
|
1422
|
1437
|
|
|
1423
|
|
-bringFloatedDictsIntoScope :: SpecEnv -> FloatedDictBinds -> SpecEnv
|
|
1424
|
|
-bringFloatedDictsIntoScope env (FDB { fdb_bndrs = dx_bndrs })
|
|
|
1438
|
+bringFloatedDictsIntoScope :: SpecEnv -> FloatBinds -> SpecEnv
|
|
|
1439
|
+bringFloatedDictsIntoScope env (FDB { fbs_bndrs = dx_bndrs })
|
|
1425
|
1440
|
= -- pprTrace "brought into scope" (ppr dx_bndrs) $
|
|
1426
|
1441
|
env {se_subst=subst'}
|
|
1427
|
1442
|
where
|
| ... |
... |
@@ -1432,7 +1447,7 @@ specBind :: TopLevelFlag |
|
1432
|
1447
|
-- top level binders in scope
|
|
1433
|
1448
|
-> InBind
|
|
1434
|
1449
|
-> (SpecEnv -> SpecM (body, UsageDetails)) -- Process the body
|
|
1435
|
|
- -> SpecM ( [OutBind] -- New bindings
|
|
|
1450
|
+ -> SpecM ( OrdList OutBind -- New bindings
|
|
1436
|
1451
|
, body -- Body
|
|
1437
|
1452
|
, UsageDetails) -- And info to pass upstream
|
|
1438
|
1453
|
-- Returned UsageDetails:
|
| ... |
... |
@@ -1448,13 +1463,13 @@ specBind top_lvl env (NonRec tv (Type rhs_ty)) do_body |
|
1448
|
1463
|
|
|
1449
|
1464
|
; let rhs_ty' = substTy env rhs_ty
|
|
1450
|
1465
|
bind' = NonRec tv' (Type rhs_ty')
|
|
1451
|
|
- (free_uds, dump_dbs, float_all) = dumpBindUDs True [tv'] body_uds
|
|
1452
|
|
- final_binds = mkDB bind' : fromOL dump_dbs
|
|
|
1466
|
+ (free_uds, dump_dbs, float_all) = dumpBindUDs env True [tv'] body_uds
|
|
|
1467
|
+ final_binds = unitOL (mkDB bind') `appOL` dump_dbs
|
|
1453
|
1468
|
|
|
1454
|
1469
|
; if float_all then
|
|
1455
|
|
- return ([], body', free_uds `snocDictBinds` final_binds)
|
|
|
1470
|
+ return (nilOL, body', free_uds `snocFloatBinds` final_binds)
|
|
1456
|
1471
|
else
|
|
1457
|
|
- return (map db_bind final_binds, body', free_uds) }
|
|
|
1472
|
+ return (fmap fb_bind final_binds, body', free_uds) }
|
|
1458
|
1473
|
|
|
1459
|
1474
|
specBind top_lvl env (NonRec fn rhs) do_body
|
|
1460
|
1475
|
= do { (rhs', rhs_uds) <- specExpr env rhs
|
| ... |
... |
@@ -1486,31 +1501,30 @@ specBind top_lvl env (NonRec fn rhs) do_body |
|
1486
|
1501
|
|
|
1487
|
1502
|
; let can_float_this_one = exprIsTopLevelBindable rhs (idType fn)
|
|
1488
|
1503
|
-- exprIsTopLevelBindable: see Note [Care with unlifted bindings]
|
|
1489
|
|
- (free_uds, dump_dbs, float_all) = dumpBindUDs can_float_this_one [fn4] body_uds1
|
|
|
1504
|
+ (free_uds, dump_dbs, float_all) = dumpBindUDs env can_float_this_one [fn4] body_uds1
|
|
1490
|
1505
|
all_free_uds = free_uds `thenUDs` rhs_uds
|
|
1491
|
1506
|
|
|
1492
|
1507
|
pairs = spec_defns ++ [(fn4, rhs')]
|
|
1493
|
1508
|
-- fn4 mentions the spec_defns in its rules,
|
|
1494
|
1509
|
-- so put the latter first
|
|
1495
|
1510
|
|
|
1496
|
|
- final_binds :: [DictBind]
|
|
|
1511
|
+ final_binds :: OrdList FloatBind
|
|
1497
|
1512
|
-- See Note [From non-recursive to recursive]
|
|
1498
|
1513
|
final_binds | not (isNilOL dump_dbs)
|
|
1499
|
1514
|
, not (null spec_defns)
|
|
1500
|
|
- = [recWithDumpedDicts pairs dump_dbs]
|
|
|
1515
|
+ = unitOL (recWithDumpedDicts pairs dump_dbs)
|
|
1501
|
1516
|
| otherwise
|
|
1502
|
|
- = [mkDB $ NonRec b r | (b,r) <- pairs]
|
|
1503
|
|
- ++ fromOL dump_dbs
|
|
1504
|
|
-
|
|
|
1517
|
+ = toOL [mkDB $ NonRec b r | (b,r) <- pairs]
|
|
|
1518
|
+ `appOL` dump_dbs
|
|
1505
|
1519
|
|
|
1506
|
1520
|
; if float_all then
|
|
1507
|
1521
|
-- Rather than discard the calls mentioning the bound variables
|
|
1508
|
1522
|
-- we float this (dictionary) binding along with the others
|
|
1509
|
|
- return ([], body', all_free_uds `snocDictBinds` final_binds)
|
|
|
1523
|
+ return (nilOL, body', all_free_uds `snocFloatBinds` final_binds)
|
|
1510
|
1524
|
else
|
|
1511
|
1525
|
-- No call in final_uds mentions bound variables,
|
|
1512
|
1526
|
-- so we can just leave the binding here
|
|
1513
|
|
- return (map db_bind final_binds, body', all_free_uds) }
|
|
|
1527
|
+ return (fmap fb_bind final_binds, body', all_free_uds) }
|
|
1514
|
1528
|
|
|
1515
|
1529
|
|
|
1516
|
1530
|
specBind top_lvl env (Rec pairs) do_body
|
| ... |
... |
@@ -1538,14 +1552,14 @@ specBind top_lvl env (Rec pairs) do_body |
|
1538
|
1552
|
<- specDefns rec_env uds2 (bndrs2 `zip` rhss)
|
|
1539
|
1553
|
; return (bndrs3, spec_defns3 ++ spec_defns2, uds3) }
|
|
1540
|
1554
|
|
|
1541
|
|
- ; let (final_uds, dumped_dbs, float_all) = dumpBindUDs True bndrs1 uds3
|
|
|
1555
|
+ ; let (final_uds, dumped_dbs, float_all) = dumpBindUDs env True bndrs1 uds3
|
|
1542
|
1556
|
final_bind = recWithDumpedDicts (spec_defns3 ++ zip bndrs3 rhss')
|
|
1543
|
1557
|
dumped_dbs
|
|
1544
|
1558
|
|
|
1545
|
1559
|
; if float_all then
|
|
1546
|
|
- return ([], body', final_uds `snocDictBind` final_bind)
|
|
|
1560
|
+ return (nilOL, body', final_uds `snocFloatBind` final_bind)
|
|
1547
|
1561
|
else
|
|
1548
|
|
- return ([db_bind final_bind], body', final_uds) }
|
|
|
1562
|
+ return (unitOL (fb_bind final_bind), body', final_uds) }
|
|
1549
|
1563
|
|
|
1550
|
1564
|
|
|
1551
|
1565
|
---------------------------
|
| ... |
... |
@@ -1700,21 +1714,21 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
|
1700
|
1714
|
already_covered = alreadyCovered env' rule_bndrs fn
|
|
1701
|
1715
|
rule_lhs_args is_active all_rules
|
|
1702
|
1716
|
|
|
1703
|
|
--- ; pprTrace "spec_call" (vcat
|
|
1704
|
|
--- [ text "fun: " <+> ppr fn
|
|
1705
|
|
--- , text "call info: " <+> ppr _ci
|
|
1706
|
|
--- , text "useful: " <+> ppr useful
|
|
1707
|
|
--- , text "already_covered:" <+> ppr already_covered
|
|
1708
|
|
--- , text "useful: " <+> ppr useful
|
|
1709
|
|
--- , text "rule_bndrs:" <+> ppr (sep (map (pprBndr LambdaBind) rule_bndrs))
|
|
1710
|
|
--- , text "rule_lhs_args:" <+> ppr rule_lhs_args
|
|
1711
|
|
--- , text "spec_bndrs:" <+> ppr (sep (map (pprBndr LambdaBind) spec_bndrs))
|
|
1712
|
|
--- , text "dx_binds:" <+> ppr dx_binds
|
|
1713
|
|
--- , text "spec_args: " <+> ppr spec_args
|
|
1714
|
|
--- , text "rhs_bndrs" <+> ppr (sep (map (pprBndr LambdaBind) rhs_bndrs))
|
|
1715
|
|
--- , text "rhs_body" <+> ppr rhs_body
|
|
1716
|
|
--- , text "subst'" <+> ppr subst'
|
|
1717
|
|
--- ]) $ return ()
|
|
|
1717
|
+-- ; pprTrace "spec_call" (vcat
|
|
|
1718
|
+-- [ text "fun: " <+> ppr fn
|
|
|
1719
|
+-- , text "call info: " <+> ppr _ci
|
|
|
1720
|
+-- , text "useful: " <+> ppr useful
|
|
|
1721
|
+-- , text "already_covered:" <+> ppr already_covered
|
|
|
1722
|
+-- , text "useful: " <+> ppr useful
|
|
|
1723
|
+-- , text "rule_bndrs:" <+> ppr (sep (map (pprBndr LambdaBind) rule_bndrs))
|
|
|
1724
|
+-- , text "rule_lhs_args:" <+> ppr rule_lhs_args
|
|
|
1725
|
+-- , text "spec_bndrs:" <+> ppr (sep (map (pprBndr LambdaBind) spec_bndrs))
|
|
|
1726
|
+-- , text "dx_binds:" <+> ppr dx_binds
|
|
|
1727
|
+-- , text "spec_args: " <+> ppr spec_args
|
|
|
1728
|
+-- , text "rhs_bndrs" <+> ppr (sep (map (pprBndr LambdaBind) rhs_bndrs))
|
|
|
1729
|
+-- , text "rhs_body" <+> ppr rhs_body
|
|
|
1730
|
+-- , text "subst'" <+> ppr subst'
|
|
|
1731
|
+-- ]) $ return ()
|
|
1718
|
1732
|
|
|
1719
|
1733
|
|
|
1720
|
1734
|
; if not useful -- No useful specialisation
|
| ... |
... |
@@ -1731,12 +1745,12 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
|
1731
|
1745
|
|
|
1732
|
1746
|
-- Make the RHS of the specialised function
|
|
1733
|
1747
|
; let spec_rhs_bndrs = spec_bndrs ++ inner_rhs_bndrs'
|
|
1734
|
|
- (rhs_uds2, inner_dumped_dbs) = dumpUDs spec_rhs_bndrs $
|
|
1735
|
|
- dx_binds `consDictBinds` rhs_uds
|
|
|
1748
|
+ (rhs_uds2, inner_dumped_dbs) = dumpUDs env spec_rhs_bndrs $
|
|
|
1749
|
+ dx_binds `consFloatBinds` rhs_uds
|
|
1736
|
1750
|
-- dx_binds comes from the arguments to the call,
|
|
1737
|
1751
|
-- and so can mention poly_qvars but no other local binders
|
|
1738
|
1752
|
spec_rhs = mkLams spec_rhs_bndrs $
|
|
1739
|
|
- wrapDictBindsE inner_dumped_dbs rhs_body'
|
|
|
1753
|
+ wrapFloatBindsE inner_dumped_dbs rhs_body'
|
|
1740
|
1754
|
rule_rhs_args = spec_bndrs
|
|
1741
|
1755
|
|
|
1742
|
1756
|
-- Maybe add a void arg to the specialised function,
|
| ... |
... |
@@ -1757,7 +1771,8 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
|
1757
|
1771
|
-- The wrap_unf_body applies the original unfolding to the specialised
|
|
1758
|
1772
|
-- arguments, not forgetting to wrap the dx_binds around the outside (#22358)
|
|
1759
|
1773
|
simpl_opts = initSimpleOpts dflags
|
|
1760
|
|
- wrap_unf_body body = foldr (Let . db_bind) (body `mkApps` spec_args) dx_binds
|
|
|
1774
|
+ wrap_unf_body body = wrapFloatBindsE dx_binds $
|
|
|
1775
|
+ body `mkApps` spec_args
|
|
1761
|
1776
|
spec_unf = specUnfolding simpl_opts rule_rhs_args1 wrap_unf_body
|
|
1762
|
1777
|
rule_lhs_args fn_unf
|
|
1763
|
1778
|
|
| ... |
... |
@@ -2529,10 +2544,11 @@ instance Outputable SpecArg where |
|
2529
|
2544
|
ppr UnspecType = text "UnspecType"
|
|
2530
|
2545
|
ppr UnspecArg = text "UnspecArg"
|
|
2531
|
2546
|
|
|
2532
|
|
-specArgsFVs :: InterestingVarFun -> [SpecArg] -> FV
|
|
2533
|
|
--- Find the free vars of the SpecArgs that are not already in scope
|
|
2534
|
|
-specArgsFVs interesting args
|
|
2535
|
|
- = filterFV interesting $
|
|
|
2547
|
+specArgsFVs :: [SpecArg] -> VarSet
|
|
|
2548
|
+-- Find the free vars of the SpecArgs
|
|
|
2549
|
+specArgsFVs args
|
|
|
2550
|
+ = fvVarSet $
|
|
|
2551
|
+ filterFV isLocalVar $ -- Including TyVars
|
|
2536
|
2552
|
foldr (unionFV . get) emptyFV args
|
|
2537
|
2553
|
where
|
|
2538
|
2554
|
get :: SpecArg -> FV
|
| ... |
... |
@@ -2607,15 +2623,15 @@ specHeader |
|
2607
|
2623
|
-- `$sf = \spec_bndrs. let { dx_binds } in <orig-rhs> spec_arg`
|
|
2608
|
2624
|
, [OutBndr] -- spec_bndrs: Binders for $sf, and args for the RHS
|
|
2609
|
2625
|
-- of the RULE. Subset of rule_bndrs.
|
|
2610
|
|
- , [DictBind] -- dx_binds: Auxiliary dictionary bindings
|
|
|
2626
|
+ , OrdList FloatBind -- dx_binds: Auxiliary dictionary bindings
|
|
2611
|
2627
|
, [OutExpr] -- spec_args: Specialised arguments for unfolding
|
|
2612
|
2628
|
-- Same length as "Args for LHS of rule"
|
|
2613
|
2629
|
)
|
|
2614
|
2630
|
|
|
2615
|
2631
|
-- If we run out of binders, stop immediately
|
|
2616
|
2632
|
-- See Note [Specialisation Must Preserve Sharing]
|
|
2617
|
|
-specHeader subst [] _ = pure (False, subst, [], [], [], [], [])
|
|
2618
|
|
-specHeader subst _ [] = pure (False, subst, [], [], [], [], [])
|
|
|
2633
|
+specHeader subst [] _ = pure (False, subst, [], [], [], nilOL, [])
|
|
|
2634
|
+specHeader subst _ [] = pure (False, subst, [], [], [], nilOL, [])
|
|
2619
|
2635
|
|
|
2620
|
2636
|
-- We want to specialise on type 'T1', and so we must construct a substitution
|
|
2621
|
2637
|
-- 'a->T1', as well as a LHS argument for the resulting RULE and unfolding
|
| ... |
... |
@@ -2671,20 +2687,23 @@ specHeader subst (bndr:bndrs) (_ : args) |
|
2671
|
2687
|
-- a wildcard binder to match the dictionary (See Note [Specialising Calls] for
|
|
2672
|
2688
|
-- the nitty-gritty), as a LHS rule and unfolding details.
|
|
2673
|
2689
|
specHeader subst (bndr:bndrs) (SpecDict dict_arg : args)
|
|
2674
|
|
- = do { -- Make up a fresh binder to use in the RULE
|
|
|
2690
|
+ = do { let (tv_bndrs, tv_binds) = bindAuxiliaryTyVars subst dict_arg
|
|
|
2691
|
+ subst1 = subst `Core.extendSubstInScopeSet` tv_bndrs
|
|
|
2692
|
+
|
|
|
2693
|
+ -- Make up a fresh binder to use in the RULE
|
|
2675
|
2694
|
-- It might turn into a dict binding (via bindAuxiliaryDict) which we
|
|
2676
|
2695
|
-- then float, so we use cloneIdBndr to get a completely fresh binder
|
|
2677
|
|
- u <- getUniqueM
|
|
2678
|
|
- ; let (subst1, bndr') = Core.cloneBndr subst u (zapIdOccInfo bndr)
|
|
|
2696
|
+ ; u <- getUniqueM
|
|
|
2697
|
+ ; let (subst2, bndr') = Core.cloneBndr subst1 u (zapIdOccInfo bndr)
|
|
2679
|
2698
|
-- zapIdOccInfo: see Note [Zap occ info in rule binders]
|
|
2680
|
2699
|
|
|
2681
|
2700
|
-- Extend the substitution to map bndr :-> dict_arg, for use in the RHS
|
|
2682
|
|
- ; let (subst2, dx_bind, spec_dict) = bindAuxiliaryDict subst1 bndr bndr' dict_arg
|
|
|
2701
|
+ ; let (subst3, dx1, spec_dict) = bindAuxiliaryDict subst2 bndr bndr' dict_arg
|
|
2683
|
2702
|
|
|
2684
|
|
- ; (_, subst3, rule_bs, rule_es, spec_bs, dx, spec_args) <- specHeader subst2 bndrs args
|
|
|
2703
|
+ ; (_, subst4, rule_bs, rule_es, spec_bs, dx, spec_args) <- specHeader subst3 bndrs args
|
|
2685
|
2704
|
|
|
2686
|
|
- ; let dx' = case dx_bind of { Nothing -> dx; Just d -> d : dx }
|
|
2687
|
|
- ; pure ( True, subst3 -- Ha! A useful specialisation!
|
|
|
2705
|
+ ; let dx' = tv_binds `appOL` dx1 `appOL` dx
|
|
|
2706
|
+ ; pure ( True, subst4 -- Ha! A useful specialisation!
|
|
2688
|
2707
|
, bndr' : rule_bs, Var bndr' : rule_es
|
|
2689
|
2708
|
, spec_bs, dx', spec_dict : spec_args ) }
|
|
2690
|
2709
|
|
| ... |
... |
@@ -2713,13 +2732,46 @@ specHeader subst (bndr:bndrs) (UnspecArg : args) |
|
2713
|
2732
|
, bndrs ++ spec_bs, dx, dummy_arg : spec_args ) }
|
|
2714
|
2733
|
|
|
2715
|
2734
|
|
|
|
2735
|
+bindAuxiliaryTyVars :: Subst -> CoreExpr -> (TyVarSet, OrdList FloatBind)
|
|
|
2736
|
+bindAuxiliaryTyVars subst dict_arg
|
|
|
2737
|
+ = go emptyVarSet need_bind_tvs
|
|
|
2738
|
+ where
|
|
|
2739
|
+ go _ []
|
|
|
2740
|
+ = (emptyVarSet, nilOL)
|
|
|
2741
|
+ go tv_bndrs (tv:tvs)
|
|
|
2742
|
+ | tv `elemVarSet` tv_bndrs
|
|
|
2743
|
+ = go tv_bndrs tvs
|
|
|
2744
|
+ | Just unf <- tyVarUnfolding_maybe tv
|
|
|
2745
|
+ , (child_bndrs, child_binds) <- go tv_bndrs (someTyCoVarsOfTypeList needs_binding unf)
|
|
|
2746
|
+ , let tv_bndrs1 = child_bndrs `extendVarSet` tv
|
|
|
2747
|
+ , (rest_bndrs, rest_binds) <- go tv_bndrs1 tvs
|
|
|
2748
|
+ = ( rest_bndrs
|
|
|
2749
|
+ , child_binds `appOL` unitOL (mkDB (NonRec tv (Type unf)))
|
|
|
2750
|
+ `appOL` rest_binds )
|
|
|
2751
|
+ | otherwise
|
|
|
2752
|
+ = pprTrace "addTyVarBindings: unxpected 1" (ppr tv $$ ppr dict_arg) $
|
|
|
2753
|
+ go tv_bndrs tvs
|
|
|
2754
|
+
|
|
|
2755
|
+ need_bind_tvs = exprSomeFreeVarsList needs_binding dict_arg
|
|
|
2756
|
+ in_scope = substInScopeSet subst
|
|
|
2757
|
+ needs_binding var
|
|
|
2758
|
+ | isGlobalVar var
|
|
|
2759
|
+ = False
|
|
|
2760
|
+ | var `elemInScopeSet` in_scope
|
|
|
2761
|
+ = False
|
|
|
2762
|
+ | otherwise
|
|
|
2763
|
+ = case tyVarUnfolding_maybe var of
|
|
|
2764
|
+ Just {} -> True
|
|
|
2765
|
+ Nothing -> pprPanic "addTyVarBindings: unexpected 2"
|
|
|
2766
|
+ (ppr var $$ ppr dict_arg)
|
|
|
2767
|
+
|
|
2716
|
2768
|
-- | Binds a dictionary argument to a fresh name, to preserve sharing
|
|
2717
|
2769
|
bindAuxiliaryDict
|
|
2718
|
2770
|
:: Subst
|
|
2719
|
2771
|
-> InId -> OutId -> OutExpr -- Original dict binder, and the witnessing expression
|
|
2720
|
|
- -> ( Subst -- Substitutes for orig_dict_id
|
|
2721
|
|
- , Maybe DictBind -- Auxiliary dict binding, if any
|
|
2722
|
|
- , OutExpr) -- Witnessing expression (always trivial)
|
|
|
2772
|
+ -> ( Subst -- Substitutes for orig_dict_id
|
|
|
2773
|
+ , OrdList FloatBind -- Auxiliary dict binding, if any
|
|
|
2774
|
+ , OutExpr) -- Witnessing expression (always trivial)
|
|
2723
|
2775
|
bindAuxiliaryDict subst orig_dict_id fresh_dict_id dict_arg
|
|
2724
|
2776
|
|
|
2725
|
2777
|
-- If the dictionary argument is trivial,
|
| ... |
... |
@@ -2727,7 +2779,7 @@ bindAuxiliaryDict subst orig_dict_id fresh_dict_id dict_arg |
|
2727
|
2779
|
| exprIsTrivial dict_arg
|
|
2728
|
2780
|
, let subst' = Core.extendSubst subst orig_dict_id dict_arg
|
|
2729
|
2781
|
= -- pprTrace "bindAuxiliaryDict:trivial" (ppr orig_dict_id <+> ppr dict_arg) $
|
|
2730
|
|
- (subst', Nothing, dict_arg)
|
|
|
2782
|
+ (subst', nilOL, dict_arg)
|
|
2731
|
2783
|
|
|
2732
|
2784
|
| otherwise -- Non-trivial dictionary arg; make an auxiliary binding
|
|
2733
|
2785
|
, let fresh_dict_id' = fresh_dict_id `addDictUnfolding` dict_arg
|
| ... |
... |
@@ -2737,7 +2789,7 @@ bindAuxiliaryDict subst orig_dict_id fresh_dict_id dict_arg |
|
2737
|
2789
|
`Core.extendSubstInScope` fresh_dict_id'
|
|
2738
|
2790
|
-- Ensure the new unfolding is in the in-scope set
|
|
2739
|
2791
|
= -- pprTrace "bindAuxiliaryDict:non-trivial" (ppr orig_dict_id <+> ppr fresh_dict_id') $
|
|
2740
|
|
- (subst', Just dict_bind, Var fresh_dict_id')
|
|
|
2792
|
+ (subst', unitOL dict_bind, Var fresh_dict_id')
|
|
2741
|
2793
|
|
|
2742
|
2794
|
addDictUnfolding :: Id -> CoreExpr -> Id
|
|
2743
|
2795
|
-- Add unfolding for freshly-bound Ids: see Note [Make the new dictionaries interesting]
|
| ... |
... |
@@ -2767,34 +2819,34 @@ in the dictionary Id. |
|
2767
|
2819
|
********************************************************************* -}
|
|
2768
|
2820
|
|
|
2769
|
2821
|
data UsageDetails
|
|
2770
|
|
- = MkUD { ud_binds :: !FloatedDictBinds
|
|
|
2822
|
+ = MkUD { ud_binds :: !FloatBinds
|
|
2771
|
2823
|
, ud_calls :: !CallDetails }
|
|
2772
|
|
- -- INVARIANT: suppose bs = fdb_bndrs ud_binds
|
|
|
2824
|
+ -- INVARIANT: suppose bs = fbs_bndrs ud_binds
|
|
2773
|
2825
|
-- Then 'calls' may *mention* 'bs',
|
|
2774
|
2826
|
-- but there should be no calls *for* bs
|
|
2775
|
2827
|
|
|
2776
|
|
-data FloatedDictBinds -- See Note [Floated dictionary bindings]
|
|
2777
|
|
- = FDB { fdb_binds :: !(OrdList DictBind)
|
|
|
2828
|
+data FloatBinds -- See Note [Floated dictionary bindings]
|
|
|
2829
|
+ = FDB { fbs_binds :: !(OrdList FloatBind)
|
|
2778
|
2830
|
-- The order is important;
|
|
2779
|
2831
|
-- in ds1 `appOL` ds2, bindings in ds2 can depend on those in ds1
|
|
2780
|
2832
|
|
|
2781
|
|
- , fdb_bndrs :: !IdSet
|
|
2782
|
|
- } -- ^ The binders of 'fdb_binds'.
|
|
|
2833
|
+ , fbs_bndrs :: !IdSet
|
|
|
2834
|
+ } -- ^ The binders of 'fbs_binds'.
|
|
2783
|
2835
|
-- Caches a superset of the expression
|
|
2784
|
|
- -- `mkVarSet (bindersOfDictBinds fdb_binds))`
|
|
|
2836
|
+ -- `mkVarSet (bindersOfFloatBinds fbs_binds))`
|
|
2785
|
2837
|
-- for later addition to an InScopeSet
|
|
2786
|
2838
|
|
|
2787
|
|
--- | A 'DictBind' is a binding along with a cached set containing its free
|
|
|
2839
|
+-- | A 'FloatBind' is a binding along with a cached set containing its free
|
|
2788
|
2840
|
-- variables (both type variables and dictionaries). We need this set
|
|
2789
|
|
--- in splitDictBinds, when filtering bindings to decide which are
|
|
|
2841
|
+-- in splitFloatBinds, when filtering bindings to decide which are
|
|
2790
|
2842
|
-- captured by a binder
|
|
2791
|
|
-data DictBind = DB { db_bind :: CoreBind, db_fvs :: VarSet }
|
|
|
2843
|
+data FloatBind = DB { fb_bind :: CoreBind, fb_fvs :: VarSet }
|
|
2792
|
2844
|
|
|
2793
|
|
-bindersOfDictBind :: DictBind -> [Id]
|
|
2794
|
|
-bindersOfDictBind = bindersOf . db_bind
|
|
|
2845
|
+bindersOfFloatBind :: FloatBind -> [Id]
|
|
|
2846
|
+bindersOfFloatBind = bindersOf . fb_bind
|
|
2795
|
2847
|
|
|
2796
|
|
-bindersOfDictBinds :: Foldable f => f DictBind -> [Id]
|
|
2797
|
|
-bindersOfDictBinds = bindersOfBinds . foldr ((:) . db_bind) []
|
|
|
2848
|
+bindersOfFloatBinds :: Foldable f => f FloatBind -> [Id]
|
|
|
2849
|
+bindersOfFloatBinds = bindersOfBinds . foldr ((:) . fb_bind) []
|
|
2798
|
2850
|
|
|
2799
|
2851
|
{- Note [Floated dictionary bindings]
|
|
2800
|
2852
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... |
... |
@@ -2819,7 +2871,7 @@ and continue. But then we have to add $c== to the floats, and so on. |
|
2819
|
2871
|
These all float above the binding for 'f', and now we can
|
|
2820
|
2872
|
successfully specialise 'f'.
|
|
2821
|
2873
|
|
|
2822
|
|
-So the DictBinds in (ud_binds :: OrdList DictBind) may contain
|
|
|
2874
|
+So the FloatBinds in (ud_binds :: OrdList FloatBind) may contain
|
|
2823
|
2875
|
non-dictionary bindings too.
|
|
2824
|
2876
|
|
|
2825
|
2877
|
Note [Specialising polymorphic dictionaries]
|
| ... |
... |
@@ -2853,9 +2905,8 @@ Here are the moving parts: |
|
2853
|
2905
|
CIS wimwam (CI { ci_key = [@(ST s), dMST @s]
|
|
2854
|
2906
|
, ci_fvs = {dMST} })
|
|
2855
|
2907
|
when we come to the /\s. Instead, we simply let it continue to float
|
|
2856
|
|
- upwards. Hence ci_fvs is an IdSet, listing the /Ids/ that
|
|
2857
|
|
- are free in the call, but not the /TyVars/. Hence using specArgFreeIds
|
|
2858
|
|
- in singleCall.
|
|
|
2908
|
+ upwards. We deal with this in `deleteCallsMentioning`,
|
|
|
2909
|
+ when `Opt_PolymorphicSpecialisation` is on
|
|
2859
|
2910
|
|
|
2860
|
2911
|
NB to be fully kosher we should explicitly quantifying the CallInfo
|
|
2861
|
2912
|
over 's', but we don't bother. This would matter if there was an
|
| ... |
... |
@@ -2953,8 +3004,8 @@ over too many type variables. But that too is now fixed; |
|
2953
|
3004
|
see Note [Which type variables to abstract over] in that module.
|
|
2954
|
3005
|
-}
|
|
2955
|
3006
|
|
|
2956
|
|
-instance Outputable DictBind where
|
|
2957
|
|
- ppr (DB { db_bind = bind, db_fvs = fvs })
|
|
|
3007
|
+instance Outputable FloatBind where
|
|
|
3008
|
+ ppr (DB { fb_bind = bind, fb_fvs = fvs })
|
|
2958
|
3009
|
= text "DB" <+> braces (sep [ text "fvs: " <+> ppr fvs
|
|
2959
|
3010
|
, text "bind:" <+> ppr bind ])
|
|
2960
|
3011
|
|
| ... |
... |
@@ -2964,15 +3015,15 @@ instance Outputable UsageDetails where |
|
2964
|
3015
|
[text "binds" <+> equals <+> ppr dbs,
|
|
2965
|
3016
|
text "calls" <+> equals <+> ppr calls]))
|
|
2966
|
3017
|
|
|
2967
|
|
-instance Outputable FloatedDictBinds where
|
|
2968
|
|
- ppr (FDB { fdb_binds = binds }) = ppr binds
|
|
|
3018
|
+instance Outputable FloatBinds where
|
|
|
3019
|
+ ppr (FDB { fbs_binds = binds }) = ppr binds
|
|
2969
|
3020
|
|
|
2970
|
3021
|
emptyUDs :: UsageDetails
|
|
2971
|
3022
|
emptyUDs = MkUD { ud_binds = emptyFDBs, ud_calls = emptyDVarEnv }
|
|
2972
|
3023
|
|
|
2973
|
3024
|
|
|
2974
|
|
-emptyFDBs :: FloatedDictBinds
|
|
2975
|
|
-emptyFDBs = FDB { fdb_binds = nilOL, fdb_bndrs = emptyVarSet }
|
|
|
3025
|
+emptyFDBs :: FloatBinds
|
|
|
3026
|
+emptyFDBs = FDB { fbs_binds = nilOL, fbs_bndrs = emptyVarSet }
|
|
2976
|
3027
|
|
|
2977
|
3028
|
------------------------------------------------------------
|
|
2978
|
3029
|
type CallDetails = DIdEnv CallInfoSet
|
| ... |
... |
@@ -2990,9 +3041,9 @@ data CallInfo |
|
2990
|
3041
|
= CI { ci_key :: [SpecArg] -- Arguments of the call
|
|
2991
|
3042
|
-- See Note [The (CI-KEY) invariant]
|
|
2992
|
3043
|
|
|
2993
|
|
- , ci_fvs :: IdSet -- Free Ids of the ci_key call
|
|
|
3044
|
+ , ci_fvs :: IdSet -- All free vars of ci_key arguments
|
|
2994
|
3045
|
-- /not/ including the main id itself, of course
|
|
2995
|
|
- -- NB: excluding tyvars:
|
|
|
3046
|
+ -- NB: including tyvars:
|
|
2996
|
3047
|
-- See Note [Specialising polymorphic dictionaries]
|
|
2997
|
3048
|
}
|
|
2998
|
3049
|
|
| ... |
... |
@@ -3047,21 +3098,15 @@ getTheta = fmap piTyBinderType . filter isInvisiblePiTyBinder . filter isAnonPiT |
|
3047
|
3098
|
|
|
3048
|
3099
|
|
|
3049
|
3100
|
------------------------------------------------------------
|
|
3050
|
|
-singleCall :: SpecEnv -> Id -> [SpecArg] -> UsageDetails
|
|
3051
|
|
-singleCall spec_env id args
|
|
|
3101
|
+singleCall :: Id -> [SpecArg] -> UsageDetails
|
|
|
3102
|
+singleCall id args
|
|
3052
|
3103
|
= MkUD {ud_binds = emptyFDBs,
|
|
3053
|
3104
|
ud_calls = unitDVarEnv id $ CIS id $
|
|
3054
|
|
- unitBag (CI { ci_key = args
|
|
3055
|
|
- , ci_fvs = fvVarSet call_fvs }) }
|
|
|
3105
|
+ unitBag call_info }
|
|
3056
|
3106
|
where
|
|
3057
|
|
- poly_spec = gopt Opt_PolymorphicSpecialisation (se_dflags spec_env)
|
|
3058
|
|
-
|
|
3059
|
|
- -- With -fpolymorphic-specialisation, keep just local /Ids/
|
|
3060
|
|
- -- Otherwise, keep /all/ free vars including TyVars
|
|
3061
|
|
- -- See (MP1) in Note [Specialising polymorphic dictionaries]
|
|
3062
|
|
- -- But NB: we don't include the 'id' itself.
|
|
3063
|
|
- call_fvs | poly_spec = specArgsFVs isLocalId args
|
|
3064
|
|
- | otherwise = specArgsFVs isLocalVar args
|
|
|
3107
|
+ call_info = CI { ci_key = args
|
|
|
3108
|
+ , ci_fvs = specArgsFVs args }
|
|
|
3109
|
+ -- See (STV1) in Note [Specialisation and type-variable bindings]
|
|
3065
|
3110
|
|
|
3066
|
3111
|
mkCallUDs :: SpecEnv -> OutExpr -> [OutExpr] -> UsageDetails
|
|
3067
|
3112
|
mkCallUDs env fun args
|
| ... |
... |
@@ -3076,7 +3121,7 @@ mkCallUDs' env f args |
|
3076
|
3121
|
| wantCallsFor env f -- We want it, and...
|
|
3077
|
3122
|
, not (null ci_key) -- this call site has a useful specialisation
|
|
3078
|
3123
|
= -- pprTrace "mkCallUDs: keeping" _trace_doc
|
|
3079
|
|
- singleCall env f ci_key
|
|
|
3124
|
+ singleCall f ci_key
|
|
3080
|
3125
|
|
|
3081
|
3126
|
| otherwise -- See also Note [Specialisations already covered]
|
|
3082
|
3127
|
= -- pprTrace "mkCallUDs: discarding" _trace_doc
|
| ... |
... |
@@ -3352,21 +3397,21 @@ thenUDs (MkUD {ud_binds = db1, ud_calls = calls1}) |
|
3352
|
3397
|
= MkUD { ud_binds = db1 `thenFDBs` db2
|
|
3353
|
3398
|
, ud_calls = calls1 `unionCalls` calls2 }
|
|
3354
|
3399
|
|
|
3355
|
|
-thenFDBs :: FloatedDictBinds -> FloatedDictBinds -> FloatedDictBinds
|
|
3356
|
|
--- Combine FloatedDictBinds
|
|
|
3400
|
+thenFDBs :: FloatBinds -> FloatBinds -> FloatBinds
|
|
|
3401
|
+-- Combine FloatBinds
|
|
3357
|
3402
|
-- In (dbs1 `thenFDBs` dbs2), dbs2 may mention dbs1 but not vice versa
|
|
3358
|
|
-thenFDBs (FDB { fdb_binds = dbs1, fdb_bndrs = bs1 })
|
|
3359
|
|
- (FDB { fdb_binds = dbs2, fdb_bndrs = bs2 })
|
|
3360
|
|
- = FDB { fdb_binds = dbs1 `appOL` dbs2
|
|
3361
|
|
- , fdb_bndrs = bs1 `unionVarSet` bs2 }
|
|
|
3403
|
+thenFDBs (FDB { fbs_binds = dbs1, fbs_bndrs = bs1 })
|
|
|
3404
|
+ (FDB { fbs_binds = dbs2, fbs_bndrs = bs2 })
|
|
|
3405
|
+ = FDB { fbs_binds = dbs1 `appOL` dbs2
|
|
|
3406
|
+ , fbs_bndrs = bs1 `unionVarSet` bs2 }
|
|
3362
|
3407
|
|
|
3363
|
3408
|
-----------------------------
|
|
3364
|
|
-_dictBindBndrs :: OrdList DictBind -> [Id]
|
|
3365
|
|
-_dictBindBndrs dbs = foldr ((++) . bindersOf . db_bind) [] dbs
|
|
|
3409
|
+_dictBindBndrs :: OrdList FloatBind -> [Id]
|
|
|
3410
|
+_dictBindBndrs dbs = foldr ((++) . bindersOf . fb_bind) [] dbs
|
|
3366
|
3411
|
|
|
3367
|
|
--- | Construct a 'DictBind' from a 'CoreBind'
|
|
3368
|
|
-mkDB :: CoreBind -> DictBind
|
|
3369
|
|
-mkDB bind = DB { db_bind = bind, db_fvs = bind_fvs bind }
|
|
|
3412
|
+-- | Construct a 'FloatBind' from a 'CoreBind'
|
|
|
3413
|
+mkDB :: CoreBind -> FloatBind
|
|
|
3414
|
+mkDB bind = DB { fb_bind = bind, fb_fvs = bind_fvs bind }
|
|
3370
|
3415
|
|
|
3371
|
3416
|
-- | Identify the free variables of a 'CoreBind'
|
|
3372
|
3417
|
bind_fvs :: CoreBind -> VarSet
|
| ... |
... |
@@ -3397,54 +3442,54 @@ pair_fvs (bndr, rhs) = bndr_fvs `unionVarSet` rhs_fvs |
|
3397
|
3442
|
-- whether a dictionary binding depends on an imported
|
|
3398
|
3443
|
-- DFun in case we try to specialise that imported DFun
|
|
3399
|
3444
|
|
|
3400
|
|
--- | Flatten a set of "dumped" 'DictBind's, and some other binding
|
|
|
3445
|
+-- | Flatten a set of "dumped" 'FloatBind's, and some other binding
|
|
3401
|
3446
|
-- pairs, into a single recursive binding.
|
|
3402
|
|
-recWithDumpedDicts :: [(Id,CoreExpr)] -> OrdList DictBind -> DictBind
|
|
|
3447
|
+recWithDumpedDicts :: [(Id,CoreExpr)] -> OrdList FloatBind -> FloatBind
|
|
3403
|
3448
|
recWithDumpedDicts pairs dbs
|
|
3404
|
|
- = DB { db_bind = Rec bindings
|
|
3405
|
|
- , db_fvs = fvs `delVarSetList` map fst bindings }
|
|
|
3449
|
+ = DB { fb_bind = Rec bindings
|
|
|
3450
|
+ , fb_fvs = fvs `delVarSetList` map fst bindings }
|
|
3406
|
3451
|
where
|
|
3407
|
3452
|
(bindings, fvs) = foldr add ([], emptyVarSet)
|
|
3408
|
3453
|
(dbs `snocOL` mkDB (Rec pairs))
|
|
3409
|
|
- add (DB { db_bind = bind, db_fvs = fvs }) (prs_acc, fvs_acc)
|
|
|
3454
|
+ add (DB { fb_bind = bind, fb_fvs = fvs }) (prs_acc, fvs_acc)
|
|
3410
|
3455
|
= case bind of
|
|
3411
|
3456
|
NonRec b r -> ((b,r) : prs_acc, fvs')
|
|
3412
|
3457
|
Rec prs1 -> (prs1 ++ prs_acc, fvs')
|
|
3413
|
3458
|
where
|
|
3414
|
3459
|
fvs' = fvs_acc `unionVarSet` fvs
|
|
3415
|
3460
|
|
|
3416
|
|
-snocDictBind :: UsageDetails -> DictBind -> UsageDetails
|
|
3417
|
|
-snocDictBind uds@MkUD{ud_binds= FDB { fdb_binds = dbs, fdb_bndrs = bs }} db
|
|
3418
|
|
- = uds { ud_binds = FDB { fdb_binds = dbs `snocOL` db
|
|
3419
|
|
- , fdb_bndrs = bs `extendVarSetList` bindersOfDictBind db } }
|
|
|
3461
|
+snocFloatBind :: UsageDetails -> FloatBind -> UsageDetails
|
|
|
3462
|
+snocFloatBind uds@MkUD{ud_binds= FDB { fbs_binds = dbs, fbs_bndrs = bs }} db
|
|
|
3463
|
+ = uds { ud_binds = FDB { fbs_binds = dbs `snocOL` db
|
|
|
3464
|
+ , fbs_bndrs = bs `extendVarSetList` bindersOfFloatBind db } }
|
|
3420
|
3465
|
|
|
3421
|
|
-snocDictBinds :: UsageDetails -> [DictBind] -> UsageDetails
|
|
|
3466
|
+snocFloatBinds :: UsageDetails -> OrdList FloatBind -> UsageDetails
|
|
3422
|
3467
|
-- Add ud_binds to the tail end of the bindings in uds
|
|
3423
|
|
-snocDictBinds uds@MkUD{ud_binds=FDB{ fdb_binds = binds, fdb_bndrs = bs }} dbs
|
|
3424
|
|
- = uds { ud_binds = FDB { fdb_binds = binds `appOL` (toOL dbs)
|
|
3425
|
|
- , fdb_bndrs = bs `extendVarSetList` bindersOfDictBinds dbs } }
|
|
|
3468
|
+snocFloatBinds uds@MkUD{ud_binds=FDB{ fbs_binds = binds, fbs_bndrs = bs }} dbs
|
|
|
3469
|
+ = uds { ud_binds = FDB { fbs_binds = binds `appOL` dbs
|
|
|
3470
|
+ , fbs_bndrs = bs `extendVarSetList` bindersOfFloatBinds dbs } }
|
|
3426
|
3471
|
|
|
3427
|
|
-consDictBinds :: [DictBind] -> UsageDetails -> UsageDetails
|
|
3428
|
|
-consDictBinds dbs uds@MkUD{ud_binds=FDB{fdb_binds = binds, fdb_bndrs = bs}}
|
|
3429
|
|
- = uds { ud_binds = FDB{ fdb_binds = toOL dbs `appOL` binds
|
|
3430
|
|
- , fdb_bndrs = bs `extendVarSetList` bindersOfDictBinds dbs } }
|
|
|
3472
|
+consFloatBinds :: OrdList FloatBind -> UsageDetails -> UsageDetails
|
|
|
3473
|
+consFloatBinds dbs uds@MkUD{ud_binds=FDB{fbs_binds = binds, fbs_bndrs = bs}}
|
|
|
3474
|
+ = uds { ud_binds = FDB{ fbs_binds = dbs `appOL` binds
|
|
|
3475
|
+ , fbs_bndrs = bs `extendVarSetList` bindersOfFloatBinds dbs } }
|
|
3431
|
3476
|
|
|
3432
|
|
-wrapDictBinds :: FloatedDictBinds -> [CoreBind] -> [CoreBind]
|
|
3433
|
|
-wrapDictBinds (FDB { fdb_binds = dbs }) binds
|
|
|
3477
|
+wrapFloatBinds :: FloatBinds -> [CoreBind] -> [CoreBind]
|
|
|
3478
|
+wrapFloatBinds (FDB { fbs_binds = dbs }) binds
|
|
3434
|
3479
|
= foldr add binds dbs
|
|
3435
|
3480
|
where
|
|
3436
|
|
- add (DB { db_bind = bind }) binds = bind : binds
|
|
|
3481
|
+ add (DB { fb_bind = bind }) binds = bind : binds
|
|
3437
|
3482
|
|
|
3438
|
|
-wrapDictBindsE :: OrdList DictBind -> CoreExpr -> CoreExpr
|
|
3439
|
|
-wrapDictBindsE dbs expr
|
|
|
3483
|
+wrapFloatBindsE :: OrdList FloatBind -> CoreExpr -> CoreExpr
|
|
|
3484
|
+wrapFloatBindsE dbs expr
|
|
3440
|
3485
|
= foldr add expr dbs
|
|
3441
|
3486
|
where
|
|
3442
|
|
- add (DB { db_bind = bind }) expr = Let bind expr
|
|
|
3487
|
+ add (DB { fb_bind = bind }) expr = Let bind expr
|
|
3443
|
3488
|
|
|
3444
|
3489
|
----------------------
|
|
3445
|
|
-dumpUDs :: [CoreBndr] -> UsageDetails -> (UsageDetails, OrdList DictBind)
|
|
|
3490
|
+dumpUDs :: SpecEnv -> [CoreBndr] -> UsageDetails -> (UsageDetails, OrdList FloatBind)
|
|
3446
|
3491
|
-- Used at binder; just dump anything mentioning the binder
|
|
3447
|
|
-dumpUDs bndrs uds@(MkUD { ud_binds = orig_dbs, ud_calls = orig_calls })
|
|
|
3492
|
+dumpUDs env bndrs uds@(MkUD { ud_binds = orig_dbs, ud_calls = orig_calls })
|
|
3448
|
3493
|
| null bndrs = (uds, nilOL) -- Common in case alternatives
|
|
3449
|
3494
|
| otherwise = -- pprTrace "dumpUDs" (vcat
|
|
3450
|
3495
|
-- [ text "bndrs" <+> ppr bndrs
|
| ... |
... |
@@ -3455,19 +3500,20 @@ dumpUDs bndrs uds@(MkUD { ud_binds = orig_dbs, ud_calls = orig_calls }) |
|
3455
|
3500
|
where
|
|
3456
|
3501
|
free_uds = uds { ud_binds = free_dbs, ud_calls = free_calls }
|
|
3457
|
3502
|
bndr_set = mkVarSet bndrs
|
|
3458
|
|
- (free_dbs, dump_dbs, dump_set) = splitDictBinds orig_dbs bndr_set
|
|
|
3503
|
+ (free_dbs, dump_dbs, dump_set) = splitFloatBinds orig_dbs bndr_set
|
|
3459
|
3504
|
|
|
3460
|
3505
|
-- Delete calls:
|
|
3461
|
3506
|
-- * For any binder in `bndrs`
|
|
3462
|
3507
|
-- * That mention a dictionary bound in `dump_set`
|
|
3463
|
3508
|
-- These variables aren't in scope "above" the binding and the `dump_dbs`,
|
|
3464
|
3509
|
-- so no call should mention them. (See #26682.)
|
|
3465
|
|
- free_calls = deleteCallsMentioning dump_set $
|
|
|
3510
|
+ free_calls = deleteCallsMentioning env dump_set $
|
|
3466
|
3511
|
deleteCallsFor bndrs orig_calls
|
|
3467
|
3512
|
|
|
3468
|
|
-dumpBindUDs :: Bool -- Main binding can float to top
|
|
|
3513
|
+dumpBindUDs :: SpecEnv
|
|
|
3514
|
+ -> Bool -- Main binding can float to top
|
|
3469
|
3515
|
-> [CoreBndr] -> UsageDetails
|
|
3470
|
|
- -> (UsageDetails, OrdList DictBind, Bool)
|
|
|
3516
|
+ -> (UsageDetails, OrdList FloatBind, Bool)
|
|
3471
|
3517
|
-- Used at a let(rec) binding.
|
|
3472
|
3518
|
-- We return a boolean indicating whether the binding itself
|
|
3473
|
3519
|
-- is mentioned, directly or indirectly, by any of the ud_calls;
|
| ... |
... |
@@ -3475,17 +3521,17 @@ dumpBindUDs :: Bool -- Main binding can float to top |
|
3475
|
3521
|
-- See Note [Floated dictionary bindings]
|
|
3476
|
3522
|
-- If the boolean is True, then the returned ud_calls can mention `bndrs`;
|
|
3477
|
3523
|
-- if False, then returned ud_calls must not mention `bndrs`
|
|
3478
|
|
-dumpBindUDs can_float_bind bndrs (MkUD { ud_binds = orig_dbs, ud_calls = orig_calls })
|
|
|
3524
|
+dumpBindUDs env can_float_bind bndrs (MkUD { ud_binds = orig_dbs, ud_calls = orig_calls })
|
|
3479
|
3525
|
= ( MkUD { ud_binds = free_dbs, ud_calls = free_calls2 }
|
|
3480
|
3526
|
, dump_dbs
|
|
3481
|
3527
|
, can_float_bind && calls_mention_bndrs )
|
|
3482
|
3528
|
where
|
|
3483
|
3529
|
bndr_set = mkVarSet bndrs
|
|
3484
|
|
- (free_dbs, dump_dbs, dump_set) = splitDictBinds orig_dbs bndr_set
|
|
|
3530
|
+ (free_dbs, dump_dbs, dump_set) = splitFloatBinds orig_dbs bndr_set
|
|
3485
|
3531
|
free_calls1 = deleteCallsFor bndrs orig_calls
|
|
3486
|
3532
|
calls_mention_bndrs = dump_set `intersectsVarSet` callDetailsFVs free_calls1
|
|
3487
|
3533
|
free_calls2 | can_float_bind = free_calls1
|
|
3488
|
|
- | otherwise = deleteCallsMentioning dump_set free_calls1
|
|
|
3534
|
+ | otherwise = deleteCallsMentioning env dump_set free_calls1
|
|
3489
|
3535
|
|
|
3490
|
3536
|
callsForMe :: Id -> UsageDetails -> (UsageDetails, [CallInfo])
|
|
3491
|
3537
|
callsForMe fn uds@MkUD { ud_binds = orig_dbs, ud_calls = orig_calls }
|
| ... |
... |
@@ -3502,22 +3548,22 @@ callsForMe fn uds@MkUD { ud_binds = orig_dbs, ud_calls = orig_calls } |
|
3502
|
3548
|
Just cis -> filterCalls cis orig_dbs
|
|
3503
|
3549
|
|
|
3504
|
3550
|
----------------------
|
|
3505
|
|
-filterCalls :: CallInfoSet -> FloatedDictBinds -> [CallInfo]
|
|
|
3551
|
+filterCalls :: CallInfoSet -> FloatBinds -> [CallInfo]
|
|
3506
|
3552
|
-- Remove
|
|
3507
|
3553
|
-- (a) dominated calls: (MP3) in Note [Specialising polymorphic dictionaries]
|
|
3508
|
3554
|
-- (b) loopy DFuns: Note [Avoiding loops (DFuns)]
|
|
3509
|
|
-filterCalls (CIS fn call_bag) (FDB { fdb_binds = dbs })
|
|
|
3555
|
+filterCalls (CIS fn call_bag) (FDB { fbs_binds = dbs })
|
|
3510
|
3556
|
| isDFunId fn = filter ok_call de_dupd_calls -- Deals with (b)
|
|
3511
|
3557
|
| otherwise = de_dupd_calls
|
|
3512
|
3558
|
where
|
|
3513
|
3559
|
de_dupd_calls = removeDupCalls call_bag -- Deals with (a)
|
|
3514
|
3560
|
|
|
3515
|
3561
|
dump_set = foldl' go (unitVarSet fn) dbs
|
|
3516
|
|
- -- This dump-set could also be computed by splitDictBinds
|
|
3517
|
|
- -- (_,_,dump_set) = splitDictBinds dbs {fn}
|
|
|
3562
|
+ -- This dump-set could also be computed by splitFloatBinds
|
|
|
3563
|
+ -- (_,_,dump_set) = splitFloatBinds dbs {fn}
|
|
3518
|
3564
|
-- But this variant is shorter
|
|
3519
|
3565
|
|
|
3520
|
|
- go so_far (DB { db_bind = bind, db_fvs = fvs })
|
|
|
3566
|
+ go so_far (DB { fb_bind = bind, fb_fvs = fvs })
|
|
3521
|
3567
|
| fvs `intersectsVarSet` so_far
|
|
3522
|
3568
|
= extendVarSetList so_far (bindersOf bind)
|
|
3523
|
3569
|
| otherwise = so_far
|
| ... |
... |
@@ -3558,16 +3604,16 @@ beats_or_same (CI { ci_key = args1 }) (CI { ci_key = args2 }) |
|
3558
|
3604
|
go_arg _ _ = False
|
|
3559
|
3605
|
|
|
3560
|
3606
|
----------------------
|
|
3561
|
|
-splitDictBinds :: FloatedDictBinds -> IdSet -> (FloatedDictBinds, OrdList DictBind, IdSet)
|
|
3562
|
|
--- splitDictBinds dbs bndrs returns
|
|
|
3607
|
+splitFloatBinds :: FloatBinds -> IdSet -> (FloatBinds, OrdList FloatBind, IdSet)
|
|
|
3608
|
+-- splitFloatBinds dbs bndrs returns
|
|
3563
|
3609
|
-- (free_dbs, dump_dbs, dump_set)
|
|
3564
|
3610
|
-- where
|
|
3565
|
3611
|
-- * dump_dbs depends, transitively on bndrs
|
|
3566
|
3612
|
-- * free_dbs does not depend on bndrs
|
|
3567
|
3613
|
-- * dump_set = bndrs `union` bndrs(dump_dbs)
|
|
3568
|
|
-splitDictBinds (FDB { fdb_binds = dbs, fdb_bndrs = bs }) bndr_set
|
|
3569
|
|
- = (FDB { fdb_binds = free_dbs
|
|
3570
|
|
- , fdb_bndrs = bs `minusVarSet` dump_set }
|
|
|
3614
|
+splitFloatBinds (FDB { fbs_binds = dbs, fbs_bndrs = bs }) bndr_set
|
|
|
3615
|
+ = (FDB { fbs_binds = free_dbs
|
|
|
3616
|
+ , fbs_bndrs = bs `minusVarSet` dump_set }
|
|
3571
|
3617
|
, dump_dbs, dump_set)
|
|
3572
|
3618
|
where
|
|
3573
|
3619
|
(free_dbs, dump_dbs, dump_set)
|
| ... |
... |
@@ -3576,7 +3622,7 @@ splitDictBinds (FDB { fdb_binds = dbs, fdb_bndrs = bs }) bndr_set |
|
3576
|
3622
|
-- we're accumulating the set of dumped ids in dump_set
|
|
3577
|
3623
|
|
|
3578
|
3624
|
split_db (free_dbs, dump_dbs, dump_idset) db
|
|
3579
|
|
- | DB { db_bind = bind, db_fvs = fvs } <- db
|
|
|
3625
|
+ | DB { fb_bind = bind, fb_fvs = fvs } <- db
|
|
3580
|
3626
|
, dump_idset `intersectsVarSet` fvs -- Dump it
|
|
3581
|
3627
|
= (free_dbs, dump_dbs `snocOL` db,
|
|
3582
|
3628
|
extendVarSetList dump_idset (bindersOf bind))
|
| ... |
... |
@@ -3586,15 +3632,26 @@ splitDictBinds (FDB { fdb_binds = dbs, fdb_bndrs = bs }) bndr_set |
|
3586
|
3632
|
|
|
3587
|
3633
|
|
|
3588
|
3634
|
----------------------
|
|
3589
|
|
-deleteCallsMentioning :: VarSet -> CallDetails -> CallDetails
|
|
|
3635
|
+deleteCallsMentioning :: SpecEnv -> VarSet -> CallDetails -> CallDetails
|
|
3590
|
3636
|
-- Remove calls mentioning any Id in bndrs
|
|
3591
|
3637
|
-- NB: The call is allowed to mention TyVars in bndrs
|
|
3592
|
3638
|
-- Note [Specialising polymorphic dictionaries]
|
|
3593
|
3639
|
-- ci_fvs are just the free /Ids/
|
|
3594
|
|
-deleteCallsMentioning bndrs calls
|
|
|
3640
|
+deleteCallsMentioning env bndrs calls
|
|
3595
|
3641
|
= mapDVarEnv (ciSetFilter keep_call) calls
|
|
3596
|
3642
|
where
|
|
3597
|
|
- keep_call (CI { ci_fvs = fvs }) = fvs `disjointVarSet` bndrs
|
|
|
3643
|
+ keep_call (CI { ci_fvs = fvs }) = fvs `disjointVarSet` bad_bndrs
|
|
|
3644
|
+
|
|
|
3645
|
+ poly_spec = gopt Opt_PolymorphicSpecialisation (se_dflags env)
|
|
|
3646
|
+
|
|
|
3647
|
+ -- With -fpolymorphic-specialisation, we allow calls to float outside
|
|
|
3648
|
+ -- the binding of a TyVar, so we restrict the bad_bndrs to just the Ids
|
|
|
3649
|
+ -- See (STV2) in Note [Specialisation and type-variable bindings]
|
|
|
3650
|
+ -- and (MP1) in Note [Specialising polymorphic dictionaries]
|
|
|
3651
|
+ -- But NB: we don't include the 'id' itself.
|
|
|
3652
|
+ bad_bndrs | poly_spec = filterVarSet isId bndrs
|
|
|
3653
|
+ | otherwise = bndrs
|
|
|
3654
|
+
|
|
3598
|
3655
|
|
|
3599
|
3656
|
deleteCallsFor :: [Id] -> CallDetails -> CallDetails
|
|
3600
|
3657
|
-- Remove calls *for* bndrs
|