github.com/golangci/go-tools@v0.0.0-20190318060251-af6baa5dc196/functions/loops.go (about) 1 package functions 2 3 import "github.com/golangci/go-tools/ssa" 4 5 type Loop map[*ssa.BasicBlock]bool 6 7 func findLoops(fn *ssa.Function) []Loop { 8 if fn.Blocks == nil { 9 return nil 10 } 11 tree := fn.DomPreorder() 12 var sets []Loop 13 for _, h := range tree { 14 for _, n := range h.Preds { 15 if !h.Dominates(n) { 16 continue 17 } 18 // n is a back-edge to h 19 // h is the loop header 20 if n == h { 21 sets = append(sets, Loop{n: true}) 22 continue 23 } 24 set := Loop{h: true, n: true} 25 for _, b := range allPredsBut(n, h, nil) { 26 set[b] = true 27 } 28 sets = append(sets, set) 29 } 30 } 31 return sets 32 } 33 34 func allPredsBut(b, but *ssa.BasicBlock, list []*ssa.BasicBlock) []*ssa.BasicBlock { 35 outer: 36 for _, pred := range b.Preds { 37 if pred == but { 38 continue 39 } 40 for _, p := range list { 41 // TODO improve big-o complexity of this function 42 if pred == p { 43 continue outer 44 } 45 } 46 list = append(list, pred) 47 list = allPredsBut(pred, but, list) 48 } 49 return list 50 }