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