Source file src/cmd/compile/internal/ssa/phielim.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 // phielim eliminates redundant phi values from f. 8 // A phi is redundant if its arguments are all equal. For 9 // purposes of counting, ignore the phi itself. Both of 10 // these phis are redundant: 11 // v = phi(x,x,x) 12 // v = phi(x,v,x,v) 13 // We repeat this process to also catch situations like: 14 // v = phi(x, phi(x, x), phi(x, v)) 15 // TODO: Can we also simplify cases like: 16 // v = phi(v, w, x) 17 // w = phi(v, w, x) 18 // and would that be useful? 19 func phielim(f *Func) { 20 for { 21 change := false 22 for _, b := range f.Blocks { 23 for _, v := range b.Values { 24 copyelimValue(v) 25 change = phielimValue(v) || change 26 } 27 } 28 if !change { 29 break 30 } 31 } 32 } 33 34 // phielimValue tries to convert the phi v to a copy. 35 func phielimValue(v *Value) bool { 36 if v.Op != OpPhi { 37 return false 38 } 39 40 // If there are two distinct args of v which 41 // are not v itself, then the phi must remain. 42 // Otherwise, we can replace it with a copy. 43 var w *Value 44 for _, x := range v.Args { 45 if x == v { 46 continue 47 } 48 if x == w { 49 continue 50 } 51 if w != nil { 52 return false 53 } 54 w = x 55 } 56 57 if w == nil { 58 // v references only itself. It must be in 59 // a dead code loop. Don't bother modifying it. 60 return false 61 } 62 v.Op = OpCopy 63 v.SetArgs1(w) 64 f := v.Block.Func 65 if f.pass.debug > 0 { 66 f.Warnl(v.Pos, "eliminated phi") 67 } 68 return true 69 } 70