Note [ANF-ising literal string arguments]

GHC/CoreToStg/Prep.hs:1468 compiler 1 ticket

Consider a Core program like,

    data Foo = Foo Addr#
    foo = Foo "turtle"#

String literals are non-trivial, see 'GHC.Types.Literal.litIsTrivial', hence
they are non-atomic in STG.
With -O1, FloatOut is likely to have floated most of these strings to top-level,
not least to give CSE a chance to deduplicate strings early (before the
linker, that is).
(Notable exceptions seem to be applications of 'unpackAppendCString#'.)
But with -O0, there is no FloatOut, so CorePrep must do the ANFisation to

    s = "turtle"#
    foo = Foo s

(String literals are the only kind of binding allowed at top-level and hence
their `FloatInfo` is `TopLvlFloatable`.)

This appears to lead to bad code if the arg is under a lambda, because CorePrep
doesn't float out of RHSs, e.g., (T23270)

    foo x = ... patError "turtle"# ...
==> foo x = ... case "turtle"# of s { __DEFAULT -> petError s } ...

This looks bad because it evals an HNF on every call.
But actually, it doesn't, because "turtle"# is already an HNF. Here is the Cmm:

  [section ""cstring" . cB4_str" {
       cB4_str:
           I8[] "turtle"
   }
  ...
  _sAG::I64 = cB4_str;
  R2 = _sAG::I64;
  Sp = Sp + 8;
  call Control.Exception.Base.patError_info(R2) args: 8, res: 0, upd: 8;

Wrinkles:

(FS1) We detect string literals in `cpeBind Rec{}` and float them out anyway;
      otherwise we'd try to bind a string literal in a letrec, violating
      Note [Core letrec invariant]. Since we know that literals don't have
      free variables, we float further.
      Arguably, we could just as well relax the letrec invariant for
      string literals, or anthing that is a value (lifted or not).
      This is tracked in #24036.

References 1

Referenced by 2