From ca1e636a9c4d8947a680c36167683616d09f4625 Mon Sep 17 00:00:00 2001
From: Rodrigo Mesquita <rodrigo.m.mesquita@gmail.com>
Date: Fri, 14 Jul 2023 16:58:55 +0100
Subject: [PATCH] Improve Note [Binder-swap during float-out]

---
 compiler/GHC/Core/Opt/SetLevels.hs | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/compiler/GHC/Core/Opt/SetLevels.hs b/compiler/GHC/Core/Opt/SetLevels.hs
index bcd01bec04ab..ffa66b30288b 100644
--- a/compiler/GHC/Core/Opt/SetLevels.hs
+++ b/compiler/GHC/Core/Opt/SetLevels.hs
@@ -44,13 +44,33 @@
         case x of wild { p -> ...wild... }
    we substitute x for wild in the RHS of the case alternatives:
         case x of wild { p -> ...x... }
-   This means that a sub-expression involving x is not "trapped" inside the RHS.
+   This means that a sub-expression involving x is not "trapped" inside the RHS
+   (i.e. it can now be floated out, whereas if it mentioned wild it could not).
    And it's not inconvenient because we already have a substitution.
 
-  Note that this is EXACTLY BACKWARDS from the what the simplifier does.
-  The simplifier tries to get rid of occurrences of x, in favour of wild,
-  in the hope that there will only be one remaining occurrence of x, namely
-  the scrutinee of the case, and we can inline it.
+   For example, consider:
+
+      f x = letrec go y = case x of z { (a,b) -> ...(expensive z)... }
+              in ...
+
+   If we do the reverse binder-swap we get
+
+      f x = letrec go y = case x of z { (a,b) -> ...(expensive x)... }
+              in ...
+
+   and now we can float out:
+
+      f x = let t = expensive x
+              in letrec go y = case x of z { (a,b) -> ...(t)... }
+              in ...
+
+   Now (expensive x) is computed once, rather than once each time around the 'go' loop.
+
+   Note that this is EXACTLY BACKWARDS from the what the simplifier does.
+   The simplifier tries to get rid of occurrences of x, in favour of wild,
+   in the hope that there will only be one remaining occurrence of x, namely
+   the scrutinee of the case, and we can inline it.
+
 -}
 
 module GHC.Core.Opt.SetLevels (
-- 
GitLab