[GHC] #11731: Demand analysis: Thunk wrongly determined single-entry

GHC ghc-devs at haskell.org
Mon Mar 21 08:27:16 UTC 2016


#11731: Demand analysis: Thunk wrongly determined single-entry
-------------------------------------+-------------------------------------
        Reporter:  nomeata           |                Owner:
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by nomeata):

 {{{
     Entries      Alloc    Alloc'd     #Alloc     Single   Multiple  Non-
 void Arguments      STG Name
        4096          0      65536       2048          0       2048   0
 sat_s2vw{v} (main at main:GamtebMain) (thk,se) in r2uq
 }}}

 The relevant `-ddump-prep` code is this:
 {{{
                                       let {
                                         sat_s2vw [Occ=Once,
 Dmd=<L,1*U(U)>] :: GamtebType.Random
                                         [LclId, Str=DmdType] =
                                             \s srt:SRT:[r4K :->
 Utils.$wgenRand] []
                                                 case Utils.$wgenRand
 w_s2ux of _ [Occ=Dead] {
                                                   (#,#) ww5_s2vu
 [Occ=Once] _ [Occ=Dead] ->
                                                       ww5_s2vu;
                                                 };
                                       } in
                                         TransPort.$wtransPort
                                             lvl2_r2ut
                                             lvl2_r2ut
                                             lvl2_r2ut
                                             lvl2_r2ut
                                             lvl1_r2us
                                             lvl2_r2ut
                                             lvl1_r2us
                                             w1_s2uz
                                             ww2_s2vk
                                             lvl_r2ur
                                             sat_s2vw
                                             ww17_s2vn
                                             ww19_s2vp
                                             ww22_s2vs;
 }}}

 The relevant code for `$wtransPort` ist

 {{{
 TransPort.$wtransPort [InlPrag=[0], Occ=LoopBreaker]
   :: GamtebType.Coord
      -> GamtebType.Coord
      -> GamtebType.Coord
      -> GamtebType.Coord
      -> GamtebType.Coord
      -> GamtebType.Coord
      -> GamtebType.Weight
      -> GamtebType.Energy
      -> GamtebType.Indx
      -> GHC.Types.Int
      -> GamtebType.Random
      -> GamtebType.Prob
      -> GamtebType.Prob
      -> GHC.Prim.Double#
      -> (# [GamtebType.Result], [GamtebType.Stat] #)
 [GblId,
  Arity=14,
  Str=DmdType
 <L,U(U)><L,U(U)><L,U(U)><L,U(U)><L,U(U)><L,U(U)><L,U(U)><L,U(U)><L,U><L,U(U)><L,1*U(U)><L,U(U)><L,U(U)><S,U>,
  Unf=OtherCon []] =
     \r srt:SRT:[r4K :-> Utils.$wgenRand, r5x :-> Compton.$wcompton,
                 r5O :-> Pair.$wpair, r3Df :-> TransPort.$wtransPort,
                 r3Dr :-> lvl11_r3Dr] [ww_s3Dy
                                       ww1_s3Dz
                                       ww2_s3DA
                                       ww3_s3DB
                                       ww4_s3DC
                                       ww5_s3DD
                                       ww6_s3DE
                                       ww7_s3DF
                                       ww8_s3DG
                                       ww9_s3DH
                                       ww10_s3DI
                                       ww11_s3DJ
                                       ww12_s3DK
                                       ww13_s3DL]
         case Utils.$wgenRand ww10_s3DI of _ [Occ=Dead] {
           (#,#) ww15_s3DN [Occ=Once!] ww16_s3DO ->
 }}}

 Note how the strictness signature say that the `Random` argument is used
 at most once (`1*U(U)`). The call to `$wgenRand` is indeed the only use of
 `ww10_s3DI`. So here is the code of `$wgenRand`:

 {{{
 Utils.$wgenRand [InlPrag=[0]]
   :: GamtebType.Random -> (# GamtebType.Random, GamtebType.Random #)
 [GblId, Arity=1, Str=DmdType <L,U(U)>, Unf=OtherCon []] =
     \r srt:SRT:[015 :-> GHC.Integer.Type.timesInteger,
                 017 :-> GHC.Integer.Type.negateInteger,
                 01j :-> GHC.Integer.Type.divInteger,
                 01x :-> GHC.Integer.Type.shiftLInteger] [w_s3BX]
         let {
           sat_s3CT [Occ=Once] :: GamtebType.Random
           [LclId, Str=DmdType] =
               \u srt:SRT:[015 :-> GHC.Integer.Type.timesInteger,
                           017 :-> GHC.Integer.Type.negateInteger,
                           01j :-> GHC.Integer.Type.divInteger,
                           01x :-> GHC.Integer.Type.shiftLInteger] []
                   case w_s3BX of _ [Occ=Dead] {
                     GHC.Types.D# y_s3Cs [Occ=Once] ->
 ...
                   }; } in
         let {
           sat_s3Cq [Occ=Once] :: GamtebType.Random
           [LclId, Str=DmdType] =
               \u srt:SRT:[015 :-> GHC.Integer.Type.timesInteger,
                           017 :-> GHC.Integer.Type.negateInteger,
                           01j :-> GHC.Integer.Type.divInteger,
                           01x :-> GHC.Integer.Type.shiftLInteger] []
                   case w_s3BX of _ [Occ=Dead] {
                     GHC.Types.D# y_s3BZ [Occ=Once] ->
 ...
                   };
         } in  (#,#) [sat_s3Cq sat_s3CT];
 }}}

 So `$wgenRand` may evaluate its argument more than once (as its strictness
 signature says). On what grounds does `$wtransPort` then claim the
 argument is used at most once?

 Now if the argument to `$wgenRand` were a complex expression, this would
 be valid reasoning, as it would be let-bound and then shared. But trivial
 expressions, when passed as arguments, are _not_ shared at this point, so
 the information that the argument may be used multiple times should be
 propagated out.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11731#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list