github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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 for i, v := range b.ControlValues() { 21 if v.Op == OpCopy { 22 b.ReplaceControl(i, v.Args[0]) 23 } 24 } 25 } 26 27 // Update named values. 28 for _, name := range f.Names { 29 values := f.NamedValues[name] 30 for i, v := range values { 31 if v.Op == OpCopy { 32 values[i] = v.Args[0] 33 } 34 } 35 } 36 } 37 38 // copySource returns the (non-copy) op which is the 39 // ultimate source of v. v must be a copy op. 40 func copySource(v *Value) *Value { 41 w := v.Args[0] 42 43 // This loop is just: 44 // for w.Op == OpCopy { 45 // w = w.Args[0] 46 // } 47 // but we take some extra care to make sure we 48 // don't get stuck in an infinite loop. 49 // Infinite copy loops may happen in unreachable code. 50 // (TODO: or can they? Needs a test.) 51 slow := w 52 var advance bool 53 for w.Op == OpCopy { 54 w = w.Args[0] 55 if w == slow { 56 w.reset(OpUnknown) 57 break 58 } 59 if advance { 60 slow = slow.Args[0] 61 } 62 advance = !advance 63 } 64 65 // The answer is w. Update all the copies we saw 66 // to point directly to w. Doing this update makes 67 // sure that we don't end up doing O(n^2) work 68 // for a chain of n copies. 69 for v != w { 70 x := v.Args[0] 71 v.SetArg(0, w) 72 v = x 73 } 74 return w 75 } 76 77 // copyelimValue ensures that no args of v are copies. 78 func copyelimValue(v *Value) { 79 for i, a := range v.Args { 80 if a.Op == OpCopy { 81 v.SetArg(i, copySource(a)) 82 } 83 } 84 }