Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,868
    • Issues 4,868
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 456
    • Merge requests 456
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #21148
Closed
Open
Created Feb 28, 2022 by Sebastian Graf@sgraf812Developer

Exit join points inhibit CPR

Consider

f :: Int -> IO Int
f x = return $! sum [0..x]
{-# NOINLINE f #-}

I would expect CPR to unbox the nested Int. Yet it doesn't. Here's the Core after CPR analysis:

f_s15n
  = \ (x_aup [Dmd=1!L] :: Int)
      (eta_B0 [OS=OneShot] :: GHC.Prim.State# GHC.Prim.RealWorld) ->
      case x_aup of { GHC.Types.I# ipv_sP7 ->
      case GHC.Prim.># 0# ipv_sP7 of {
        __DEFAULT ->
          join {
            $j_s15t [Dmd=SCS(C1(!L))]
              :: GHC.Prim.Int#
                 -> Int -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #)
            [LclId[JoinId(2)(Nothing)], Arity=2, Str=<A><L>, Cpr=1]
            $j_s15t _ [Occ=Dead, Dmd=A, OS=OneShot]
                    (vx_aP2 [OS=OneShot]
                       :: Int
                       Unf=OtherCon [])
              = (# eta_B0, vx_aP2 #) } in
          joinrec {
            go3_a153 [Occ=LoopBreaker, Dmd=SCS(C1(!L))]
              :: GHC.Prim.Int#
                 -> Int -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #)
            [LclId[JoinId(2)(Nothing)],
             Arity=2,
             Str=<L><1!L> {s15t->SCS(C1(!L))},
             Cpr=1,
             Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
                     WorkFree=True, Expandable=True, Guidance=IF_ARGS [0 20] 66 0}]
            go3_a153 (x_a154 :: GHC.Prim.Int#)
                     (v_a13a [Dmd=1!L, OS=OneShot] :: Int)
              = case v_a13a of { GHC.Types.I# ipv_s14C ->
                case GHC.Prim.==# x_a154 ipv_sP7 of {
                  __DEFAULT ->
                    jump go3_a153
                      (GHC.Prim.+# x_a154 1#)
                      (GHC.Types.I# (GHC.Prim.+# ipv_s14C x_a154));
                  1# ->
                    let {
                      ipv_s158 :: GHC.Prim.Int#
                      [LclId,
                       Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False,
                               WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 1 0}]
                      ipv_s158 = GHC.Prim.+# ipv_s14C x_a154 } in
                    jump $j_s15t ipv_s158 (GHC.Types.I# ipv_s158)
                }
                }; } in
          jump go3_a153 0# lvl_s15p;
        1# -> (# eta_B0, lvl_s15p #)
      }
      }

Note that the single jump to $j_s15t passes the integer boxed. Unfortunately, we don't see that in the join body. (And neither do we have the SubDemand vocabulary that a call is with a certain boxity in the argument.)

As a result, we can't unbox the nestedly returned Int.

The short-term fix is simple: Inline $j. IMO its existence does more harm than good.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking