Allocation stack lowering based on escape analysis

Now that we can run libgo benchmarks:
https://codereview.appspot.com/103550047/
we can measure the effect of optimizations to see if they are worth adding
to the compiler.

This introduces an ssaopt package to hold SSA-level optimizations, to which
we add an allocation stack lowering pass based on a simple intraprocedural
escape analysis. In an experiment comparing libgo benchmark performance
before and after this change, this pass yielded a geo-mean 7.1% (5.5-8.7%
at a 95% confidence interval) improvement in performance.
Yes, this is the bug I alluded to earlier. I'm working with adonovan on a fix:
https://codereview.appspot.com/110170045/
although the fix in that CL probably won't be the one that will eventually land.

Here's the case that exposes the unsoundness bug, if you are interested:

    package main
    
    func main() {
    	var p, q *int
    	for i := 0; i != 2; i++ {
    		p = q
    		q = new(int)
    		*q = i
    	}
    	println(*p, *q)
    }

The SSA representation:

    func main():
    .0.entry:                                                               P:0 S:1
    	jump 3.for.loop
    .1.for.body:                                                            P:1 S:1
    	t0 = new int (new)                                                 *int
    	*t0 = t7
    	t1 = t7 + 1:int                                                     int
    	jump 3.for.loop
    .2.for.done:                                                            P:1 S:0
    	t2 = *t5                                                            int
    	t3 = *t6                                                            int
    	t4 = println(t2, t3)                                                 ()
    	return
    .3.for.loop:                                                            P:2 S:2
    	t5 = phi [0.entry: nil:*int, 1.for.body: t6] #p                    *int
    	t6 = phi [0.entry: nil:*int, 1.for.body: t0] #q                    *int
    	t7 = phi [0.entry: 0:int, 1.for.body: t1] #i                        int
    	t8 = t7 != 2:int                                                   bool
    	if t8 goto 1.for.body else 2.for.done

In this example, the analysis would conclude that t0 can be made into a local (if not for the unwanted referrers), but this is wrong because this would give the two "versions" of t0 in the loop the same identity. As a result, the local lowering for t0 would transform the program such that it would print "1 1" rather than "0 1".

I think that we can detect such cases by checking whether a (directly or indirectly) referred phi node dominates the allocation.

I have made my fix available in the libgo-esc2 branch of my repository (it depends on the go/tools CL above).