Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use reader for SetM on GHC #1103

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

meooow25
Copy link
Contributor

@meooow25 meooow25 commented Feb 1, 2025

This is to avoid passing around the visited array in dfs' go.

Also add a bang on g, so that dfs is strict in g on non-GHC as it is on GHC.

Closes #1102


Core before:

Expand
-- RHS size: {terms: 241, types: 183, coercions: 0, joins: 1/6}
$wdfs [InlPrag=[2]]
  :: Vertex -> Vertex -> Array# [Vertex] -> [Vertex] -> [Tree Vertex]
[GblId[StrictWorker([!, !, ~, !])],
 Arity=4,
 Str=<1L><1L><L><1L>,
 Unf=OtherCon []]
$wdfs
  = \ (ww_sbqZ :: Vertex)
      (ww1_sbr0 :: Vertex)
      (ww2_sbr2 :: Array# [Vertex])
      (vs0_sbr4 :: [Vertex]) ->
      runRW#
        @LiftedRep
        @[Tree Vertex]
        (\ (s_aaG5 [OS=OneShot] :: State# RealWorld) ->
           case ww_sbqZ of { I# m_iaGP ->
           case ww1_sbr0 of { I# n_iaGS ->
           join {
             $w$j_sbqV [InlPrag=[2], Dmd=1C(1,C(1,L))]
               :: Int# -> Int# -> [Tree Vertex]
             [LclId[JoinId(2)(Nothing)], Arity=2, Str=<L><L>, Unf=OtherCon []]
             $w$j_sbqV (x_sbqP [OS=OneShot] :: Int#)
                       (ww3_sbqS [OS=OneShot] :: Int#)
               = case <# x_sbqP 0# of {
                   __DEFAULT ->
                     let {
                       nbytes#_saSV :: Int#
                       [LclId]
                       nbytes#_saSV
                         = uncheckedIShiftL# (uncheckedIShiftRL# (+# x_sbqP 63#) 6#) 3# } in
                     case newByteArray# @RealWorld nbytes#_saSV s_aaG5 of
                     { (# ipv_aaGu, ipv1_aaGv #) ->
                     case setByteArray# @RealWorld ipv1_aaGv 0# nbytes#_saSV 0# ipv_aaGu
                     of s3#_aaGx
                     { __DEFAULT ->
                     letrec {
                       $sgo_sbDD [Occ=LoopBreaker,
                                  Dmd=SC(S,C(1,C(1,C(1,C(1,C(1,!P(L,L)))))))]
                         :: Int#
                            -> Int#
                            -> Int#
                            -> MutableByteArray# RealWorld
                            -> [Int]
                            -> State# RealWorld
                            -> (# State# RealWorld, [Tree Vertex] #)
                       [LclId[StrictWorker([~, ~, ~, ~, !])],
                        Arity=6,
                        Str=<L><L><L><L><1L><L>,
                        Unf=OtherCon []]
                       $sgo_sbDD
                         = \ (sc_sbDy :: Int#)
                             (sc1_sbDz :: Int#)
                             (sc2_sbDA :: Int#)
                             (sc3_sbDB :: MutableByteArray# RealWorld)
                             (sc4_sbDx :: [Int])
                             (eta_B1 [OS=OneShot] :: State# RealWorld) ->
                             case sc4_sbDx of {
                               [] -> (# eta_B1, [] @(Tree Vertex) #);
                               : v_a6eL vs_a6eM ->
                                 case v_a6eL of wild3_iaCR { I# i1_iaCV ->
                                 case <=# sc_sbDy i1_iaCV of {
                                   __DEFAULT -> case indegree1 i1_iaCV sc_sbDy sc1_sbDz of {};
                                   1# ->
                                     case <=# i1_iaCV sc1_sbDz of {
                                       __DEFAULT -> case indegree1 i1_iaCV sc_sbDy sc1_sbDz of {};
                                       1# ->
                                         let {
                                           y_ibcn :: Int#
                                           [LclId]
                                           y_ibcn = -# i1_iaCV sc_sbDy } in
                                         case <=# 0# y_ibcn of {
                                           __DEFAULT -> case lvl58_rbKc y_ibcn sc2_sbDA of {};
                                           1# ->
                                             case <# y_ibcn sc2_sbDA of {
                                               __DEFAULT -> case lvl58_rbKc y_ibcn sc2_sbDA of {};
                                               1# ->
                                                 case readWordArray#
                                                        @RealWorld
                                                        sc3_sbDB
                                                        (uncheckedIShiftRA# y_ibcn 6#)
                                                        eta_B1
                                                 of
                                                 { (# ipv2_aaCz, ipv3_aaCA #) ->
                                                 case and#
                                                        ipv3_aaCA
                                                        (uncheckedShiftL#
                                                           1##
                                                           (word2Int#
                                                              (and# (int2Word# y_ibcn) 63##)))
                                                 of {
                                                   __DEFAULT ->
                                                     $sgo_sbDD
                                                       sc_sbDy
                                                       sc1_sbDz
                                                       sc2_sbDA
                                                       sc3_sbDB
                                                       vs_a6eM
                                                       ipv2_aaCz;
                                                   0## ->
                                                     let {
                                                       j#_saSP :: Int#
                                                       [LclId]
                                                       j#_saSP = uncheckedIShiftRA# y_ibcn 6# } in
                                                     case readWordArray#
                                                            @RealWorld sc3_sbDB j#_saSP ipv2_aaCz
                                                     of
                                                     { (# ipv4_aaEg, ipv5_aaEh #) ->
                                                     case writeWordArray#
                                                            @RealWorld
                                                            sc3_sbDB
                                                            j#_saSP
                                                            (or#
                                                               ipv5_aaEh
                                                               (uncheckedShiftL#
                                                                  1##
                                                                  (word2Int#
                                                                     (and#
                                                                        (int2Word# y_ibcn) 63##))))
                                                            ipv4_aaEg
                                                     of s3#1_aaEn
                                                     { __DEFAULT ->
                                                     case <=# m_iaGP i1_iaCV of {
                                                       __DEFAULT ->
                                                         case indegree1 i1_iaCV m_iaGP n_iaGS of {};
                                                       1# ->
                                                         case <=# i1_iaCV n_iaGS of {
                                                           __DEFAULT ->
                                                             case indegree1 i1_iaCV m_iaGP n_iaGS
                                                             of {};
                                                           1# ->
                                                             case indexArray#
                                                                    @Lifted
                                                                    @[Vertex]
                                                                    ww2_sbr2
                                                                    (-# i1_iaCV m_iaGP)
                                                             of
                                                             { (# ipv6_iaEL #) ->
                                                             case $sgo_sbDD
                                                                    sc_sbDy
                                                                    sc1_sbDz
                                                                    sc2_sbDA
                                                                    sc3_sbDB
                                                                    ipv6_iaEL
                                                                    s3#1_aaEn
                                                             of
                                                             { (# ipv7_Xb, ipv8_Xc #) ->
                                                             case $sgo_sbDD
                                                                    sc_sbDy
                                                                    sc1_sbDz
                                                                    sc2_sbDA
                                                                    sc3_sbDB
                                                                    vs_a6eM
                                                                    ipv7_Xb
                                                             of
                                                             { (# ipv9_Xe, ipv10_Xf #) ->
                                                             (# ipv9_Xe,
                                                                : @(Tree Vertex)
                                                                  (Node @Vertex wild3_iaCR ipv8_Xc)
                                                                  ipv10_Xf #)
                                                             }
                                                             }
                                                             }
                                                         }
                                                     }
                                                     }
                                                     }
                                                 }
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 }
                             }; } in
                     case $sgo_sbDD m_iaGP n_iaGS ww3_sbqS ipv1_aaGv vs0_sbr4 s3#_aaGx
                     of
                     { (# ipv2_aaG7, ipv3_aaG8 #) ->
                     ipv3_aaG8
                     }
                     }
                     };
                   1# -> case lvl56_rbKa of {}
                 } } in
           case <=# m_iaGP n_iaGS of {
             __DEFAULT -> jump $w$j_sbqV 0# 0#;
             1# ->
               let {
                 x_ibb6 :: Int#
                 [LclId]
                 x_ibb6 = +# (-# n_iaGS m_iaGP) 1# } in
               jump $w$j_sbqV x_ibb6 x_ibb6
           }
           }
           })

-- RHS size: {terms: 10, types: 11, coercions: 0, joins: 0/0}
dfs [InlPrag=[2]] :: Graph -> [Vertex] -> [Tree Vertex]
[GblId,
 Arity=2,
 Str=<1!P(1L,1L,A,L)><1L>,
 Unf=Unf{Src=StableSystem, TopLvl=True,
         Value=True, ConLike=True, WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
         Tmpl= \ (g_sbqX [Occ=Once1!] :: Graph)
                 (vs0_sbr4 [Occ=Once1] :: [Vertex]) ->
                 case g_sbqX of
                 { Array ww_sbqZ [Occ=Once1] ww1_sbr0 [Occ=Once1] _ [Occ=Dead]
                         ww3_sbr2 [Occ=Once1] ->
                 $wdfs ww_sbqZ ww1_sbr0 ww3_sbr2 vs0_sbr4
                 }}]
dfs
  = \ (g_sbqX :: Graph) (vs0_sbr4 :: [Vertex]) ->
      case g_sbqX of { Array ww_sbqZ ww1_sbr0 ww2_sbr1 ww3_sbr2 ->
      $wdfs ww_sbqZ ww1_sbr0 ww3_sbr2 vs0_sbr4
      }

Core after:

Expand
-- RHS size: {terms: 186, types: 157, coercions: 0, joins: 1/5}
$wdfs [InlPrag=[2]]
  :: Int# -> Int# -> Array# [Vertex] -> [Vertex] -> [Tree Vertex]
[GblId[StrictWorker([~, ~, ~, !])],
 Arity=4,
 Str=<L><L><L><1L>,
 Unf=Unf{Src=<vanilla>, TopLvl=True,
         Value=True, ConLike=True, WorkFree=True, Expandable=True,
         Guidance=IF_ARGS [0 0 0 0] 533 0}]
$wdfs
  = \ (ww_sbkb :: Int#)
      (ww1_sbkf :: Int#)
      (ww2_sbki :: Array# [Vertex])
      (vs0_sbkk :: [Vertex]) ->
      runRW#
        @LiftedRep
        @[Tree Vertex]
        (\ (s_aav8 [OS=OneShot] :: State# RealWorld) ->
           join {
             $j1_sb7K [Dmd=1C(1,L)] :: Int# -> [Tree Vertex]
             [LclId[JoinId(1)(Nothing)], Arity=1, Str=<L>, Unf=OtherCon []]
             $j1_sb7K (x_ib59 [OS=OneShot] :: Int#)
               = case <# x_ib59 0# of {
                   __DEFAULT ->
                     let {
                       nbytes#_saMI :: Int#
                       [LclId]
                       nbytes#_saMI
                         = uncheckedIShiftL# (uncheckedIShiftRL# (+# x_ib59 63#) 6#) 3# } in
                     case newByteArray# @RealWorld nbytes#_saMI s_aav8 of
                     { (# ipv_aauw, ipv1_aaux #) ->
                     case setByteArray# @RealWorld ipv1_aaux 0# nbytes#_saMI 0# ipv_aauw
                     of s3#_aauz
                     { __DEFAULT ->
                     letrec {
                       go_saMK [Occ=LoopBreaker, Dmd=SC(S,C(1,!P(L,L)))]
                         :: [Int] -> STRep RealWorld [Tree Int]
                       [LclId, Arity=2, Str=<1L><L>, Unf=OtherCon []]
                       go_saMK
                         = \ (ds_d9Qc :: [Int]) (eta_B0 [OS=OneShot] :: State# RealWorld) ->
                             case ds_d9Qc of {
                               [] -> (# eta_B0, [] @(Tree Int) #);
                               : v_a6eJ vs_a6eK ->
                                 case v_a6eJ of wild3_iaxb { I# i1_iaxf ->
                                 case <=# ww_sbkb i1_iaxf of {
                                   __DEFAULT -> case dfs3 i1_iaxf ww_sbkb ww1_sbkf of {};
                                   1# ->
                                     case <=# i1_iaxf ww1_sbkf of {
                                       __DEFAULT -> case dfs3 i1_iaxf ww_sbkb ww1_sbkf of {};
                                       1# ->
                                         let {
                                           y_ib6q :: Int#
                                           [LclId]
                                           y_ib6q = -# i1_iaxf ww_sbkb } in
                                         case <=# 0# y_ib6q of {
                                           __DEFAULT -> case dfs2 y_ib6q x_ib59 of {};
                                           1# ->
                                             case <# y_ib6q x_ib59 of {
                                               __DEFAULT -> case dfs2 y_ib6q x_ib59 of {};
                                               1# ->
                                                 case readWordArray#
                                                        @RealWorld
                                                        ipv1_aaux
                                                        (uncheckedIShiftRA# y_ib6q 6#)
                                                        eta_B0
                                                 of
                                                 { (# ipv2_aawT, ipv3_aawU #) ->
                                                 case and#
                                                        ipv3_aawU
                                                        (uncheckedShiftL#
                                                           1##
                                                           (word2Int#
                                                              (and# (int2Word# y_ib6q) 63##)))
                                                 of {
                                                   __DEFAULT -> go_saMK vs_a6eK ipv2_aawT;
                                                   0## ->
                                                     let {
                                                       j#_saMY :: Int#
                                                       [LclId]
                                                       j#_saMY = uncheckedIShiftRA# y_ib6q 6# } in
                                                     case readWordArray#
                                                            @RealWorld ipv1_aaux j#_saMY ipv2_aawT
                                                     of
                                                     { (# ipv4_aayz, ipv5_aayA #) ->
                                                     case writeWordArray#
                                                            @RealWorld
                                                            ipv1_aaux
                                                            j#_saMY
                                                            (or#
                                                               ipv5_aayA
                                                               (uncheckedShiftL#
                                                                  1##
                                                                  (word2Int#
                                                                     (and#
                                                                        (int2Word# y_ib6q) 63##))))
                                                            ipv4_aayz
                                                     of s3#1_aayG
                                                     { __DEFAULT ->
                                                     case indexArray# @Lifted @[Int] ww2_sbki y_ib6q
                                                     of
                                                     { (# ipv6_iazQ #) ->
                                                     case go_saMK ipv6_iazQ s3#1_aayG of
                                                     { (# ipv7_Xc, ipv8_Xd #) ->
                                                     case go_saMK vs_a6eK ipv7_Xc of
                                                     { (# ipv9_Xf, ipv10_Xg #) ->
                                                     (# ipv9_Xf,
                                                        : @(Tree Int)
                                                          (Node @Int wild3_iaxb ipv8_Xd)
                                                          ipv10_Xg #)
                                                     }
                                                     }
                                                     }
                                                     }
                                                     }
                                                 }
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 }
                             }; } in
                     case go_saMK vs0_sbkk s3#_aauz of { (# ipv2_aava, ipv3_aavb #) ->
                     ipv3_aavb
                     }
                     }
                     };
                   1# -> case dfs1 of {}
                 } } in
           case <=# ww_sbkb ww1_sbkf of {
             __DEFAULT -> jump $j1_sb7K 0#;
             1# -> jump $j1_sb7K (+# (-# ww1_sbkf ww_sbkb) 1#)
           })

-- RHS size: {terms: 16, types: 15, coercions: 0, joins: 0/0}
dfs [InlPrag=[2]] :: Graph -> [Vertex] -> [Tree Vertex]
[GblId,
 Arity=2,
 Str=<1!P(1!P(L),1!P(L),A,L)><1L>,
 Unf=Unf{Src=StableSystem, TopLvl=True,
         Value=True, ConLike=True, WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
         Tmpl= \ (g_sbk7 [Occ=Once1!] :: Graph)
                 (vs0_sbkk [Occ=Once1] :: [Vertex]) ->
                 case g_sbk7 of
                 { Array ww_sbk9 [Occ=Once1!] ww1_sbkd [Occ=Once1!] _ [Occ=Dead]
                         ww3_sbki [Occ=Once1] ->
                 case ww_sbk9 of { I# ww4_sbkb [Occ=Once1] ->
                 case ww1_sbkd of { I# ww5_sbkf [Occ=Once1] ->
                 $wdfs ww4_sbkb ww5_sbkf ww3_sbki vs0_sbkk
                 }
                 }
                 }}]
dfs
  = \ (g_sbk7 :: Graph) (vs0_sbkk :: [Vertex]) ->
      case g_sbk7 of { Array ww_sbk9 ww1_sbkd ww2_sbkh ww3_sbki ->
      case ww_sbk9 of { I# ww4_sbtw ->
      case ww1_sbkd of { I# ww5_sbtz ->
      $wdfs ww4_sbtw ww5_sbtz ww3_sbki vs0_sbkk
      }
      }
      }

Interestingly, GHC got rid of one unnecessary bounds check where it previously didn't.


Benchmarks on GHC 9.10.1

Name                           Time - - - - - - - -    Allocated - - - - -
                                    A       B     %         A       B     %
dff.line,n=100                 2.1 μs  2.1 μs   -2%     12 KB   12 KB   +0%
dff.line,n=1000000             206 ms  201 ms   -2%    202 MB  202 MB   +0%
dff.maxDAG,n=15                634 ns  602 ns   -4%    1.8 KB  1.9 KB   +0%
dff.maxDAG,n=1500               16 ms   17 ms   +5%    276 KB  212 KB  -23%
dff.rand,n=100,m=1000          5.7 μs  5.3 μs   -5%     12 KB   12 KB   +0%
dff.rand,n=100,m=10000          53 μs   52 μs   -2%     12 KB   12 KB   +0%
dff.rand,n=10000,m=100000      1.7 ms  1.6 ms   +0%    1.9 MB  1.9 MB   +0%
dff.rand,n=100000,m=1000000     78 ms   83 ms   +5%     19 MB   19 MB   +0%
dff.star,n=100                 2.1 μs  2.0 μs   -1%     12 KB   12 KB   +0%
dff.star,n=1000000             105 ms   95 ms   -9%    178 MB  138 MB  -22%
dfs.line,n=100                 1.4 μs  1.4 μs   +2%    4.8 KB  4.8 KB   +0%
dfs.line,n=1000000             107 ms  104 ms   -2%    133 MB  133 MB   +0%
dfs.maxDAG,n=15                506 ns  487 ns   -3%    800 B   816 B    +2%
dfs.maxDAG,n=1500               15 ms   15 ms   +0%    168 KB  104 KB  -37%
dfs.rand,n=100,m=1000          4.9 μs  4.6 μs   -6%    4.8 KB  4.8 KB   +0%
dfs.rand,n=100,m=10000          47 μs   44 μs   -5%    4.8 KB  4.8 KB   +0%
dfs.rand,n=10000,m=100000      1.5 ms  1.5 ms   +1%    1.2 MB  1.2 MB   +0%
dfs.rand,n=100000,m=1000000     70 ms   75 ms   +6%     12 MB   12 MB   +0%
dfs.star,n=100                 1.3 μs  1.4 μs   +3%    4.8 KB  4.8 KB   +0%
dfs.star,n=1000000              77 ms   69 ms  -10%    109 MB   70 MB  -36%

Small changes in time are expected.
I don't understand why allocations seem to have reduced however.

This is to avoid passing around the visited array in dfs' go.

Also add a bang on g, so that dfs is strict in g on non-GHC as it is
on GHC.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider avoiding reader for SetM
1 participant