Ticket #4945 (closed bug: fixed)

Opened 2 years ago

Last modified 2 years ago

Another SpecConstr infelicity

Reported by: batterseapower Owned by:
Priority: normal Milestone: 7.0.2
Component: Compiler Version: 7.0.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Runtime performance bug Difficulty:
Test Case: simplCore/should_compile/T4945 Blocked By:
Blocking: Related Tickets:

Description

I'm beginning to sound like a broken record, but SpecConstr still doesn't seem to be right! The last problem has been fixed, but I've found a new one.

Please observe the output of compiling the attached code with:

./ghc -fforce-recomp -c -dverbose-core2core -O2 -fno-liberate-case STUArray-Rewrite2.hs

In the output of SpecConstr we have a local letrec:

(letrec {
   $wa_s1G7 [Occ=LoopBreaker]
     :: forall s_aJm.
        Data.Array.Base.STUArray
          s_aJm GHC.Types.Int GHC.Types.Int
        -> GHC.Prim.Int#
        -> GHC.Prim.State# s_aJm
        -> (# GHC.Prim.State# s_aJm, () #)
   [LclId, Arity=3, Str=DmdType LLL]
   $wa_s1G7 =
     \ (@ s_aJm)
       (w_s1FS
          :: Data.Array.Base.STUArray
               s_aJm GHC.Types.Int GHC.Types.Int)
       (ww_s1FV :: GHC.Prim.Int#)
       (w_s1FX :: GHC.Prim.State# s_aJm) ->
       case GHC.Prim.># ww_s1FV ww_s1FN
       of wild_Xj [Dmd=Just A] {
         GHC.Types.False ->
           case w_s1FS
           of wild_aTj [Dmd=Just L]
           { Data.Array.Base.STUArray ds1_aTl [Dmd=Just U]
                                      ds2_aTm [Dmd=Just U]
                                      n_aTn [Dmd=Just U(L)]
                                      ds3_aTo [Dmd=Just A] ->
           case n_aTn
           of wild_aTs [Dmd=Just A]
           { GHC.Types.I# x_aTu [Dmd=Just L] ->
           case $wa_s1G0
                  @ s_aJm
                  w_s1FS
                  (GHC.Types.I# ww_s1FV)
                  0
                  (GHC.Prim.-# x_aTu 1)
                  w_s1FX
           of wild_XUw [Dmd=Just A]
           { (# new_s_XUB [Dmd=Just L], r_XUD [Dmd=Just A] #) ->
           $wa_s1G7
             @ s_aJm w_s1FS (GHC.Prim.+# ww_s1FV 1) new_s_XUB
           }
           }
           };
         GHC.Types.True -> (# w_s1FX, GHC.Unit.() #)
       }; } in
 $wa_s1G7)

This is a local recursive loop with an invariant first argument (w_s1FS) that is recrutinised every time! This seems deeply uncool.

This is with HEAD (7.1.20110203, incorporating the patch "Fix typo in SpecConstr that made it not work at all")

Attachments

STUArray-Rewrite2.hs Download (0.8 KB) - added by batterseapower 2 years ago.

Change History

Changed 2 years ago by batterseapower

Changed 2 years ago by batterseapower

I see what is going on here. Since this is a local letrec, you don't generate any specialisations from the RHS call patterns unless at least one call pattern is boring. However, since the body doesn't apply *any* arguments at all to the function, SpecConstr doesn't detect any calls! How amusing :-)

A quick and easy hack that would probably solve it would be to replace SpecConstr:1486 with:

any isNothing mb_pats || null mb_pats

I can't test this right now.

Changed 2 years ago by batterseapower

OK, I did actually manage to try my fix, and I'm still not getting specialisation of that function. That observation might be part of the problem, but it's not the whole story.

Changed 2 years ago by batterseapower

OK, I got it. All you need to do is replace varUsage with:

varUsage :: ScEnv -> OutVar -> ArgOcc -> ScUsage
varUsage env v use = case lookupHowBound env v of
    Just RecArg -> SCU { scu_calls = emptyVarEnv
                       , scu_occs = unitVarEnv v use }
    Just RecFun -> SCU { scu_calls = unitVarEnv v [(emptyVarEnv, [])] -- Added so we get specialisations even if function used in trivial way (i.e. as a variable)
                       , scu_occs = emptyVarEnv }
    Nothing -> nullUsage

Otherwise the pattern guard on (lookupVarEnv bind_calls fn) in specialise fails, so we don't even get to call callsToPats.

I think this is the right change, because it should also mean that we get call pattern specialisations for locally-bound functions that are e.g. stored inside a data structure.

Changed 2 years ago by simonpj

  • status changed from new to merge
  • testcase set to simplCore/should_compile/T4935

Right. I came to the same conclusion.

Mon Feb  7 10:25:37 GMT 2011  simonpj@microsoft.com
  * Fix Trac #4945: another SpecConstr infelicity
  
  Well, more a plain bug really, which led to SpecConstr
  missing some obvious opportunities for specialisation.
  
  Thanks to Max Bolingbroke for spotting this.

    M ./compiler/specialise/SpecConstr.lhs -21 +35

Simon

Changed 2 years ago by igloo

  • milestone set to 7.0.2

Changed 2 years ago by simonpj

  • testcase changed from simplCore/should_compile/T4935 to simplCore/should_compile/T4945

Changed 2 years ago by igloo

  • status changed from merge to closed
  • resolution set to fixed

Only performance, and not a regression since 7.0.1 at least, so not merging at this stage of the release cycle.

Note: See TracTickets for help on using tickets.