| ... |
... |
@@ -1106,8 +1106,17 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs |
|
1106
|
1106
|
|
|
1107
|
1107
|
WithDmdType rhs_dmd_ty rhs' = dmdAnal env rhs_sd rhs
|
|
1108
|
1108
|
DmdType rhs_env rhs_dmds = rhs_dmd_ty
|
|
|
1109
|
+
|
|
|
1110
|
+ -- See Note [Absence analysis for stable unfoldings and RULES]
|
|
|
1111
|
+ -- If there's a stable unfolding, we need to combine argument demands
|
|
|
1112
|
+ -- from the unfolding with those from the RHS, because the unfolding
|
|
|
1113
|
+ -- might use arguments that the (optimised) RHS doesn't.
|
|
|
1114
|
+ -- Any argument with a demand absent in one but not the other can
|
|
|
1115
|
+ -- be problematic, see #26416
|
|
|
1116
|
+ combined_rhs_dmds = combineUnfoldingDmds env rhs_sd id rhs_dmds
|
|
|
1117
|
+
|
|
1109
|
1118
|
(final_rhs_dmds, final_rhs) = finaliseArgBoxities env id ww_arity
|
|
1110
|
|
- rhs_dmds (de_div rhs_env) rhs'
|
|
|
1119
|
+ combined_rhs_dmds (de_div rhs_env) rhs'
|
|
1111
|
1120
|
|
|
1112
|
1121
|
dmd_sig_arity = ww_arity + strictCallArity body_sd
|
|
1113
|
1122
|
sig = mkDmdSigForArity dmd_sig_arity (DmdType sig_env final_rhs_dmds)
|
| ... |
... |
@@ -1144,6 +1153,27 @@ splitWeakDmds :: DmdEnv -> (DmdEnv, WeakDmds) |
|
1144
|
1153
|
splitWeakDmds (DE fvs div) = (DE sig_fvs div, weak_fvs)
|
|
1145
|
1154
|
where (!weak_fvs, !sig_fvs) = partitionVarEnv isWeakDmd fvs
|
|
1146
|
1155
|
|
|
|
1156
|
+-- | If there is a stable unfolding, don't let any demand be absent that
|
|
|
1157
|
+-- is also not absent in the unfolding
|
|
|
1158
|
+-- 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
|
|
|
1161
|
+ | not (isStableUnfolding unf)
|
|
|
1162
|
+ = rhs_dmds -- No stable unfolding, nothing to do
|
|
|
1163
|
+
|
|
|
1164
|
+ | 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
|
|
|
1170
|
+ where
|
|
|
1171
|
+ unf = realIdUnfolding id
|
|
|
1172
|
+ go rhs [] = rhs
|
|
|
1173
|
+ go [] _ = []
|
|
|
1174
|
+ go (AbsDmd:rhs) (u:unfs) = u : go rhs unfs
|
|
|
1175
|
+ go (r:rhs) (AbsDmd:unfs) = r : go rhs unfs
|
|
|
1176
|
+
|
|
1147
|
1177
|
-- | The result type after applying 'idArity' many arguments. Returns 'Nothing'
|
|
1148
|
1178
|
-- when the type doesn't have exactly 'idArity' many arrows.
|
|
1149
|
1179
|
resultType_maybe :: Id -> Maybe Type
|
| ... |
... |
@@ -1523,6 +1553,25 @@ Wrinkles: |
|
1523
|
1553
|
for `sg`, failing to unleash the signature and hence observed an absent
|
|
1524
|
1554
|
error instead of the `really important message`.
|
|
1525
|
1555
|
|
|
|
1556
|
+ (W3) The SOLUTION above handles /free variables/ of stable unfoldings, but
|
|
|
1557
|
+ what about /arguments/? Consider (#25965)
|
|
|
1558
|
+
|
|
|
1559
|
+ fromVector :: (Storable a, KnownNat n) => Vector a -> Vector a
|
|
|
1560
|
+ fromVector v = ... (uses Storable dictionary) ...
|
|
|
1561
|
+ {-# INLINABLE fromVector #-}
|
|
|
1562
|
+
|
|
|
1563
|
+ Suppose that the optimised RHS of `fromVector` somehow discards the use of
|
|
|
1564
|
+ the Storable dictionary, but the stable unfolding still uses it. Then the
|
|
|
1565
|
+ demand signature will say that the Storable dictionary argument is absent,
|
|
|
1566
|
+ and worker/wrapper will replace it with `LitRubbish`. But when the
|
|
|
1567
|
+ worker's unfolding is inlined, it will use that rubbish value as a real
|
|
|
1568
|
+ dictionary, leading to a segfault!
|
|
|
1569
|
+
|
|
|
1570
|
+ SOLUTION: in `dmdAnalRhsSig`, if the function has a stable unfolding,
|
|
|
1571
|
+ analyse it and drop any AbsDmds which are not absent in the unfolding.
|
|
|
1572
|
+ This is done by `combineUnfoldingDmds`. This ensures that if the unfolding
|
|
|
1573
|
+ uses an argument, it won't be marked as absent.
|
|
|
1574
|
+
|
|
1526
|
1575
|
Note [DmdAnal for DataCon wrappers]
|
|
1527
|
1576
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
1528
|
1577
|
We give DataCon wrappers a (necessarily flat) demand signature in
|
| ... |
... |
@@ -2046,8 +2095,11 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs |
|
2046
|
2095
|
|
|
2047
|
2096
|
arg_triples :: [(Type, StrictnessMark, Demand)]
|
|
2048
|
2097
|
arg_triples = take ww_arity $
|
|
2049
|
|
- [ (idType bndr, NotMarkedStrict, get_dmd bndr)
|
|
2050
|
|
- | bndr <- bndrs, isRuntimeVar bndr ]
|
|
|
2098
|
+ zipWith mk_triple
|
|
|
2099
|
+ [ bndr | bndr <- bndrs, isRuntimeVar bndr ]
|
|
|
2100
|
+ arg_dmds
|
|
|
2101
|
+ where
|
|
|
2102
|
+ mk_triple bndr dmd = (idType bndr, NotMarkedStrict, get_dmd dmd)
|
|
2051
|
2103
|
|
|
2052
|
2104
|
arg_dmds' = ww_arg_dmds ++ map trimBoxity (drop ww_arity arg_dmds)
|
|
2053
|
2105
|
-- If ww_arity < length arg_dmds, the leftover ones
|
| ... |
... |
@@ -2063,12 +2115,10 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs |
|
2063
|
2115
|
-- This is the budget initialisation step of
|
|
2064
|
2116
|
-- Note [Worker argument budget]
|
|
2065
|
2117
|
|
|
2066
|
|
- get_dmd :: Id -> Demand
|
|
2067
|
|
- get_dmd bndr
|
|
|
2118
|
+ get_dmd :: Demand -> Demand
|
|
|
2119
|
+ get_dmd dmd
|
|
2068
|
2120
|
| is_bot_fn = unboxDeeplyDmd dmd -- See Note [Boxity for bottoming functions],
|
|
2069
|
2121
|
| otherwise = dmd -- case (B)
|
|
2070
|
|
- where
|
|
2071
|
|
- dmd = idDemandInfo bndr
|
|
2072
|
2122
|
|
|
2073
|
2123
|
-- is_bot_fn: see Note [Boxity for bottoming functions]
|
|
2074
|
2124
|
is_bot_fn = div == botDiv
|