github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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 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 }