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