From b36ee57bfbecc628b7f0919e1e59b7066495034f Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Tue, 26 Mar 2024 17:36:47 +0100
Subject: [PATCH] JS: reenable h$appendToHsString optimization (#24495)

The optimization introducing h$appendToHsString wasn't kicking in
anymore (while it did in 9.8.1) because of the changes introduced in #23270 (7e0c8b3bab30).
This patch reenables the optimization by matching on case-expression, as
done in Cmm for unpackCString# standard thunks.

The test is also T24495 added in the next commits (two commits for ease
of backporting to 9.8).
---
 compiler/GHC/StgToJS/Apply.hs | 18 ------------------
 compiler/GHC/StgToJS/Expr.hs  | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/compiler/GHC/StgToJS/Apply.hs b/compiler/GHC/StgToJS/Apply.hs
index 9ec188715d80..5a6ff33692e9 100644
--- a/compiler/GHC/StgToJS/Apply.hs
+++ b/compiler/GHC/StgToJS/Apply.hs
@@ -46,7 +46,6 @@ import GHC.StgToJS.Rts.Types
 import GHC.StgToJS.Stack
 import GHC.StgToJS.Ids
 
-import GHC.Types.Literal
 import GHC.Types.Id
 import GHC.Types.Id.Info
 import GHC.Types.CostCentre
@@ -60,7 +59,6 @@ import GHC.Core.TyCon
 import GHC.Core.DataCon
 import GHC.Core.Type hiding (typeSize)
 
-import GHC.Utils.Encoding
 import GHC.Utils.Misc
 import GHC.Utils.Monad
 import GHC.Utils.Panic
@@ -100,22 +98,6 @@ genApp
   -> G (JStgStat, ExprResult)
 genApp ctx i args
 
-    -- Case: unpackCStringAppend# "some string"# str
-    --
-    -- Generates h$appendToHsStringA(str, "some string"), which has a faster
-    -- decoding loop.
-    | [StgLitArg (LitString bs), x] <- args
-    , [top] <- concatMap typex_expr (ctxTarget ctx)
-    , getUnique i == unpackCStringAppendIdKey
-    , d <- utf8DecodeByteString bs
-    = do
-        prof <- csProf <$> getSettings
-        let profArg = if prof then [jCafCCS] else []
-        a <- genArg x
-        return ( top |= app "h$appendToHsStringA" (toJExpr d : a ++ profArg)
-               , ExprInline
-               )
-
     -- let-no-escape
     | Just n <- ctxLneBindingStackSize ctx i
     = do
diff --git a/compiler/GHC/StgToJS/Expr.hs b/compiler/GHC/StgToJS/Expr.hs
index 7b6f20a2b836..90c4a45e8daf 100644
--- a/compiler/GHC/StgToJS/Expr.hs
+++ b/compiler/GHC/StgToJS/Expr.hs
@@ -60,11 +60,13 @@ import GHC.Types.Var.Set
 import GHC.Types.Id
 import GHC.Types.Unique.FM
 import GHC.Types.RepType
+import GHC.Types.Literal
 
 import GHC.Stg.Syntax
 import GHC.Stg.Utils
 
 import GHC.Builtin.PrimOps
+import GHC.Builtin.Names
 
 import GHC.Core hiding (Var)
 import GHC.Core.TyCon
@@ -73,6 +75,7 @@ import GHC.Core.Opt.Arity (isOneShotBndr)
 import GHC.Core.Type hiding (typeSize)
 
 import GHC.Utils.Misc
+import GHC.Utils.Encoding
 import GHC.Utils.Monad
 import GHC.Utils.Panic
 import GHC.Utils.Outputable (ppr, renderWithContext, defaultSDocContext)
@@ -555,6 +558,36 @@ genCase :: HasDebugCallStack
         -> LiveVars
         -> G (JStgStat, ExprResult)
 genCase ctx bnd e at alts l
+  -- For:      unpackCStringAppend# "some string"# str
+  -- Generate: h$appendToHsStringA(str, "some string")
+  --
+  -- The latter has a faster decoding loop.
+  --
+  -- Since #23270 and 7e0c8b3bab30, literals strings aren't STG atoms and we
+  -- need to match the following instead:
+  --
+  --    case "some string"# of b {
+  --      DEFAULT -> unpackCStringAppend# b str
+  --    }
+  --
+  -- Wrinkle: it doesn't kick in when literals are floated out to the top level.
+  --
+  | StgLit (LitString bs) <- e
+  , [GenStgAlt DEFAULT _ rhs] <- alts
+  , StgApp i args <- rhs
+  , getUnique i == unpackCStringAppendIdKey
+  , [StgVarArg b',x] <- args
+  , bnd == b'
+  , d <- utf8DecodeByteString bs
+  , [top] <- concatMap typex_expr (ctxTarget ctx)
+  = do
+      prof <- csProf <$> getSettings
+      let profArg = if prof then [jCafCCS] else []
+      a <- genArg x
+      return ( top |= app "h$appendToHsStringA" (toJExpr d : a ++ profArg)
+             , ExprInline
+             )
+
   | isInlineExpr e = do
       bndi <- identsForId bnd
       let ctx' = ctxSetTop bnd
-- 
GitLab