...

Source file src/pkg/cmd/compile/internal/ssa/copyelim.go

     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 uses of OpCopy values from f.
     8	// A subsequent deadcode pass is needed to actually remove the copies.
     9	func copyelim(f *Func) {
    10		// Modify all values so no arg (including args
    11		// of OpCopy) is a copy.
    12		for _, b := range f.Blocks {
    13			for _, v := range b.Values {
    14				copyelimValue(v)
    15			}
    16		}
    17	
    18		// Update block control values.
    19		for _, b := range f.Blocks {
    20			if v := b.Control; v != nil && v.Op == OpCopy {
    21				b.SetControl(v.Args[0])
    22			}
    23		}
    24	
    25		// Update named values.
    26		for _, name := range f.Names {
    27			values := f.NamedValues[name]
    28			for i, v := range values {
    29				if v.Op == OpCopy {
    30					values[i] = v.Args[0]
    31				}
    32			}
    33		}
    34	}
    35	
    36	// copySource returns the (non-copy) op which is the
    37	// ultimate source of v.  v must be a copy op.
    38	func copySource(v *Value) *Value {
    39		w := v.Args[0]
    40	
    41		// This loop is just:
    42		// for w.Op == OpCopy {
    43		//     w = w.Args[0]
    44		// }
    45		// but we take some extra care to make sure we
    46		// don't get stuck in an infinite loop.
    47		// Infinite copy loops may happen in unreachable code.
    48		// (TODO: or can they? Needs a test.)
    49		slow := w
    50		var advance bool
    51		for w.Op == OpCopy {
    52			w = w.Args[0]
    53			if w == slow {
    54				w.reset(OpUnknown)
    55				break
    56			}
    57			if advance {
    58				slow = slow.Args[0]
    59			}
    60			advance = !advance
    61		}
    62	
    63		// The answer is w.  Update all the copies we saw
    64		// to point directly to w.  Doing this update makes
    65		// sure that we don't end up doing O(n^2) work
    66		// for a chain of n copies.
    67		for v != w {
    68			x := v.Args[0]
    69			v.SetArg(0, w)
    70			v = x
    71		}
    72		return w
    73	}
    74	
    75	// copyelimValue ensures that no args of v are copies.
    76	func copyelimValue(v *Value) {
    77		for i, a := range v.Args {
    78			if a.Op == OpCopy {
    79				v.SetArg(i, copySource(a))
    80			}
    81		}
    82	}
    83	

View as plain text