Zubin pushed to branch wip/26416 at Glasgow Haskell Compiler / GHC Commits: 63cec3b4 by Zubin Duggal at 2026-03-12T16:13:59+05:30 review - - - - - 2 changed files: - compiler/GHC/Core/Opt/DmdAnal.hs - compiler/GHC/Types/Demand.hs Changes: ===================================== compiler/GHC/Core/Opt/DmdAnal.hs ===================================== @@ -1111,8 +1111,17 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs full_dmd_ty = addUnfoldingDemands env rhs_sd id rhs_dmd_ty DmdType full_rhs_env combined_rhs_dmds = full_dmd_ty - (final_rhs_dmds, final_rhs) = finaliseArgBoxities env id ww_arity - combined_rhs_dmds (de_div full_rhs_env) rhs' + final_rhs_dmds = finaliseArgBoxities env id ww_arity + combined_rhs_dmds (de_div full_rhs_env) rhs' + + -- Attach the final demands to the lambda binders of the RHS. + -- IMPORTANT: The lambda binders of final_rhs must carry the final demand + -- info, because worker/wrapper drives decisions from the idDemandInfo on + -- the lambdas (see mkWwstr_one), NOT from the strictness signature of the + -- function. So the demands must reflect both the unfolding combination + -- (from addUnfoldingDemands) and the boxity finalisation (from + -- finaliseArgBoxities). + final_rhs = set_lam_dmds final_rhs_dmds rhs' dmd_sig_arity = ww_arity + strictCallArity body_sd sig = mkDmdSigForArity dmd_sig_arity (DmdType sig_env final_rhs_dmds) @@ -2053,29 +2062,20 @@ positiveTopBudget (MkB n _) = n >= 0 finaliseArgBoxities :: AnalEnv -> Id -> Arity -> [Demand] -> Divergence - -> CoreExpr -> ([Demand], CoreExpr) + -> CoreExpr -> [Demand] -- POSTCONDITION: --- If: (dmds', rhs') = finaliseArgBoxitities ... dmds .. rhs +-- If: dmds' = finaliseArgBoxities ... dmds .. rhs -- Then: -- dmds' is the same as dmds (including length), except for boxity info --- rhs' is the same as rhs, except that the idDemandInfo on the outer --- lambda binders now includes the same finalised boxity info as dmds' -- NB: For join points, length dmds might be greater than ww_arity --- --- IMPORTANT: The lambda binders of rhs' must carry the final demand info, --- because worker/wrapper drives decisions from the idDemandInfo on the lambdas --- (see mkWwstr_one), NOT from the strictness signature of the function. --- So the demands must reflect both the unfolding combination (from --- addUnfoldingDemands) and the boxity finalisation done here. +-- NB: rhs is needed only to count visible binders. finaliseArgBoxities env fn ww_arity arg_dmds div rhs -- Check for an OPAQUE function: see Note [OPAQUE pragma] -- In that case, trim off all boxity info from argument demands - -- and demand info on lambda binders -- See Note [The OPAQUE pragma and avoiding the reboxing of arguments] | isOpaquePragma (idInlinePragma fn) - , let trimmed_arg_dmds = map trimBoxity arg_dmds - = (trimmed_arg_dmds, set_lam_dmds trimmed_arg_dmds rhs) + = map trimBoxity arg_dmds -- Check that we have enough visible binders to match the -- ww arity; if not, we won't do worker/wrapper @@ -2086,7 +2086,7 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs -- It's a bit of a corner case. Anyway for now we pass on the -- unadulterated demands from the RHS, without any boxity trimming. | ww_arity > count isId bndrs - = (arg_dmds, rhs) + = arg_dmds -- The normal case | otherwise @@ -2095,10 +2095,7 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs -- , text "max" <+> ppr max_wkr_args -- , text "dmds before:" <+> ppr (map idDemandInfo (filter isId bndrs)) -- , text "dmds after: " <+> ppr arg_dmds' ]) $ - (arg_dmds', set_lam_dmds arg_dmds' rhs) - -- set_lam_dmds: we must attach the final boxities to the lambda-binders - -- of the function, both because that's kosher, and because CPR analysis - -- uses the info on the binders directly. + arg_dmds' where opts = ae_opts env (bndrs, _body) = collectBinders rhs @@ -2186,18 +2183,18 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs | positiveTopBudget bg_inner' = (bg_inner', dmd') | otherwise = (bg_inner, trimBoxity dmd) - set_lam_dmds :: [Demand] -> CoreExpr -> CoreExpr - -- Attach the demands to the outer lambdas of this expression - set_lam_dmds (dmd:dmds) (Lam v e) - | isTyVar v = Lam v (set_lam_dmds (dmd:dmds) e) - | otherwise = Lam (v `setIdDemandInfo` dmd) (set_lam_dmds dmds e) - set_lam_dmds dmds (Cast e co) = Cast (set_lam_dmds dmds e) co - -- This case happens for an OPAQUE function, which may look like - -- f = (\x y. blah) |> co - -- We give it strictness but no boxity (#22502) - set_lam_dmds _ e = e - -- In the OPAQUE case, the list of demands at this point might be - -- non-empty, e.g., when looking at a PAP. Hence don't panic (#22997). +set_lam_dmds :: [Demand] -> CoreExpr -> CoreExpr +-- Attach the demands to the outer lambdas of this expression +set_lam_dmds (dmd:dmds) (Lam v e) + | isTyVar v = Lam v (set_lam_dmds (dmd:dmds) e) + | otherwise = Lam (v `setIdDemandInfo` dmd) (set_lam_dmds dmds e) +set_lam_dmds dmds (Cast e co) = Cast (set_lam_dmds dmds e) co + -- This case happens for an OPAQUE function, which may look like + -- f = (\x y. blah) |> co + -- We give it strictness but no boxity (#22502) +set_lam_dmds _ e = e + -- In the OPAQUE case, the list of demands at this point might be + -- non-empty, e.g., when looking at a PAP. Hence don't panic (#22997). finaliseLetBoxity :: AnalEnv ===================================== compiler/GHC/Types/Demand.hs ===================================== @@ -874,10 +874,22 @@ because: * The optimised RHS may have had transformations applied that reveal strictness (e.g., inlining exposes a case on an argument). + Example: + RHS: x + Unfolding: head [x] + It's clear that the RHS is strict in `x`, but the demand analyser won't + spot that when it analyses the unfolding. * The optimised RHS may have had transformations applied that drop usage (e.g., a rewrite rule fires that doesn't use an argument, or a seq on a dictionary is dropped because dictionaries are known to terminate). + Example: + RHS: a + Unfolding: fst g + where `g` is in scope as `g = (a,b)`. + +See Note [Absence analysis for stable unfoldings and RULES] in +GHC.Core.Opt.DmdAnal for the broader context. When we inline the stable unfolding at a call site, we get the unfolding's behaviour, not the RHS's. So we must be conservative and combine the demands: @@ -894,9 +906,6 @@ behaviour, not the RHS's. So we must be conservative and combine the demands: So for cardinality bounds [l1..u1] from RHS and [l2..u2] from unfolding, we compute [max(l1,l2)..max(u1,u2)]. - -See Note [Absence analysis for stable unfoldings and RULES] in GHC.Core.Opt.DmdAnal -for the broader context. -} -- | Takes the maximum of both the lower and upper bound of two 'Card's. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/63cec3b4827d4ddaf3ec43aea15c619f... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/63cec3b4827d4ddaf3ec43aea15c619f... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Zubin (@wz1000)