Home | History | Annotate | Download | only in gc
      1 // Derived from Inferno utils/6c/gc.h
      2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
      3 //
      4 //	Copyright  1994-1999 Lucent Technologies Inc.  All rights reserved.
      5 //	Portions Copyright  1995-1997 C H Forsyth (forsyth (a] terzarima.net)
      6 //	Portions Copyright  1997-1999 Vita Nuova Limited
      7 //	Portions Copyright  2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
      8 //	Portions Copyright  2004,2006 Bruce Ellis
      9 //	Portions Copyright  2005-2007 C H Forsyth (forsyth (a] terzarima.net)
     10 //	Revisions Copyright  2000-2007 Lucent Technologies Inc. and others
     11 //	Portions Copyright  2009 The Go Authors.  All rights reserved.
     12 //
     13 // Permission is hereby granted, free of charge, to any person obtaining a copy
     14 // of this software and associated documentation files (the "Software"), to deal
     15 // in the Software without restriction, including without limitation the rights
     16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17 // copies of the Software, and to permit persons to whom the Software is
     18 // furnished to do so, subject to the following conditions:
     19 //
     20 // The above copyright notice and this permission notice shall be included in
     21 // all copies or substantial portions of the Software.
     22 //
     23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     29 // THE SOFTWARE.
     30 
     31 // "Portable" optimizations.
     32 
     33 package gc
     34 
     35 import (
     36 	"cmd/internal/obj"
     37 	"fmt"
     38 	"sort"
     39 	"strings"
     40 )
     41 
     42 type OptStats struct {
     43 	Ncvtreg int32
     44 	Nspill  int32
     45 	Nreload int32
     46 	Ndelmov int32
     47 	Nvar    int32
     48 	Naddr   int32
     49 }
     50 
     51 var Ostats OptStats
     52 
     53 var noreturn_symlist [10]*Sym
     54 
     55 // p is a call instruction. Does the call fail to return?
     56 func Noreturn(p *obj.Prog) bool {
     57 	if noreturn_symlist[0] == nil {
     58 		noreturn_symlist[0] = Pkglookup("panicindex", Runtimepkg)
     59 		noreturn_symlist[1] = Pkglookup("panicslice", Runtimepkg)
     60 		noreturn_symlist[2] = Pkglookup("throwinit", Runtimepkg)
     61 		noreturn_symlist[3] = Pkglookup("gopanic", Runtimepkg)
     62 		noreturn_symlist[4] = Pkglookup("panicwrap", Runtimepkg)
     63 		noreturn_symlist[5] = Pkglookup("throwreturn", Runtimepkg)
     64 		noreturn_symlist[6] = Pkglookup("selectgo", Runtimepkg)
     65 		noreturn_symlist[7] = Pkglookup("block", Runtimepkg)
     66 	}
     67 
     68 	if p.To.Node == nil {
     69 		return false
     70 	}
     71 	s := ((p.To.Node).(*Node)).Sym
     72 	if s == nil {
     73 		return false
     74 	}
     75 	for i := 0; noreturn_symlist[i] != nil; i++ {
     76 		if s == noreturn_symlist[i] {
     77 			return true
     78 		}
     79 	}
     80 	return false
     81 }
     82 
     83 // JMP chasing and removal.
     84 //
     85 // The code generator depends on being able to write out jump
     86 // instructions that it can jump to now but fill in later.
     87 // the linker will resolve them nicely, but they make the code
     88 // longer and more difficult to follow during debugging.
     89 // Remove them.
     90 
     91 /* what instruction does a JMP to p eventually land on? */
     92 func chasejmp(p *obj.Prog, jmploop *int) *obj.Prog {
     93 	n := 0
     94 	for p != nil && p.As == obj.AJMP && p.To.Type == obj.TYPE_BRANCH {
     95 		n++
     96 		if n > 10 {
     97 			*jmploop = 1
     98 			break
     99 		}
    100 
    101 		p = p.To.Val.(*obj.Prog)
    102 	}
    103 
    104 	return p
    105 }
    106 
    107 /*
    108  * reuse reg pointer for mark/sweep state.
    109  * leave reg==nil at end because alive==nil.
    110  */
    111 var alive interface{} = nil
    112 var dead interface{} = 1
    113 
    114 /* mark all code reachable from firstp as alive */
    115 func mark(firstp *obj.Prog) {
    116 	for p := firstp; p != nil; p = p.Link {
    117 		if p.Opt != dead {
    118 			break
    119 		}
    120 		p.Opt = alive
    121 		if p.As != obj.ACALL && p.To.Type == obj.TYPE_BRANCH && p.To.Val.(*obj.Prog) != nil {
    122 			mark(p.To.Val.(*obj.Prog))
    123 		}
    124 		if p.As == obj.AJMP || p.As == obj.ARET || p.As == obj.AUNDEF {
    125 			break
    126 		}
    127 	}
    128 }
    129 
    130 func fixjmp(firstp *obj.Prog) {
    131 	if Debug['R'] != 0 && Debug['v'] != 0 {
    132 		fmt.Printf("\nfixjmp\n")
    133 	}
    134 
    135 	// pass 1: resolve jump to jump, mark all code as dead.
    136 	jmploop := 0
    137 
    138 	for p := firstp; p != nil; p = p.Link {
    139 		if Debug['R'] != 0 && Debug['v'] != 0 {
    140 			fmt.Printf("%v\n", p)
    141 		}
    142 		if p.As != obj.ACALL && p.To.Type == obj.TYPE_BRANCH && p.To.Val.(*obj.Prog) != nil && p.To.Val.(*obj.Prog).As == obj.AJMP {
    143 			p.To.Val = chasejmp(p.To.Val.(*obj.Prog), &jmploop)
    144 			if Debug['R'] != 0 && Debug['v'] != 0 {
    145 				fmt.Printf("->%v\n", p)
    146 			}
    147 		}
    148 
    149 		p.Opt = dead
    150 	}
    151 
    152 	if Debug['R'] != 0 && Debug['v'] != 0 {
    153 		fmt.Printf("\n")
    154 	}
    155 
    156 	// pass 2: mark all reachable code alive
    157 	mark(firstp)
    158 
    159 	// pass 3: delete dead code (mostly JMPs).
    160 	var last *obj.Prog
    161 
    162 	for p := firstp; p != nil; p = p.Link {
    163 		if p.Opt == dead {
    164 			if p.Link == nil && p.As == obj.ARET && last != nil && last.As != obj.ARET {
    165 				// This is the final ARET, and the code so far doesn't have one.
    166 				// Let it stay. The register allocator assumes that all live code in
    167 				// the function can be traversed by starting at all the RET instructions
    168 				// and following predecessor links. If we remove the final RET,
    169 				// this assumption will not hold in the case of an infinite loop
    170 				// at the end of a function.
    171 				// Keep the RET but mark it dead for the liveness analysis.
    172 				p.Mode = 1
    173 			} else {
    174 				if Debug['R'] != 0 && Debug['v'] != 0 {
    175 					fmt.Printf("del %v\n", p)
    176 				}
    177 				continue
    178 			}
    179 		}
    180 
    181 		if last != nil {
    182 			last.Link = p
    183 		}
    184 		last = p
    185 	}
    186 
    187 	last.Link = nil
    188 
    189 	// pass 4: elide JMP to next instruction.
    190 	// only safe if there are no jumps to JMPs anymore.
    191 	if jmploop == 0 {
    192 		var last *obj.Prog
    193 		for p := firstp; p != nil; p = p.Link {
    194 			if p.As == obj.AJMP && p.To.Type == obj.TYPE_BRANCH && p.To.Val == p.Link {
    195 				if Debug['R'] != 0 && Debug['v'] != 0 {
    196 					fmt.Printf("del %v\n", p)
    197 				}
    198 				continue
    199 			}
    200 
    201 			if last != nil {
    202 				last.Link = p
    203 			}
    204 			last = p
    205 		}
    206 
    207 		last.Link = nil
    208 	}
    209 
    210 	if Debug['R'] != 0 && Debug['v'] != 0 {
    211 		fmt.Printf("\n")
    212 		for p := firstp; p != nil; p = p.Link {
    213 			fmt.Printf("%v\n", p)
    214 		}
    215 		fmt.Printf("\n")
    216 	}
    217 }
    218 
    219 // Control flow analysis. The Flow structures hold predecessor and successor
    220 // information as well as basic loop analysis.
    221 //
    222 //	graph = flowstart(firstp, 0);
    223 //	... use flow graph ...
    224 //	flowend(graph); // free graph
    225 //
    226 // Typical uses of the flow graph are to iterate over all the flow-relevant instructions:
    227 //
    228 //	for(f = graph->start; f != nil; f = f->link)
    229 //
    230 // or, given an instruction f, to iterate over all the predecessors, which is
    231 // f->p1 and this list:
    232 //
    233 //	for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
    234 //
    235 // The size argument to flowstart specifies an amount of zeroed memory
    236 // to allocate in every f->data field, for use by the client.
    237 // If size == 0, f->data will be nil.
    238 
    239 var flowmark int
    240 
    241 // MaxFlowProg is the maximum size program (counted in instructions)
    242 // for which the flow code will build a graph. Functions larger than this limit
    243 // will not have flow graphs and consequently will not be optimized.
    244 const MaxFlowProg = 50000
    245 
    246 func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph {
    247 	// Count and mark instructions to annotate.
    248 	nf := 0
    249 
    250 	for p := firstp; p != nil; p = p.Link {
    251 		p.Opt = nil // should be already, but just in case
    252 		Thearch.Proginfo(p)
    253 		if p.Info.Flags&Skip != 0 {
    254 			continue
    255 		}
    256 		p.Opt = &flowmark
    257 		nf++
    258 	}
    259 
    260 	if nf == 0 {
    261 		return nil
    262 	}
    263 
    264 	if nf >= MaxFlowProg {
    265 		if Debug['v'] != 0 {
    266 			Warn("%v is too big (%d instructions)", Curfn.Func.Nname.Sym, nf)
    267 		}
    268 		return nil
    269 	}
    270 
    271 	// Allocate annotations and assign to instructions.
    272 	graph := new(Graph)
    273 	ff := make([]Flow, nf)
    274 	start := &ff[0]
    275 	id := 0
    276 	var last *Flow
    277 	for p := firstp; p != nil; p = p.Link {
    278 		if p.Opt == nil {
    279 			continue
    280 		}
    281 		f := &ff[0]
    282 		ff = ff[1:]
    283 		p.Opt = f
    284 		f.Prog = p
    285 		if last != nil {
    286 			last.Link = f
    287 		}
    288 		last = f
    289 		if newData != nil {
    290 			f.Data = newData()
    291 		}
    292 		f.Id = int32(id)
    293 		id++
    294 	}
    295 
    296 	// Fill in pred/succ information.
    297 	var f1 *Flow
    298 	var p *obj.Prog
    299 	for f := start; f != nil; f = f.Link {
    300 		p = f.Prog
    301 		if p.Info.Flags&Break == 0 {
    302 			f1 = f.Link
    303 			f.S1 = f1
    304 			f1.P1 = f
    305 		}
    306 
    307 		if p.To.Type == obj.TYPE_BRANCH {
    308 			if p.To.Val == nil {
    309 				Fatal("pnil %v", p)
    310 			}
    311 			f1 = p.To.Val.(*obj.Prog).Opt.(*Flow)
    312 			if f1 == nil {
    313 				Fatal("fnil %v / %v", p, p.To.Val.(*obj.Prog))
    314 			}
    315 			if f1 == f {
    316 				//fatal("self loop %v", p);
    317 				continue
    318 			}
    319 
    320 			f.S2 = f1
    321 			f.P2link = f1.P2
    322 			f1.P2 = f
    323 		}
    324 	}
    325 
    326 	graph.Start = start
    327 	graph.Num = nf
    328 	return graph
    329 }
    330 
    331 func Flowend(graph *Graph) {
    332 	for f := graph.Start; f != nil; f = f.Link {
    333 		f.Prog.Info.Flags = 0 // drop cached proginfo
    334 		f.Prog.Opt = nil
    335 	}
    336 }
    337 
    338 /*
    339  * find looping structure
    340  *
    341  * 1) find reverse postordering
    342  * 2) find approximate dominators,
    343  *	the actual dominators if the flow graph is reducible
    344  *	otherwise, dominators plus some other non-dominators.
    345  *	See Matthew S. Hecht and Jeffrey D. Ullman,
    346  *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
    347  *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
    348  *	Oct. 1-3, 1973, pp.  207-217.
    349  * 3) find all nodes with a predecessor dominated by the current node.
    350  *	such a node is a loop head.
    351  *	recursively, all preds with a greater rpo number are in the loop
    352  */
    353 func postorder(r *Flow, rpo2r []*Flow, n int32) int32 {
    354 	r.Rpo = 1
    355 	r1 := r.S1
    356 	if r1 != nil && r1.Rpo == 0 {
    357 		n = postorder(r1, rpo2r, n)
    358 	}
    359 	r1 = r.S2
    360 	if r1 != nil && r1.Rpo == 0 {
    361 		n = postorder(r1, rpo2r, n)
    362 	}
    363 	rpo2r[n] = r
    364 	n++
    365 	return n
    366 }
    367 
    368 func rpolca(idom []int32, rpo1 int32, rpo2 int32) int32 {
    369 	if rpo1 == -1 {
    370 		return rpo2
    371 	}
    372 	var t int32
    373 	for rpo1 != rpo2 {
    374 		if rpo1 > rpo2 {
    375 			t = rpo2
    376 			rpo2 = rpo1
    377 			rpo1 = t
    378 		}
    379 
    380 		for rpo1 < rpo2 {
    381 			t = idom[rpo2]
    382 			if t >= rpo2 {
    383 				Fatal("bad idom")
    384 			}
    385 			rpo2 = t
    386 		}
    387 	}
    388 
    389 	return rpo1
    390 }
    391 
    392 func doms(idom []int32, r int32, s int32) bool {
    393 	for s > r {
    394 		s = idom[s]
    395 	}
    396 	return s == r
    397 }
    398 
    399 func loophead(idom []int32, r *Flow) bool {
    400 	src := r.Rpo
    401 	if r.P1 != nil && doms(idom, src, r.P1.Rpo) {
    402 		return true
    403 	}
    404 	for r = r.P2; r != nil; r = r.P2link {
    405 		if doms(idom, src, r.Rpo) {
    406 			return true
    407 		}
    408 	}
    409 	return false
    410 }
    411 
    412 func loopmark(rpo2r **Flow, head int32, r *Flow) {
    413 	if r.Rpo < head || r.Active == head {
    414 		return
    415 	}
    416 	r.Active = head
    417 	r.Loop += LOOP
    418 	if r.P1 != nil {
    419 		loopmark(rpo2r, head, r.P1)
    420 	}
    421 	for r = r.P2; r != nil; r = r.P2link {
    422 		loopmark(rpo2r, head, r)
    423 	}
    424 }
    425 
    426 func flowrpo(g *Graph) {
    427 	g.Rpo = make([]*Flow, g.Num)
    428 	idom := make([]int32, g.Num)
    429 
    430 	for r1 := g.Start; r1 != nil; r1 = r1.Link {
    431 		r1.Active = 0
    432 	}
    433 
    434 	rpo2r := g.Rpo
    435 	d := postorder(g.Start, rpo2r, 0)
    436 	nr := int32(g.Num)
    437 	if d > nr {
    438 		Fatal("too many reg nodes %d %d", d, nr)
    439 	}
    440 	nr = d
    441 	var r1 *Flow
    442 	for i := int32(0); i < nr/2; i++ {
    443 		r1 = rpo2r[i]
    444 		rpo2r[i] = rpo2r[nr-1-i]
    445 		rpo2r[nr-1-i] = r1
    446 	}
    447 
    448 	for i := int32(0); i < nr; i++ {
    449 		rpo2r[i].Rpo = i
    450 	}
    451 
    452 	idom[0] = 0
    453 	var me int32
    454 	for i := int32(0); i < nr; i++ {
    455 		r1 = rpo2r[i]
    456 		me = r1.Rpo
    457 		d = -1
    458 
    459 		// rpo2r[r->rpo] == r protects against considering dead code,
    460 		// which has r->rpo == 0.
    461 		if r1.P1 != nil && rpo2r[r1.P1.Rpo] == r1.P1 && r1.P1.Rpo < me {
    462 			d = r1.P1.Rpo
    463 		}
    464 		for r1 = r1.P2; r1 != nil; r1 = r1.P2link {
    465 			if rpo2r[r1.Rpo] == r1 && r1.Rpo < me {
    466 				d = rpolca(idom, d, r1.Rpo)
    467 			}
    468 		}
    469 		idom[i] = d
    470 	}
    471 
    472 	for i := int32(0); i < nr; i++ {
    473 		r1 = rpo2r[i]
    474 		r1.Loop++
    475 		if r1.P2 != nil && loophead(idom, r1) {
    476 			loopmark(&rpo2r[0], i, r1)
    477 		}
    478 	}
    479 
    480 	for r1 := g.Start; r1 != nil; r1 = r1.Link {
    481 		r1.Active = 0
    482 	}
    483 }
    484 
    485 func Uniqp(r *Flow) *Flow {
    486 	r1 := r.P1
    487 	if r1 == nil {
    488 		r1 = r.P2
    489 		if r1 == nil || r1.P2link != nil {
    490 			return nil
    491 		}
    492 	} else if r.P2 != nil {
    493 		return nil
    494 	}
    495 	return r1
    496 }
    497 
    498 func Uniqs(r *Flow) *Flow {
    499 	r1 := r.S1
    500 	if r1 == nil {
    501 		r1 = r.S2
    502 		if r1 == nil {
    503 			return nil
    504 		}
    505 	} else if r.S2 != nil {
    506 		return nil
    507 	}
    508 	return r1
    509 }
    510 
    511 // The compilers assume they can generate temporary variables
    512 // as needed to preserve the right semantics or simplify code
    513 // generation and the back end will still generate good code.
    514 // This results in a large number of ephemeral temporary variables.
    515 // Merge temps with non-overlapping lifetimes and equal types using the
    516 // greedy algorithm in Poletto and Sarkar, "Linear Scan Register Allocation",
    517 // ACM TOPLAS 1999.
    518 
    519 type TempVar struct {
    520 	node    *Node
    521 	def     *Flow    // definition of temp var
    522 	use     *Flow    // use list, chained through Flow.data
    523 	merge   *TempVar // merge var with this one
    524 	start   int64    // smallest Prog.pc in live range
    525 	end     int64    // largest Prog.pc in live range
    526 	addr    uint8    // address taken - no accurate end
    527 	removed uint8    // removed from program
    528 }
    529 
    530 type startcmp []*TempVar
    531 
    532 func (x startcmp) Len() int {
    533 	return len(x)
    534 }
    535 
    536 func (x startcmp) Swap(i, j int) {
    537 	x[i], x[j] = x[j], x[i]
    538 }
    539 
    540 func (x startcmp) Less(i, j int) bool {
    541 	a := x[i]
    542 	b := x[j]
    543 
    544 	if a.start < b.start {
    545 		return true
    546 	}
    547 	if a.start > b.start {
    548 		return false
    549 	}
    550 
    551 	// Order what's left by id or symbol name,
    552 	// just so that sort is forced into a specific ordering,
    553 	// so that the result of the sort does not depend on
    554 	// the sort implementation.
    555 	if a.def != b.def {
    556 		return int(a.def.Id-b.def.Id) < 0
    557 	}
    558 	if a.node != b.node {
    559 		return stringsCompare(a.node.Sym.Name, b.node.Sym.Name) < 0
    560 	}
    561 	return false
    562 }
    563 
    564 // Is n available for merging?
    565 func canmerge(n *Node) bool {
    566 	return n.Class == PAUTO && strings.HasPrefix(n.Sym.Name, "autotmp")
    567 }
    568 
    569 func mergetemp(firstp *obj.Prog) {
    570 	const (
    571 		debugmerge = 0
    572 	)
    573 
    574 	g := Flowstart(firstp, nil)
    575 	if g == nil {
    576 		return
    577 	}
    578 
    579 	// Build list of all mergeable variables.
    580 	nvar := 0
    581 	for l := Curfn.Func.Dcl; l != nil; l = l.Next {
    582 		if canmerge(l.N) {
    583 			nvar++
    584 		}
    585 	}
    586 
    587 	var_ := make([]TempVar, nvar)
    588 	nvar = 0
    589 	var n *Node
    590 	var v *TempVar
    591 	for l := Curfn.Func.Dcl; l != nil; l = l.Next {
    592 		n = l.N
    593 		if canmerge(n) {
    594 			v = &var_[nvar]
    595 			nvar++
    596 			n.SetOpt(v)
    597 			v.node = n
    598 		}
    599 	}
    600 
    601 	// Build list of uses.
    602 	// We assume that the earliest reference to a temporary is its definition.
    603 	// This is not true of variables in general but our temporaries are all
    604 	// single-use (that's why we have so many!).
    605 	for f := g.Start; f != nil; f = f.Link {
    606 		p := f.Prog
    607 		if p.From.Node != nil && ((p.From.Node).(*Node)).Opt() != nil && p.To.Node != nil && ((p.To.Node).(*Node)).Opt() != nil {
    608 			Fatal("double node %v", p)
    609 		}
    610 		v = nil
    611 		n, _ = p.From.Node.(*Node)
    612 		if n != nil {
    613 			v, _ = n.Opt().(*TempVar)
    614 		}
    615 		if v == nil {
    616 			n, _ = p.To.Node.(*Node)
    617 			if n != nil {
    618 				v, _ = n.Opt().(*TempVar)
    619 			}
    620 		}
    621 		if v != nil {
    622 			if v.def == nil {
    623 				v.def = f
    624 			}
    625 			f.Data = v.use
    626 			v.use = f
    627 			if n == p.From.Node && (p.Info.Flags&LeftAddr != 0) {
    628 				v.addr = 1
    629 			}
    630 		}
    631 	}
    632 
    633 	if debugmerge > 1 && Debug['v'] != 0 {
    634 		Dumpit("before", g.Start, 0)
    635 	}
    636 
    637 	nkill := 0
    638 
    639 	// Special case.
    640 	for i := 0; i < len(var_); i++ {
    641 		v = &var_[i]
    642 		if v.addr != 0 {
    643 			continue
    644 		}
    645 
    646 		// Used in only one instruction, which had better be a write.
    647 		f := v.use
    648 		if f != nil && f.Data.(*Flow) == nil {
    649 			p := f.Prog
    650 			if p.To.Node == v.node && (p.Info.Flags&RightWrite != 0) && p.Info.Flags&RightRead == 0 {
    651 				p.As = obj.ANOP
    652 				p.To = obj.Addr{}
    653 				v.removed = 1
    654 				if debugmerge > 0 && Debug['v'] != 0 {
    655 					fmt.Printf("drop write-only %v\n", v.node.Sym)
    656 				}
    657 			} else {
    658 				Fatal("temp used and not set: %v", p)
    659 			}
    660 			nkill++
    661 			continue
    662 		}
    663 
    664 		// Written in one instruction, read in the next, otherwise unused,
    665 		// no jumps to the next instruction. Happens mainly in 386 compiler.
    666 		f = v.use
    667 		if f != nil && f.Link == f.Data.(*Flow) && (f.Data.(*Flow)).Data.(*Flow) == nil && Uniqp(f.Link) == f {
    668 			p := f.Prog
    669 			p1 := f.Link.Prog
    670 			const (
    671 				SizeAny = SizeB | SizeW | SizeL | SizeQ | SizeF | SizeD
    672 			)
    673 			if p.From.Node == v.node && p1.To.Node == v.node && (p.Info.Flags&Move != 0) && (p.Info.Flags|p1.Info.Flags)&(LeftAddr|RightAddr) == 0 && p.Info.Flags&SizeAny == p1.Info.Flags&SizeAny {
    674 				p1.From = p.From
    675 				Thearch.Excise(f)
    676 				v.removed = 1
    677 				if debugmerge > 0 && Debug['v'] != 0 {
    678 					fmt.Printf("drop immediate-use %v\n", v.node.Sym)
    679 				}
    680 			}
    681 
    682 			nkill++
    683 			continue
    684 		}
    685 	}
    686 
    687 	// Traverse live range of each variable to set start, end.
    688 	// Each flood uses a new value of gen so that we don't have
    689 	// to clear all the r->active words after each variable.
    690 	gen := int32(0)
    691 
    692 	for i := 0; i < len(var_); i++ {
    693 		v = &var_[i]
    694 		gen++
    695 		for f := v.use; f != nil; f = f.Data.(*Flow) {
    696 			mergewalk(v, f, uint32(gen))
    697 		}
    698 		if v.addr != 0 {
    699 			gen++
    700 			for f := v.use; f != nil; f = f.Data.(*Flow) {
    701 				varkillwalk(v, f, uint32(gen))
    702 			}
    703 		}
    704 	}
    705 
    706 	// Sort variables by start.
    707 	bystart := make([]*TempVar, len(var_))
    708 
    709 	for i := 0; i < len(var_); i++ {
    710 		bystart[i] = &var_[i]
    711 	}
    712 	sort.Sort(startcmp(bystart[:len(var_)]))
    713 
    714 	// List of in-use variables, sorted by end, so that the ones that
    715 	// will last the longest are the earliest ones in the array.
    716 	// The tail inuse[nfree:] holds no-longer-used variables.
    717 	// In theory we should use a sorted tree so that insertions are
    718 	// guaranteed O(log n) and then the loop is guaranteed O(n log n).
    719 	// In practice, it doesn't really matter.
    720 	inuse := make([]*TempVar, len(var_))
    721 
    722 	ninuse := 0
    723 	nfree := len(var_)
    724 	var t *Type
    725 	var v1 *TempVar
    726 	var j int
    727 	for i := 0; i < len(var_); i++ {
    728 		v = bystart[i]
    729 		if debugmerge > 0 && Debug['v'] != 0 {
    730 			fmt.Printf("consider %v: removed=%d\n", Nconv(v.node, obj.FmtSharp), v.removed)
    731 		}
    732 
    733 		if v.removed != 0 {
    734 			continue
    735 		}
    736 
    737 		// Expire no longer in use.
    738 		for ninuse > 0 && inuse[ninuse-1].end < v.start {
    739 			ninuse--
    740 			v1 = inuse[ninuse]
    741 			nfree--
    742 			inuse[nfree] = v1
    743 		}
    744 
    745 		if debugmerge > 0 && Debug['v'] != 0 {
    746 			fmt.Printf("consider %v: removed=%d nfree=%d nvar=%d\n", Nconv(v.node, obj.FmtSharp), v.removed, nfree, len(var_))
    747 		}
    748 
    749 		// Find old temp to reuse if possible.
    750 		t = v.node.Type
    751 
    752 		for j = nfree; j < len(var_); j++ {
    753 			v1 = inuse[j]
    754 			if debugmerge > 0 && Debug['v'] != 0 {
    755 				fmt.Printf("consider %v: maybe %v: type=%v,%v addrtaken=%v,%v\n", Nconv(v.node, obj.FmtSharp), Nconv(v1.node, obj.FmtSharp), t, v1.node.Type, v.node.Addrtaken, v1.node.Addrtaken)
    756 			}
    757 
    758 			// Require the types to match but also require the addrtaken bits to match.
    759 			// If a variable's address is taken, that disables registerization for the individual
    760 			// words of the variable (for example, the base,len,cap of a slice).
    761 			// We don't want to merge a non-addressed var with an addressed one and
    762 			// inhibit registerization of the former.
    763 			if Eqtype(t, v1.node.Type) && v.node.Addrtaken == v1.node.Addrtaken {
    764 				inuse[j] = inuse[nfree]
    765 				nfree++
    766 				if v1.merge != nil {
    767 					v.merge = v1.merge
    768 				} else {
    769 					v.merge = v1
    770 				}
    771 				nkill++
    772 				break
    773 			}
    774 		}
    775 
    776 		// Sort v into inuse.
    777 		j = ninuse
    778 		ninuse++
    779 
    780 		for j > 0 && inuse[j-1].end < v.end {
    781 			inuse[j] = inuse[j-1]
    782 			j--
    783 		}
    784 
    785 		inuse[j] = v
    786 	}
    787 
    788 	if debugmerge > 0 && Debug['v'] != 0 {
    789 		fmt.Printf("%v [%d - %d]\n", Curfn.Func.Nname.Sym, len(var_), nkill)
    790 		var v *TempVar
    791 		for i := 0; i < len(var_); i++ {
    792 			v = &var_[i]
    793 			fmt.Printf("var %v %v %d-%d", Nconv(v.node, obj.FmtSharp), v.node.Type, v.start, v.end)
    794 			if v.addr != 0 {
    795 				fmt.Printf(" addr=1")
    796 			}
    797 			if v.removed != 0 {
    798 				fmt.Printf(" dead=1")
    799 			}
    800 			if v.merge != nil {
    801 				fmt.Printf(" merge %v", Nconv(v.merge.node, obj.FmtSharp))
    802 			}
    803 			if v.start == v.end && v.def != nil {
    804 				fmt.Printf(" %v", v.def.Prog)
    805 			}
    806 			fmt.Printf("\n")
    807 		}
    808 
    809 		if debugmerge > 1 && Debug['v'] != 0 {
    810 			Dumpit("after", g.Start, 0)
    811 		}
    812 	}
    813 
    814 	// Update node references to use merged temporaries.
    815 	for f := g.Start; f != nil; f = f.Link {
    816 		p := f.Prog
    817 		n, _ = p.From.Node.(*Node)
    818 		if n != nil {
    819 			v, _ = n.Opt().(*TempVar)
    820 			if v != nil && v.merge != nil {
    821 				p.From.Node = v.merge.node
    822 			}
    823 		}
    824 		n, _ = p.To.Node.(*Node)
    825 		if n != nil {
    826 			v, _ = n.Opt().(*TempVar)
    827 			if v != nil && v.merge != nil {
    828 				p.To.Node = v.merge.node
    829 			}
    830 		}
    831 	}
    832 
    833 	// Delete merged nodes from declaration list.
    834 	var l *NodeList
    835 	for lp := &Curfn.Func.Dcl; ; {
    836 		l = *lp
    837 		if l == nil {
    838 			break
    839 		}
    840 
    841 		Curfn.Func.Dcl.End = l
    842 		n = l.N
    843 		v, _ = n.Opt().(*TempVar)
    844 		if v != nil && (v.merge != nil || v.removed != 0) {
    845 			*lp = l.Next
    846 			continue
    847 		}
    848 
    849 		lp = &l.Next
    850 	}
    851 
    852 	// Clear aux structures.
    853 	for i := 0; i < len(var_); i++ {
    854 		var_[i].node.SetOpt(nil)
    855 	}
    856 
    857 	Flowend(g)
    858 }
    859 
    860 func mergewalk(v *TempVar, f0 *Flow, gen uint32) {
    861 	var p *obj.Prog
    862 	var f1 *Flow
    863 
    864 	for f1 = f0; f1 != nil; f1 = f1.P1 {
    865 		if uint32(f1.Active) == gen {
    866 			break
    867 		}
    868 		f1.Active = int32(gen)
    869 		p = f1.Prog
    870 		if v.end < p.Pc {
    871 			v.end = p.Pc
    872 		}
    873 		if f1 == v.def {
    874 			v.start = p.Pc
    875 			break
    876 		}
    877 	}
    878 
    879 	var f2 *Flow
    880 	for f := f0; f != f1; f = f.P1 {
    881 		for f2 = f.P2; f2 != nil; f2 = f2.P2link {
    882 			mergewalk(v, f2, gen)
    883 		}
    884 	}
    885 }
    886 
    887 func varkillwalk(v *TempVar, f0 *Flow, gen uint32) {
    888 	var p *obj.Prog
    889 	var f1 *Flow
    890 
    891 	for f1 = f0; f1 != nil; f1 = f1.S1 {
    892 		if uint32(f1.Active) == gen {
    893 			break
    894 		}
    895 		f1.Active = int32(gen)
    896 		p = f1.Prog
    897 		if v.end < p.Pc {
    898 			v.end = p.Pc
    899 		}
    900 		if v.start > p.Pc {
    901 			v.start = p.Pc
    902 		}
    903 		if p.As == obj.ARET || (p.As == obj.AVARKILL && p.To.Node == v.node) {
    904 			break
    905 		}
    906 	}
    907 
    908 	for f := f0; f != f1; f = f.S1 {
    909 		varkillwalk(v, f.S2, gen)
    910 	}
    911 }
    912 
    913 // Eliminate redundant nil pointer checks.
    914 //
    915 // The code generation pass emits a CHECKNIL for every possibly nil pointer.
    916 // This pass removes a CHECKNIL if every predecessor path has already
    917 // checked this value for nil.
    918 //
    919 // Simple backwards flood from check to definition.
    920 // Run prog loop backward from end of program to beginning to avoid quadratic
    921 // behavior removing a run of checks.
    922 //
    923 // Assume that stack variables with address not taken can be loaded multiple times
    924 // from memory without being rechecked. Other variables need to be checked on
    925 // each load.
    926 
    927 var killed int // f->data is either nil or &killed
    928 
    929 func nilopt(firstp *obj.Prog) {
    930 	g := Flowstart(firstp, nil)
    931 	if g == nil {
    932 		return
    933 	}
    934 
    935 	if Debug_checknil > 1 { /* || strcmp(curfn->nname->sym->name, "f1") == 0 */
    936 		Dumpit("nilopt", g.Start, 0)
    937 	}
    938 
    939 	ncheck := 0
    940 	nkill := 0
    941 	var p *obj.Prog
    942 	for f := g.Start; f != nil; f = f.Link {
    943 		p = f.Prog
    944 		if p.As != obj.ACHECKNIL || !Thearch.Regtyp(&p.From) {
    945 			continue
    946 		}
    947 		ncheck++
    948 		if Thearch.Stackaddr(&p.From) {
    949 			if Debug_checknil != 0 && p.Lineno > 1 {
    950 				Warnl(int(p.Lineno), "removed nil check of SP address")
    951 			}
    952 			f.Data = &killed
    953 			continue
    954 		}
    955 
    956 		nilwalkfwd(f)
    957 		if f.Data != nil {
    958 			if Debug_checknil != 0 && p.Lineno > 1 {
    959 				Warnl(int(p.Lineno), "removed nil check before indirect")
    960 			}
    961 			continue
    962 		}
    963 
    964 		nilwalkback(f)
    965 		if f.Data != nil {
    966 			if Debug_checknil != 0 && p.Lineno > 1 {
    967 				Warnl(int(p.Lineno), "removed repeated nil check")
    968 			}
    969 			continue
    970 		}
    971 	}
    972 
    973 	for f := g.Start; f != nil; f = f.Link {
    974 		if f.Data != nil {
    975 			nkill++
    976 			Thearch.Excise(f)
    977 		}
    978 	}
    979 
    980 	Flowend(g)
    981 
    982 	if Debug_checknil > 1 {
    983 		fmt.Printf("%v: removed %d of %d nil checks\n", Curfn.Func.Nname.Sym, nkill, ncheck)
    984 	}
    985 }
    986 
    987 func nilwalkback(fcheck *Flow) {
    988 	for f := fcheck; f != nil; f = Uniqp(f) {
    989 		p := f.Prog
    990 		if (p.Info.Flags&RightWrite != 0) && Thearch.Sameaddr(&p.To, &fcheck.Prog.From) {
    991 			// Found initialization of value we're checking for nil.
    992 			// without first finding the check, so this one is unchecked.
    993 			return
    994 		}
    995 
    996 		if f != fcheck && p.As == obj.ACHECKNIL && Thearch.Sameaddr(&p.From, &fcheck.Prog.From) {
    997 			fcheck.Data = &killed
    998 			return
    999 		}
   1000 	}
   1001 }
   1002 
   1003 // Here is a more complex version that scans backward across branches.
   1004 // It assumes fcheck->kill = 1 has been set on entry, and its job is to find a reason
   1005 // to keep the check (setting fcheck->kill = 0).
   1006 // It doesn't handle copying of aggregates as well as I would like,
   1007 // nor variables with their address taken,
   1008 // and it's too subtle to turn on this late in Go 1.2. Perhaps for Go 1.3.
   1009 /*
   1010 for(f1 = f0; f1 != nil; f1 = f1->p1) {
   1011 	if(f1->active == gen)
   1012 		break;
   1013 	f1->active = gen;
   1014 	p = f1->prog;
   1015 
   1016 	// If same check, stop this loop but still check
   1017 	// alternate predecessors up to this point.
   1018 	if(f1 != fcheck && p->as == ACHECKNIL && thearch.sameaddr(&p->from, &fcheck->prog->from))
   1019 		break;
   1020 
   1021 	if((p.Info.flags & RightWrite) && thearch.sameaddr(&p->to, &fcheck->prog->from)) {
   1022 		// Found initialization of value we're checking for nil.
   1023 		// without first finding the check, so this one is unchecked.
   1024 		fcheck->kill = 0;
   1025 		return;
   1026 	}
   1027 
   1028 	if(f1->p1 == nil && f1->p2 == nil) {
   1029 		print("lost pred for %v\n", fcheck->prog);
   1030 		for(f1=f0; f1!=nil; f1=f1->p1) {
   1031 			thearch.proginfo(&info, f1->prog);
   1032 			print("\t%v %d %d %D %D\n", r1->prog, info.flags&RightWrite, thearch.sameaddr(&f1->prog->to, &fcheck->prog->from), &f1->prog->to, &fcheck->prog->from);
   1033 		}
   1034 		fatal("lost pred trail");
   1035 	}
   1036 }
   1037 
   1038 for(f = f0; f != f1; f = f->p1)
   1039 	for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
   1040 		nilwalkback(fcheck, f2, gen);
   1041 */
   1042 
   1043 func nilwalkfwd(fcheck *Flow) {
   1044 	// If the path down from rcheck dereferences the address
   1045 	// (possibly with a small offset) before writing to memory
   1046 	// and before any subsequent checks, it's okay to wait for
   1047 	// that implicit check. Only consider this basic block to
   1048 	// avoid problems like:
   1049 	//	_ = *x // should panic
   1050 	//	for {} // no writes but infinite loop may be considered visible
   1051 
   1052 	var last *Flow
   1053 	for f := Uniqs(fcheck); f != nil; f = Uniqs(f) {
   1054 		p := f.Prog
   1055 		if (p.Info.Flags&LeftRead != 0) && Thearch.Smallindir(&p.From, &fcheck.Prog.From) {
   1056 			fcheck.Data = &killed
   1057 			return
   1058 		}
   1059 
   1060 		if (p.Info.Flags&(RightRead|RightWrite) != 0) && Thearch.Smallindir(&p.To, &fcheck.Prog.From) {
   1061 			fcheck.Data = &killed
   1062 			return
   1063 		}
   1064 
   1065 		// Stop if another nil check happens.
   1066 		if p.As == obj.ACHECKNIL {
   1067 			return
   1068 		}
   1069 
   1070 		// Stop if value is lost.
   1071 		if (p.Info.Flags&RightWrite != 0) && Thearch.Sameaddr(&p.To, &fcheck.Prog.From) {
   1072 			return
   1073 		}
   1074 
   1075 		// Stop if memory write.
   1076 		if (p.Info.Flags&RightWrite != 0) && !Thearch.Regtyp(&p.To) {
   1077 			return
   1078 		}
   1079 
   1080 		// Stop if we jump backward.
   1081 		if last != nil && f.Id <= last.Id {
   1082 			return
   1083 		}
   1084 		last = f
   1085 	}
   1086 }
   1087