github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/compile/internal/ssa/copyelim.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  // copyelim removes all copies from f.
     8  func copyelim(f *Func) {
     9  	for _, b := range f.Blocks {
    10  		for _, v := range b.Values {
    11  			copyelimValue(v)
    12  		}
    13  		v := b.Control
    14  		if v != nil && v.Op == OpCopy {
    15  			for v.Op == OpCopy {
    16  				v = v.Args[0]
    17  			}
    18  			b.SetControl(v)
    19  		}
    20  	}
    21  
    22  	// Update named values.
    23  	for _, name := range f.Names {
    24  		values := f.NamedValues[name]
    25  		for i, v := range values {
    26  			x := v
    27  			for x.Op == OpCopy {
    28  				x = x.Args[0]
    29  			}
    30  			if x != v {
    31  				values[i] = x
    32  			}
    33  		}
    34  	}
    35  }
    36  
    37  func copyelimValue(v *Value) bool {
    38  	// elide any copies generated during rewriting
    39  	changed := false
    40  	for i, a := range v.Args {
    41  		if a.Op != OpCopy {
    42  			continue
    43  		}
    44  		// Rewriting can generate OpCopy loops.
    45  		// They are harmless (see removePredecessor),
    46  		// but take care to stop if we find a cycle.
    47  		slow := a // advances every other iteration
    48  		var advance bool
    49  		for a.Op == OpCopy {
    50  			a = a.Args[0]
    51  			if slow == a {
    52  				break
    53  			}
    54  			if advance {
    55  				slow = slow.Args[0]
    56  			}
    57  			advance = !advance
    58  		}
    59  		v.SetArg(i, a)
    60  		changed = true
    61  	}
    62  	return changed
    63  }