contification paper

Stephen Weeks MLton@sourcelight.com
Fri, 16 Feb 2001 14:46:38 -0800 (PST)


> Looking at the outline, I think we'll be good on length without bringing
> in handlers.  And, they are completely transparent to the analyses, so I
> don't think they add much in this context.

Agreed.

> On the other hand, we really should be a little more precise about cycles.
> For example, we could have the following:
> 
> fun fm () = ...
> fun f () = ... K (g) ...
> fun g () = ... f () ...
> 
> and A(f) = g, A(g) = K is safe, although not minimal, and not "acyclic" in
> the sense that the transformation can't be performed.  I'll think a little
> more about this and see if I can't hammer out something more precise.

How about we just use Reach in the definition of safety.  I.E.
	* if not(Reach(f)) then A(f) = Uncalled

After all, reachability is a trivial concept and any sane analysis would do this 
(okok I know an old implementation of the contifier didn't :-).

If we do this, we can get rid of acyclicity in the definition of safety,
although we may need to prove it later anyways since we need it for the
transformation.

> > Maybe type correctness of resulting program.
> 
> I thought about this, but this will mean complicating the CPS IL a little.
> On the other hand, it probably won't be too hard; a function contified in
> another function doesn't change types at all; a function contified at a
> continuation changes it's return type, but corresponding calls also
> change.

It hadn't even occurred to me that we could present the CPS IL without the type
system.  But I see it doesn't really matter for this optimization.  However, in
the interest of staying closer to MLton and the fact that typed ILs are popular,
I think I'd like to present the IL as typed, at least in the grammar.  We can
mostly elide the types later.

> > Maybe the right thing to compare is the five analyses
> > 
> > 	none	call	cont	call+cont	dom
> > 
> > I'm wavering on including call+cont.
> 
> I agree.  The results there aren't much different than anywhere else.

So we go with none, call, cont, dom and either present run times as a ratio
relative to none or relative to dom, I'm not sure which.

> > Is this for the dom based on A*/parent, right?  Should we instead report the
> > dom based on ancestor, with a note that it's actually weaker due to the mutual
> > recursion problem?

> Yes, it is based on A*/parent.  The fact that the transformation accepts
> any A* safe analysis doesn't affect the transformation that's done when
> the dominator analysis uses ancestor (i.e., we won't be able to contify
> those two functions in logic).  It's a trivial change to run the parent
> analysis (I should just extend the contifyStrategy control) and get the
> numbers there.

You mean "change to run the ancestor analysis", right?  I assume so.  Anyways,
the run times should be based on ancestor since that conforms to the safety
definition in the paper.

Hmmm.  I just thought of another possibility.  What if we use the A* safety
definition, the parent analysis, and your latest transformation, but still
pretend we have mutual recursion.  Maybe that's not too complicated.

> I'll make one other comment.  When run with the call analysis, the new
> transformation is not identical to the old transformation.  Essentially,
> this is another nesting issue: 
..
> Essentially, the old transformation just found the one outside call and
> dropped the definition in the closest set of definitions.  The new
> transformation know that g is to be contified in f, so it's added before
> the original local functions of f.  There's no difference in runtimes
> between the old and new transformations, and virtually no difference in
> code size.

Good.  So we can stick with the one transformation that works for any safe
analysis.  I think it's ok to present a slightly historically inaccurate call
analysis, possibly with an incomprehensibly vague note about nesting.