Skip to content

Join point wrapper not inlined

Consider

loop :: Int -> Int -> (Int, ())
loop x y = go x
  where
    go x = if x > y then (x, ()) else go (x*2)

Compile that with -O2 and get

loop
  = \ (x_aXE :: Int) (y_aXF :: Int) ->
      join {
        $wgo_s2sP [InlPrag=NOUSERINLINE[2], Dmd=<C(S),1*C1(U(U,U))>]
          :: GHC.Prim.Int# -> (Int, ())
        [LclId[JoinId(1)], Arity=1, Str=<L,U>m, Unf=OtherCon []]
        $wgo_s2sP (ww_s2sN [OS=OneShot] :: GHC.Prim.Int#)
          = case y_aXF of { GHC.Types.I# y1_a2rI ->
            case GHC.Prim.># ww_s2sN y1_a2rI of {
              __DEFAULT ->
                joinrec {
                  $wgo1_X2t9 [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
                    :: GHC.Prim.Int# -> (Int, ())
                  [LclId[JoinId(1)], Arity=1, Str=<L,U>m, Unf=OtherCon []]
                  $wgo1_X2t9 (ww1_X2t8 :: GHC.Prim.Int#)
                    = case GHC.Prim.># ww1_X2t8 y1_a2rI of {
                        __DEFAULT -> jump $wgo1_X2t9 (GHC.Prim.*# ww1_X2t8 2#);
                        1# -> (GHC.Types.I# ww1_X2t8, GHC.Tuple.())
                      }; } in
                jump $wgo1_X2t9 (GHC.Prim.*# ww_s2sN 2#);
              1# -> (GHC.Types.I# ww_s2sN, GHC.Tuple.())
            }
            } } in
      join {
        go_s2se [InlPrag=NOUSERINLINE[2], Dmd=<C(S),1*C1(U(U,U))>]
          :: Int -> (Int, ())
        [LclId[JoinId(1)],
         Arity=1,
         Str=<S,1*U(U)>m,
         Unf=Unf{Src=InlineStable, TopLvl=False, Value=True, ConLike=True,
                 WorkFree=True, Expandable=True,
                 Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False)
                 Tmpl= \ (w_s2sK [Occ=Once!] :: Int) ->
                         case w_s2sK of { GHC.Types.I# ww1_s2sN [Occ=Once] ->
                         jump $wgo_s2sP ww1_s2sN
                         }}]
        go_s2se (w_s2sK [OS=OneShot] :: Int)
          = case w_s2sK of { GHC.Types.I# ww1_s2sN ->
            jump $wgo_s2sP ww1_s2sN
            } } in
      jump go_s2se x_aXE

I'd expected something like

loop
  = \ (x_aXE :: Int) (y_aXF :: Int) ->
      join {
        $wgo_s2sP [InlPrag=NOUSERINLINE[2], Dmd=<C(S),1*C1(U(U,U))>]
          :: GHC.Prim.Int# -> (Int, ())
        [LclId[JoinId(1)], Arity=1, Str=<L,U>m, Unf=OtherCon []]
        $wgo_s2sP (ww_s2sN [OS=OneShot] :: GHC.Prim.Int#)
          = case y_aXF of { GHC.Types.I# y1_a2rI ->
            case GHC.Prim.># ww_s2sN y1_a2rI of {
              __DEFAULT ->
                joinrec {
                  $wgo1_X2t9 [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
                    :: GHC.Prim.Int# -> (Int, ())
                  [LclId[JoinId(1)], Arity=1, Str=<L,U>m, Unf=OtherCon []]
                  $wgo1_X2t9 (ww1_X2t8 :: GHC.Prim.Int#)
                    = case GHC.Prim.># ww1_X2t8 y1_a2rI of {
                        __DEFAULT -> jump $wgo1_X2t9 (GHC.Prim.*# ww1_X2t8 2#);
                        1# -> (GHC.Types.I# ww1_X2t8, GHC.Tuple.())
                      }; } in
                jump $wgo1_X2t9 (GHC.Prim.*# ww_s2sN 2#);
              1# -> (GHC.Types.I# ww_s2sN, GHC.Tuple.())
            }
            } } in
      case x_aXE of { GHC.Types.I# ww1_s2sN ->
      jump $wgo_s2sP ww1_s2sN
      }

that coincides with simply inlining the join point wrapper go. I wonder why we don't inline it.

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