ICFP?

Henry Cejtin henry@sourcelight.com
Mon, 10 Sep 2001 16:01:15 -0500


I certainly don't intend to argue that SSA makes the raise=>jump better.  The
old block-structured code though clearly isn't as good as just being able  to
set  the  handler.   This  is  just like the ICFP contest problem: imperative
style is more efficient than block structured style.  The `only' advantage of
block  structure  (and  this  is  huge for the human) is that you can perform
local changes and know what effect it will have on the result without  having
to scan the entire program.

An  example  of the win here is that you never need to save the initial value
of the handler stack in a function more than once.

The example I was thinking of though was simpler.  If you have a  fold  (over
lists  say)  and  you  now want to exit the loop early, the easiest way is to
have the folder function raise an exception and handle the call to fold.   In
the  absence  of  inlining fold, this is really going to have to use the full
exception handling mechanism to pop off the frame of the folder procedure and
of  the  fold procedure.  In MLton, if both fold and the folder procedure are
inlined (which they almost always are) then the  raise  in  the  folder  just
turns  into  a jump out of the loop (thanks to the raise=>jump optimization).
Without inlining, this optimization would basically never trigger because  no
one  is  going  to  write  code to do a raise for this.  In MLton it IS a win
because the raise can only be seen to be a jump after inlining.

Just to be completely explicit:

    fun ('elem, 'state)
       fold (lst: 'elem list,
             istate: 'state,
             folder: 'elem * 'state -> 'state)
            : 'state =
          let fun loop (lst, state) =
                     case lst of
                       [] => state
                     | h::t => loop (t, folder (h, state))
          in loop (lst, istate)
          end

    fun doMults (lst: int list): int =
           let exception Zero
               fun folder (e, ac) =
                      if e = 0
                         then raise Zero
                         else e * ac
           in fold (lst, 1, folder)
                 handle Zero => 0
           end

In MLton, this should generate good code.