Note [Call-by-value for worker args]

GHC/Core/Utils.hs:2811 compiler

If we unbox a constructor with strict fields we want to
preserve the information that some of the arguments came
out of strict fields and therefore should be already properly
tagged, however we can't express this directly in core.

Instead what we do is generate a worker like this:

  data T = MkT A !B

  foo = case T of MkT a b -> $wfoo a b

  $wfoo a b = case b of b' -> rhs[b/b']

This makes the worker strict in b causing us to use a more efficient
calling convention for `b` where the caller needs to ensure `b` is
properly tagged and evaluated before it's passed to $wfoo. See Note [CBV Function Ids].

Usually the argument will be known to be properly tagged at the call site so there is
no additional work for the caller and the worker can be more efficient since it can
assume the presence of a tag.

This is especially true for recursive functions like this:
    myPred expect it's argument properly tagged
    myPred !x = ...

    loop :: MyPair -> Int
    loop (MyPair !x !y) =
        case x of
            A -> 1
            B -> 2
            _ -> loop (MyPair (myPred x) (myPred y))

Here we would ordinarily not be strict in y after unboxing.
However if we pass it as a regular argument then this means on
every iteration of loop we will incur an extra seq on y before
we can pass it to `myPred` which isn't great! That is in STG after
tag inference we get:

    Rec {
    Find.$wloop [InlPrag=[2], Occ=LoopBreaker]
      :: Find.MyEnum -> Find.MyEnum -> GHC.Prim.Int#
    [GblId[StrictWorker([!, ~])],
    Arity=2,
    Str=<1L><ML>,
    Unf=OtherCon []] =
        {} \r [x y]
            case x<TagProper> of x' [Occ=Once1] {
              __DEFAULT ->
                  case y of y' [Occ=Once1] {
                  __DEFAULT ->
                  case Find.$wmyPred y' of pred_y [Occ=Once1] {
                  __DEFAULT ->
                  case Find.$wmyPred x' of pred_x [Occ=Once1] {
                  __DEFAULT -> Find.$wloop pred_x pred_y;
                  };
                  };
              Find.A -> 1#;
              Find.B -> 2#;
            };
    end Rec }

Here comes the tricky part: If we make $wloop strict in both x/y and we get:

    Rec {
    Find.$wloop [InlPrag=[2], Occ=LoopBreaker]
      :: Find.MyEnum -> Find.MyEnum -> GHC.Prim.Int#
    [GblId[StrictWorker([!, !])],
    Arity=2,
    Str=<1L><!L>,
    Unf=OtherCon []] =
        {} \r [x y]
            case y<TagProper> of y' [Occ=Once1] { __DEFAULT ->
            case x<TagProper> of x' [Occ=Once1] {
              __DEFAULT ->
                  case Find.$wmyPred y' of pred_y [Occ=Once1] {
                  __DEFAULT ->
                  case Find.$wmyPred x' of pred_x [Occ=Once1] {
                  __DEFAULT -> Find.$wloop pred_x pred_y;
                  };
                  };
              Find.A -> 1#;
              Find.B -> 2#;
            };
    end Rec }

Here both x and y are known to be tagged in the function body since we pass strict worker args using unlifted cbv.
This means the seqs on x and y both become no-ops and compared to the first version the seq on `y` disappears at runtime.

The downside is that the caller of $wfoo potentially has to evaluate `y` once if we can't prove it isn't already evaluated.
But y coming out of a strict field is in WHNF so safe to evaluated. And most of the time it will be properly tagged+evaluated
already at the call site because of the EPT Invariant! See Note [EPT enforcement] for more in this.
This makes GHC itself around 1% faster despite doing slightly more work! So this is generally quite good.

We only apply this when we think there is a benefit in doing so however. There are a number of cases in which
it would be useless to insert an extra seq. ShouldStrictifyIdForCbv tries to identify these to avoid churn in the
simplifier. See Note [Which Ids should be strictified] for details on this.

References 3

Referenced by 6