| ... |
... |
@@ -23,7 +23,7 @@ import GHC.Core.DataCon |
|
23
|
23
|
import GHC.Core.Utils
|
|
24
|
24
|
import GHC.Core.TyCon
|
|
25
|
25
|
import GHC.Core.Type
|
|
26
|
|
-import GHC.Core.FVs ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds )
|
|
|
26
|
+import GHC.Core.FVs ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds, idRuleVars )
|
|
27
|
27
|
import GHC.Core.Coercion ( Coercion )
|
|
28
|
28
|
import GHC.Core.TyCo.FVs ( coVarsOfCos )
|
|
29
|
29
|
import GHC.Core.TyCo.Compare ( eqType )
|
| ... |
... |
@@ -1113,7 +1113,8 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs |
|
1113
|
1113
|
-- might use arguments that the (optimised) RHS doesn't.
|
|
1114
|
1114
|
-- Any argument with a demand absent in one but not the other can
|
|
1115
|
1115
|
-- be problematic, see #26416
|
|
1116
|
|
- combined_rhs_dmds = combineUnfoldingDmds env rhs_sd id rhs_dmds
|
|
|
1116
|
+ -- Also combine the DmdEnv (free variables) from the unfolding
|
|
|
1117
|
+ (unf_fv_env, combined_rhs_dmds) = combineUnfoldingDmds env rhs_sd id rhs_env rhs_dmds
|
|
1117
|
1118
|
|
|
1118
|
1119
|
(final_rhs_dmds, final_rhs) = finaliseArgBoxities env id ww_arity
|
|
1119
|
1120
|
combined_rhs_dmds (de_div rhs_env) rhs'
|
| ... |
... |
@@ -1144,7 +1145,10 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs |
|
1144
|
1145
|
NonRecursive -> rhs_env
|
|
1145
|
1146
|
|
|
1146
|
1147
|
-- See Note [Absence analysis for stable unfoldings and RULES]
|
|
1147
|
|
- rhs_env2 = rhs_env1 `plusDmdEnv` demandRootSet env (bndrRuleAndUnfoldingIds id)
|
|
|
1148
|
+ -- The unfolding FVs are handled via unf_fv_env from combineUnfoldingDmds.
|
|
|
1149
|
+ -- Here we only need demandRoots for RULES.
|
|
|
1150
|
+ rhs_env2 = rhs_env1 `plusDmdEnv` unf_fv_env
|
|
|
1151
|
+ `plusDmdEnv` demandRootSet env (idRuleVars id)
|
|
1148
|
1152
|
|
|
1149
|
1153
|
-- See Note [Lazy and unleashable free variables]
|
|
1150
|
1154
|
!(!sig_env, !weak_fvs) = splitWeakDmds rhs_env2
|
| ... |
... |
@@ -1153,27 +1157,30 @@ splitWeakDmds :: DmdEnv -> (DmdEnv, WeakDmds) |
|
1153
|
1157
|
splitWeakDmds (DE fvs div) = (DE sig_fvs div, weak_fvs)
|
|
1154
|
1158
|
where (!weak_fvs, !sig_fvs) = partitionVarEnv isWeakDmd fvs
|
|
1155
|
1159
|
|
|
1156
|
|
--- | If there is a stable unfolding, don't let any demand be absent that
|
|
1157
|
|
--- is also not absent in the unfolding
|
|
|
1160
|
+-- | If there is a stable unfolding, combine argument demands and free variable
|
|
|
1161
|
+-- demands from the unfolding with those from the RHS.
|
|
1158
|
1162
|
-- See Note [Absence analysis for stable unfoldings and RULES], Wrinkle (W3).
|
|
1159
|
|
-combineUnfoldingDmds :: AnalEnv -> SubDemand -> Id -> [Demand] -> [Demand]
|
|
1160
|
|
-combineUnfoldingDmds env rhs_sd id rhs_dmds
|
|
|
1163
|
+--
|
|
|
1164
|
+-- Returns (combined DmdEnv for free variables, combined arg demands)
|
|
|
1165
|
+-- The DmdEnv is nopDmdEnv if there's no stable unfolding.
|
|
|
1166
|
+combineUnfoldingDmds :: AnalEnv -> SubDemand -> Id -> DmdEnv -> [Demand] -> (DmdEnv, [Demand])
|
|
|
1167
|
+combineUnfoldingDmds env rhs_sd id rhs_fv_env rhs_dmds
|
|
1161
|
1168
|
| not (isStableUnfolding unf)
|
|
1162
|
|
- = rhs_dmds -- No stable unfolding, nothing to do
|
|
|
1169
|
+ = (nopDmdEnv, rhs_dmds) -- No stable unfolding, nothing to do
|
|
1163
|
1170
|
|
|
1164
|
1171
|
| Just unf_body <- maybeUnfoldingTemplate unf
|
|
1165
|
|
- , let WithDmdType (DmdType _ unf_dmds) _ = dmdAnal env rhs_sd unf_body
|
|
1166
|
|
- , let result = go rhs_dmds unf_dmds
|
|
1167
|
|
- = -- pprTrace "lubUnfoldingDmds" (ppr id $$ ppr rhs_dmds $$ ppr unf_dmds $$ ppr result) $
|
|
1168
|
|
- result
|
|
1169
|
|
- | otherwise = rhs_dmds
|
|
|
1172
|
+ , let WithDmdType (DmdType unf_fv_env unf_dmds) _ = dmdAnal env rhs_sd unf_body
|
|
|
1173
|
+ , let combined_dmds = go rhs_dmds unf_dmds
|
|
|
1174
|
+ -- Lub the free variable demands from unfolding with RHS
|
|
|
1175
|
+ combined_fv_env = lubDmdEnv rhs_fv_env unf_fv_env
|
|
|
1176
|
+ = -- pprTrace "combineUnfoldingDmds" (ppr id $$ ppr rhs_dmds $$ ppr unf_dmds $$ ppr combined_dmds) $
|
|
|
1177
|
+ (combined_fv_env, combined_dmds)
|
|
|
1178
|
+ | otherwise = (nopDmdEnv, rhs_dmds)
|
|
1170
|
1179
|
where
|
|
1171
|
1180
|
unf = realIdUnfolding id
|
|
1172
|
1181
|
go rhs [] = rhs
|
|
1173
|
1182
|
go [] _ = []
|
|
1174
|
|
- go (AbsDmd:rhs) (u:unfs) = u : go rhs unfs
|
|
1175
|
|
- go (r:rhs) (AbsDmd:unfs) = r : go rhs unfs
|
|
1176
|
|
- go (r:rhs) (_:unfs) = r : go rhs unfs
|
|
|
1183
|
+ go (r:rhs) (u:unfs) = lubUBglbLBDmd r u : go rhs unfs
|
|
1177
|
1184
|
|
|
1178
|
1185
|
-- | The result type after applying 'idArity' many arguments. Returns 'Nothing'
|
|
1179
|
1186
|
-- when the type doesn't have exactly 'idArity' many arrows.
|
| ... |
... |
@@ -1555,7 +1562,7 @@ Wrinkles: |
|
1555
|
1562
|
error instead of the `really important message`.
|
|
1556
|
1563
|
|
|
1557
|
1564
|
(W3) The SOLUTION above handles /free variables/ of stable unfoldings, but
|
|
1558
|
|
- what about /arguments/? Consider (#25965)
|
|
|
1565
|
+ what about /arguments/? Consider (#26416)
|
|
1559
|
1566
|
|
|
1560
|
1567
|
fromVector :: (Storable a, KnownNat n) => Vector a -> Vector a
|
|
1561
|
1568
|
fromVector v = ... (uses Storable dictionary) ...
|
| ... |
... |
@@ -1569,9 +1576,18 @@ Wrinkles: |
|
1569
|
1576
|
dictionary, leading to a segfault!
|
|
1570
|
1577
|
|
|
1571
|
1578
|
SOLUTION: in `dmdAnalRhsSig`, if the function has a stable unfolding,
|
|
1572
|
|
- analyse it and drop any AbsDmds which are not absent in the unfolding.
|
|
1573
|
|
- This is done by `combineUnfoldingDmds`. This ensures that if the unfolding
|
|
1574
|
|
- uses an argument, it won't be marked as absent.
|
|
|
1579
|
+ analyse it with `dmdAnal` and combine the resulting `DmdType` with the
|
|
|
1580
|
+ RHS's `DmdType`. This is done by `combineUnfoldingDmds`, which:
|
|
|
1581
|
+
|
|
|
1582
|
+ * For argument demands: combines them using `lubUBglbLBDmd`, which takes
|
|
|
1583
|
+ the glb (max) of lower bounds (strictness) and lub (max) of upper
|
|
|
1584
|
+ bounds (usage). See Note [Combining demands for stable unfoldings].
|
|
|
1585
|
+ This ensures that if the unfolding uses an argument, it won't be
|
|
|
1586
|
+ marked as absent, while preserving any strictness the RHS reveals.
|
|
|
1587
|
+
|
|
|
1588
|
+ * For free variable demands: combines them using `lubDmdEnv`. This
|
|
|
1589
|
+ replaces the `demandRoots` approach for stable unfoldings (though
|
|
|
1590
|
+ we still use `demandRoots` for RULES via `idRuleVars`).
|
|
1575
|
1591
|
|
|
1576
|
1592
|
Note [DmdAnal for DataCon wrappers]
|
|
1577
|
1593
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|