Alternate canonicalizations of expressions in CommonSubexp.

As part of performing common subexpression elimination, CommonSubexp
canonicalizes all Exp.t-s, including putting arguments to commutative
arithmetic primitives in canonical order.  There is a note in
common-subexp.fun regarding this canonicalizing of commutative
arguments:

                  fun canon2 () =
                     let
                        val a0 = arg 0
                        val a1 = arg 1
                     in
                        (* What we really want is a total orderning on
                         * variables.  Since we don't have one, we just use
                         * the total ordering on hashes, which means that
                         * we may miss a few cse's but we won't be wrong.
                         *)
                        if Var.hash a0 <= Var.hash a1
                           then (a0, a1)
                        else (a1, a0)
                     end

Note that the only cse-s that a lack of a total ordering would miss
are "a + b" and "b + a", where the variables "a" and "b" both had the
same hash.

On the other hand, the order of arguments to commutative arithmetic
arguments is sensitive to variable hashes and variable hashes are
created by an unseeded pseudo-random number generator.  This
pseudo-random number generator is used create hashes for all classes
of identifiers, so while variable hashes are deterministic, they are
sensitive to the number of identifiers created before the variable is
created.  Hence, the creation of additional identifiers (for example,
the creation of FuncEntry identifiers during ClosureCovert in the
multi-entry pipeline shifts) the assignment of hashes to variable
identifiers, which might swap the arguments of commutative arithmetic
primitives.

Now, one would hope that the codegens would not be sensitive to the
ordering of arguments in commutative arithmetic primitives.  Indeed,
the native codegens do some analysis to pick a "good" order in which
to handle the arguments of commutative arithmetic primitives.
However, when ther isn't anything to break the tie when looking for a
"good" order, the generated code follows the order of the arguments in
the primitive.

This commit introduces four different canonicalization strategies for
arguments to commutative arithmetic primitives.  "ascHash" and
"descHash" correspond to the strategies that put the arguments in
order of ascending or descending variable hashes, respectively.
"ascIndex" and "descIndex" correspond to strategies that put the
arguments in order of ascending or descending variable indices,
respectively.  Variable indices are set according to a counter and a
variable's index is set when it's defining occurrence is encountered
during the walk of the dominator tree/forest.  This doesn't guarantee
that a variable's index is always the same under different compiles; a
variable's index is sensitive to the number of variables set before
it, which will depend upon the particular program and previous program
transformations.  However, this indexing strategy does have the
advantage that the relative order of two variables will always
correspond to the relative scope of the two variables, which will tend
to be stable across compiles, so long as the variables in question are
not the subject of a serious optimization.

Here are the results:

