Implement cardinality analysis
authorSimon Peyton Jones <simonpj@microsoft.com>
Fri, 3 May 2013 13:50:58 +0000 (14:50 +0100)
committerSimon Peyton Jones <simonpj@microsoft.com>
Thu, 6 Jun 2013 13:29:53 +0000 (14:29 +0100)
commit99d4e5b4a0bd32813ff8c74e91d2dcf6b3555176
tree62098e1b36c61fe1a978a29d955f57b629c5ec79
parentda4ff650ae77930a5a10d4886c8bc7d37f081db7
Implement cardinality analysis

This major patch implements the cardinality analysis described
in our paper "Higher order cardinality analysis". It is joint
work with Ilya Sergey and Dimitrios Vytiniotis.

The basic is augment the absence-analysis part of the demand
analyser so that it can tell when something is used
 never
 at most once
   some other way

The "at most once" information is used
    a) to enable transformations, and
       in particular to identify one-shot lambdas
    b) to allow updates on thunks to be omitted.

There are two new flags, mainly there so you can do performance
comparisons:
    -fkill-absence   stops GHC doing absence analysis at all
    -fkill-one-shot  stops GHC spotting one-shot lambdas
                     and single-entry thunks

The big changes are:

* The Demand type is substantially refactored.  In particular
  the UseDmd is factored as follows
      data UseDmd
        = UCall Count UseDmd
        | UProd [MaybeUsed]
        | UHead
        | Used

      data MaybeUsed = Abs | Use Count UseDmd

      data Count = One | Many

  Notice that UCall recurses straight to UseDmd, whereas
  UProd goes via MaybeUsed.

  The "Count" embodies the "at most once" or "many" idea.

* The demand analyser itself was refactored a lot

* The previously ad-hoc stuff in the occurrence analyser for foldr and
  build goes away entirely.  Before if we had build (\cn -> ...x... )
  then the "\cn" was hackily made one-shot (by spotting 'build' as
  special.  That's essential to allow x to be inlined.  Now the
  occurrence analyser propagates info gotten from 'build's stricness
  signature (so build isn't special); and that strictness sig is
  in turn derived entirely automatically.  Much nicer!

* The ticky stuff is improved to count single-entry thunks separately.

One shortcoming is that there is no DEBUG way to spot if an
allegedly-single-entry thunk is acually entered more than once.  It
would not be hard to generate a bit of code to check for this, and it
would be reassuring.  But it's fiddly and I have not done it.

Despite all this fuss, the performance numbers are rather under-whelming.
See the paper for more discussion.

       nucleic2          -0.8%    -10.9%      0.10      0.10     +0.0%
         sphere          -0.7%     -1.5%      0.08      0.08     +0.0%
--------------------------------------------------------------------------------
            Min          -4.7%    -10.9%     -9.3%     -9.3%    -50.0%
            Max          -0.4%     +0.5%     +2.2%     +2.3%     +7.4%
 Geometric Mean          -0.8%     -0.2%     -1.3%     -1.3%     -1.8%

I don't quite know how much credence to place in the runtime changes,
but movement seems generally in the right direction.
15 files changed:
compiler/basicTypes/Demand.lhs
compiler/basicTypes/MkId.lhs
compiler/basicTypes/OccName.lhs
compiler/cmm/CmmParse.y
compiler/codeGen/StgCmmBind.hs
compiler/codeGen/StgCmmTicky.hs
compiler/coreSyn/CorePrep.lhs
compiler/main/DynFlags.hs
compiler/simplCore/OccurAnal.lhs
compiler/stgSyn/CoreToStg.lhs
compiler/stranal/DmdAnal.lhs
docs/storage-mgt/ldv.tex
includes/stg/Ticky.h
rts/Linker.c
rts/Ticky.c