From 35587eba3feb609bc6de3a290e7e47641137f946 Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones <simon.peytonjones@gmail.com> Date: Thu, 26 Oct 2023 11:50:26 +0100 Subject: [PATCH] Fix a bug in tail calls with ticks See #24078 for the diagnosis. The change affects only the Tick case of occurrence analysis. It's a bit hard to test, so no regression test (yet anyway). --- compiler/GHC/Core/Opt/OccurAnal.hs | 46 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/compiler/GHC/Core/Opt/OccurAnal.hs b/compiler/GHC/Core/Opt/OccurAnal.hs index a4af26f1496a..38dad20c0a63 100644 --- a/compiler/GHC/Core/Opt/OccurAnal.hs +++ b/compiler/GHC/Core/Opt/OccurAnal.hs @@ -2493,32 +2493,34 @@ But it is not necessary to gather CoVars from the types of other binders. -} occAnal env (Tick tickish body) - | SourceNote{} <- tickish - = WUD usage (Tick tickish body') - -- SourceNotes are best-effort; so we just proceed as usual. - -- If we drop a tick due to the issues described below it's - -- not the end of the world. + = WUD usage' (Tick tickish body') + where + WUD usage body' = occAnal env body - | tickish `tickishScopesLike` SoftScope - = WUD (markAllNonTail usage) (Tick tickish body') + usage' + | tickish `tickishScopesLike` SoftScope + = usage -- For soft-scoped ticks (including SourceNotes) we don't want + -- to lose join-point-hood, so we don't mess with `usage` (#24078) - | Breakpoint _ _ ids _ <- tickish - = WUD (addManyOccs usage_lam (mkVarSet ids)) (Tick tickish body') - -- never substitute for any of the Ids in a Breakpoint + -- For a non-soft tick scope, we can inline lambdas only, so we + -- abandon tail calls, and do markAllInsideLam too: usage_lam + + | Breakpoint _ _ ids _ <- tickish + = -- Never substitute for any of the Ids in a Breakpoint + addManyOccs usage_lam (mkVarSet ids) + + | otherwise + = usage_lam - | otherwise - = WUD usage_lam (Tick tickish body') - where - (WUD usage body') = occAnal env body - -- for a non-soft tick scope, we can inline lambdas only usage_lam = markAllNonTail (markAllInsideLam usage) - -- TODO There may be ways to make ticks and join points play - -- nicer together, but right now there are problems: - -- let j x = ... in tick<t> (j 1) - -- Making j a join point may cause the simplifier to drop t - -- (if the tick is put into the continuation). So we don't - -- count j 1 as a tail call. - -- See #14242. + + -- TODO There may be ways to make ticks and join points play + -- nicer together, but right now there are problems: + -- let j x = ... in tick<t> (j 1) + -- Making j a join point may cause the simplifier to drop t + -- (if the tick is put into the continuation). So we don't + -- count j 1 as a tail call. + -- See #14242. occAnal env (Cast expr co) = let (WUD usage expr') = occAnal env expr -- GitLab