MLton0 -- ~/devel/mlton/mlton-20130715/build/bin/mlton -keep g
MLton1 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry false -cse-canon ascHash
MLton2 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry false -cse-canon descHash
MLton3 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry false -cse-canon ascIndex
MLton4 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry false -cse-canon descIndex
MLton5 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry true -cse-canon ascHash -drop-pass duplicateEntries -drop-pass 'merge.*TailCalls.*' -drop-pass 'splitEntries.*'
MLton6 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry true -cse-canon descHash -drop-pass duplicateEntries -drop-pass 'merge.*TailCalls.*' -drop-pass 'splitEntries.*'
MLton7 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry true -cse-canon ascIndex -drop-pass duplicateEntries -drop-pass 'merge.*TailCalls.*' -drop-pass 'splitEntries.*'
MLton8 -- ~/devel/mlton/mlton.git/build/bin/mlton -keep g -check-multi-entry true -cse-canon descIndex -drop-pass duplicateEntries -drop-pass 'merge.*TailCalls.*' -drop-pass 'splitEntries.*'
run time ratio
benchmark         MLton0 MLton1 MLton2 MLton3 MLton4 MLton5 MLton6 MLton7 MLton8
barnes-hut          1.00   1.00   1.00   1.01   1.00   1.00   1.00   1.01   1.01
boyer               1.00   0.99   0.99   0.99   0.99   0.99   0.99   0.99   0.99
checksum            1.00   1.00   0.95   1.00   0.95   1.00   0.95   1.00   0.95
count-graphs        1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
DLXSimulator        1.00   1.00   0.99   0.99   0.99   0.99   0.99   0.99   0.99
even-odd            1.00   0.94   1.00   1.00   1.00   1.00   1.00   1.00   1.00
fft                 1.00   1.00   0.99   0.99   0.99   0.99   0.99   0.99   0.99
fib                 1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
flat-array          1.00   1.00   1.00   1.00   1.00   1.05   1.07   1.07   1.07
hamlet              1.00   1.03   1.01   1.02   1.02   1.02   1.03   1.02   1.01
imp-for             1.00   0.96   0.96   0.96   0.96   0.96   0.96   0.96   0.96
knuth-bendix        1.00   1.00   1.01   1.01   1.00   1.00   1.01   1.02   1.00
lexgen              1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.01   1.08
life                1.00   1.01   0.97   0.96   0.97   0.96   0.97   0.96   0.97
logic               1.00   1.00   1.01   1.00   1.00   1.00   1.00   1.00   1.00
mandelbrot          1.00   1.00   1.13   1.14   1.00   1.14   1.00   1.14   1.00
matrix-multiply     1.00   1.00   0.97   1.00   0.97   1.00   0.96   1.00   0.98
md5                 1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
merge               1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
mlyacc              1.00   1.00   1.01   1.00   1.00   1.00   1.00   1.00   1.00
model-elimination   1.00   1.01   1.00   1.00   1.00   1.00   1.00   1.00   1.00
mpuz                1.00   1.00   1.00   1.01   1.00   1.00   1.00   1.00   1.01
nucleic             1.00   1.00   1.00   0.99   1.03   0.99   0.98   0.99   1.03
output1             1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
peek                1.00   1.02   1.01   1.02   1.02   1.04   1.13   1.17   1.16
psdes-random        1.00   0.96   1.06   1.07   0.96   0.99   1.00   1.07   0.96
ratio-regions       1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
ray                 1.00   0.98   0.90   0.91   0.90   0.90   0.91   0.90   0.90
raytrace            1.00   1.01   1.01   1.01   1.01   1.01   1.01   1.01   1.01
simple              1.00   0.99   0.99   0.98   0.99   1.02   1.00   0.98   0.99
smith-normal-form   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
tailfib             1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
tak                 1.00   0.97   0.96   0.96   0.96   0.96   0.96   0.96   0.96
tensor              1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
tsp                 1.00   1.00   1.00   0.98   0.98   0.95   0.98   0.98   0.98
tyan                1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.01   1.00
vector-concat       1.00   1.00   1.00   0.99   1.00   1.00   1.00   1.00   1.00
vector-rev          1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
vliw                1.00   1.00   1.00   1.00   1.00   0.99   1.00   1.00   1.00
wc-input1           1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
wc-scanStream       1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
zebra               1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00   1.00
zern                1.00   1.01   0.98   1.00   0.98   1.00   0.98   1.00   0.98

Comparing MLton0/MLton1 (which should be equivalent) and MLton3 and
MLton4 seems to suggest thta '-cse-canon descIndex' is the proper way
to canonicalize expressions.  Using '-cse-canon ascIndex' seems to
trigger the slowdown in mandelbrot.  Correspondingly, using
'-cse-canon descIndex' seems to avoid the slowdown in mandelbrot and
seems to trigger a speedup in checksum and ray.  Not sure if any of
the other variations are significant.
Canonicalize arguments of commutative primitives according to descending variable indices.

Variable indices are set according to a counter and a variable's index
is set when it's defining occurrence is encountered during the walk of
the dominator tree/forest.  This doesn't guarantee that a variable's
index is always the same under different compiles; a variable's index
is sensitive to the number of variables set before it, which will
depend upon the particular program and previous program
transformations.  However, this indexing strategy does have the
advantage that the relative order of two variables will always
correspond to the relative scope of the two variables, which will tend
to be stable across compiles, so long as the variables in question are
not the subject of a serious optimization.