SSA simplify passes
Stephen Weeks
MLton@sourcelight.com
Fri, 4 Jan 2002 17:51:12 -0800
> md5 -- if you look at the .ssa of -loop-passes 1, you'll see three
> functions all of the form:
> fun x_148 (x_154) = L_88 ()
> L_88 ()
> ()
> which are used in about 45 non-tail calls. Before the last removeUnused
> call, these functions do somthing, but their results aren't used, so they
> are trimmed down to:
...
> which the shinker reduces to the above (this explains why removeUnused
> didn't eliminate the function argument, although it is clearly unused in
> the final function).
>
> I think that just eliminating those extraneous non-tail calls sped it up
> quite a bid.
Cool. Maybe what we need is some count of how many opts the last
shrink did, and if there werw a lot done, we re-run the simplifier.
> matrix-multiply: As best I can make out, something (I don't know what
> pass) establishes the fact that the source matrix is initialized, but
> never updated -- so it replaces all the array subs (and associated
> computation of subscripts) with the constant 1.0.
Constant propagation figures this out. The reason it didn't with
-loop-passes 1 is that inlining happens after constant propagation, so
the Array2.array constructor saw many different arrays. After
inlining, each array construction is a different call to Array_array,
it is easy for constant propagation to see that there is an array of
constants. Because of that, I don't think that's a good benchmark, so
I changed it so that the array is nonconstant.
> nucleic: Looking at the datatypes of the -loop-passes 2 version, my guess
> is too much flattening of tuples. In particular, something like this
> looks bad:
...
Yuck. Maybe arg flattening should only happen if a large fraction of
the selects are inevitable.
> btw, how does MLton map a record to a tuple?.
The translation to XML (type-inference/infer.fun) puts record fields
in alphabetical order (of course :-) when translating to a tuple.
> Here are a couple of other random "cleanup"'s I'm trying to track down:
...
> Pulling apart x_1991 just to put it back together again in env_30 seems
> wasteful. This happens all over the place in a self-compile.
Yeah, eliminating reconstitution of tuples has been on my list for a
while. Go for it.
> Another random thing I noticed: there seems to be a strange
> interplay between the XML simplifier (particularly inlining) and
> polyvariance. If you look at the SSA of logic.sml you'll see 5
> copies of a function called oc_?, all of which are alpha-equivalent.
> ...
You're right. The XML simplifier only inlines functions that are
called once. So, occurs_check is inlined inside of unify_REF. Hence
oc and ocs are inside unify_REF by the time we get to polyvariance.
unify_REF is "higher-order", and so is potentially duplicated by
polyvariance. It turns out there are 5 uses, and the size threshold
is met, so there are 5 copies of oc and ocs.
The problem is that polyvariance duplicates functions local to a
higher-order function when the function is duplicated, even if they
don't depend on the higher-order-ness. The solution as I see it is to
some kind of lambda-lifting/closure conversion to move these local
functions out so that only the code that depends on the
higher-order-ness is duplicated. There's a whole lot of unexplored
territory in MLton in lifting functions and improving closure
representations. I don't see any easy fixes. Just lots of
(interesting) work.