Notes 18 March 2010
~~~~~~~~~~~~~~~~~~~

  * John and Norman are not convinced that the ChangeFlag 'tfb_cha' is
    being updated correctly when facts change.  Because block IDs are
    added to 'tfb_bids' incrementally, we are worried that a fact at
    label L could be made to climb by a predecessor, but that this
    change wouldn't be noted by updateFact unless the block labelled L
    had already been visited.  We spent a good 20 minutes on this
    question, which right there is indicative of a problem.  The
    computation of the fixed point needs to be manifestly correct.
    Perhaps tfb_bids should be initialized all at one go, and perhaps
    it should be given type 'BlockId -> Bool'?

  * The 'nodeGraph' function, together with the supporting case of
    OCFlag and IsOC, are a bit eye-popping.   A good explanation
    should be a high priority.  Also, it would be good to be able to
    say in the paper whether GHC -O is able to eliminate the IsOC
    type-class dictionaries.  Finally, it is probably also worth
    noting that if Haskell had Sorts as in the Omega language, this
    issue might not arise.

  * Similarly, the new type-class constraints in GFTR are worth
    noting, and the same questions arise about dictionaries.

  * Norman has a few ideas to tidy the implementation of gftGraph.
    He will try them out, and if he likes them, will send them on.

  * The >>> arrow has but one use.  We suggest a local binding:

      blocks_once :: Blocks n -> Trans (TxFactBase n f) (TxFactBase n f)
      blocks_once = foldr ((>>>) . block_once) idTrans
        where (t1 >>> t2) f = t1 f >>= t2

  * Does the "it's a bit disgusting..." comment still apply?







Notes March 2010
~~~~~~~~~~~~~~~~
Normans comment on draft so far:

- Revisit introduction

- Still skeptical about blockId function

- GMany: does the list have to be non-empty?
   Could we have GMany b1 [] b2?  
   
- Distinction between invariants that hold on "finished graphs"
  and ones that hold on graphs under construction.

- Consider (GUnit b) :: Graph C C, can successors(b) include b's 
  own BlockId?  No.  

- If you ask for successors(x) can you get any pointer into x?
  Answer no.  
  Simon says: you can can only get a loop in g_blocks.  A singleton
  block can't be a loop.  

- Client knows about nodes. Our job is to lift to blocks and graphs.


* I would love to simplify the Graph type, further, but I don't know
  how.  In particular, we seem to *need* a function of type
	lift :: n e x -> Graph n e x
  to use when the client's rewriting function says Nothing.

  But that forces the slightly 

* Talking to John, we agreed that a common use of Hoopl will be to
  analyse full graphs, to get a full mapping (BlockId -> fact), for
  the *internal* nodes of the graph, not just its out-edges.  Inded
  for a full graph (eg a procedure body) there wil *be* no out-edges.

  So maybe we want 
     data Graph n e x where
       ...
       GMany { 
 	g_entry :: Block n e C,
	g_blocks :: FullGraph n,
        ...}

  where
    newtype FullGraph n = FG [Block n C C]
  
  And the client might define a procedure thus:

    data Procedure = Proc BlockId  -- Entry point
                          (FullGraph CmmNode)

  Now we may imagine
	GFT_FullGraph n f = GFT (FullGraph n)
  and the client interface might be exposed for FullGraph.
  Meanwhile, the recursive invocations of the analysis still
  work on Graphs.

  So a FullGraph would be a fourth kind of entity (as well as
  nodes, blocks, graphs), albeit one that is not an instance of
  Edges.

That would make the signature of analyseAndRewrite look like this:

analyseAndRewrite
   :: forall n f. Edges n
   => RewritingDepth
   -> DataflowLattice f
   -> ForwardTransfers n f
   -> ForwardRewrites n f
   -> GFT_FullGraph n f

where
  GFT_FullGraph n f = FullGraph n -> InFactC f -> 

* Incidentally, eleveating FullGraph in this way would let
  us switch to BlockEnv or whatever else we wanted if that 
  proved convenient.

* Maybe FullGraph should be Graph, and Graph should be PGraph (for
  partial graph), or SubGraph.

* I was thinking how to do dead-block elimination.  Given a fact
  (B17 -> Dead), how can I rewrite the block with label B17 to
  an empty graph?  I'd like to write
      rewrite fact_fun (Label b) 
        | fact_fun b == Dead = Just (GUnit (BUnit b `BCat` unreachable))
        | otherwise          = Nothing

  So what is "unreachable :: Block".  I suppose it's a new constructor
  of the Block type, that eats all its downstream fellows:

	data Block n e x where
          BUnr :: Block n O x
	  ...as before...

  It's a bit like the GNil constructor, which is there primarily
  to allow us to rewrite a node to a no-op.

  Its a bit tiresome that it has be be in Block not Graph, but
  we still need that Label. 


Ideas
~~~~~
"Optimization" encompasses:
  - substitution informed by equational reasoning (about states)
  - removal of redundant code, as justified by reasoning about
    continuations

"Code motion" is achieved by inserting redundant code,
thereby making original code redundant, which in turn
can be removed.

Technique
~~~~~~~~~
No single technique; the secret sauce is how we combine things:
  - Zipper CFG
  - Disctinct representations for construction and analyis of CFGs
  - Maximum use of polymorphism
  - Type classes to make notation resemble prior art
  - Transfer equations coded in dragon-book style
  - Fixed points courtesy Lerner, Grove, and Chambers (2002)

Contribution
~~~~~~~~~~~~
We make dataflow optimization easy to think about and easy to build:

 * Ideas that reconcile the ad-hoc 'optimization zoo' found in the
   dragon book with methods of reasoning long understood by functional
   programmers.

 * Design and implementation that make it not just possible but *easy*
   to use dataflow techniques in your compiler.



---------------------------------
Working title: Dataflow Optimization Made Simple

Note: By decomposing 'optimizations' into smaller units, we simplify.
'induction-variable elimination' is *not* an atomic thing!


---------------------------------
Vague Outline
1. Intro
2. Short example
3. Logical view of optimization
4. Clients (examples, including type class declarations)
5. Graphs
6. Fixed-point computation; the dataflow monad
7. Discussion

