github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/compile/internal/ssa/lca_test.go (about) 1 // Copyright 2016 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 import "testing" 8 9 type lca interface { 10 find(a, b *Block) *Block 11 } 12 13 func lcaEqual(f *Func, lca1, lca2 lca) bool { 14 for _, b := range f.Blocks { 15 for _, c := range f.Blocks { 16 if lca1.find(b, c) != lca2.find(b, c) { 17 return false 18 } 19 } 20 } 21 return true 22 } 23 24 func testLCAgen(t *testing.T, bg blockGen, size int) { 25 c := testConfig(t) 26 fun := c.Fun("entry", bg(size)...) 27 CheckFunc(fun.f) 28 if size == 4 { 29 t.Logf(fun.f.String()) 30 } 31 lca1 := makeLCArange(fun.f) 32 lca2 := makeLCAeasy(fun.f) 33 for _, b := range fun.f.Blocks { 34 for _, c := range fun.f.Blocks { 35 l1 := lca1.find(b, c) 36 l2 := lca2.find(b, c) 37 if l1 != l2 { 38 t.Errorf("lca(%s,%s)=%s, want %s", b, c, l1, l2) 39 } 40 } 41 } 42 } 43 44 func TestLCALinear(t *testing.T) { 45 testLCAgen(t, genLinear, 10) 46 testLCAgen(t, genLinear, 100) 47 } 48 49 func TestLCAFwdBack(t *testing.T) { 50 testLCAgen(t, genFwdBack, 10) 51 testLCAgen(t, genFwdBack, 100) 52 } 53 54 func TestLCAManyPred(t *testing.T) { 55 testLCAgen(t, genManyPred, 10) 56 testLCAgen(t, genManyPred, 100) 57 } 58 59 func TestLCAMaxPred(t *testing.T) { 60 testLCAgen(t, genMaxPred, 10) 61 testLCAgen(t, genMaxPred, 100) 62 } 63 64 func TestLCAMaxPredValue(t *testing.T) { 65 testLCAgen(t, genMaxPredValue, 10) 66 testLCAgen(t, genMaxPredValue, 100) 67 } 68 69 // Simple implementation of LCA to compare against. 70 type lcaEasy struct { 71 parent []*Block 72 } 73 74 func makeLCAeasy(f *Func) *lcaEasy { 75 return &lcaEasy{parent: dominators(f)} 76 } 77 78 func (lca *lcaEasy) find(a, b *Block) *Block { 79 da := lca.depth(a) 80 db := lca.depth(b) 81 for da > db { 82 da-- 83 a = lca.parent[a.ID] 84 } 85 for da < db { 86 db-- 87 b = lca.parent[b.ID] 88 } 89 for a != b { 90 a = lca.parent[a.ID] 91 b = lca.parent[b.ID] 92 } 93 return a 94 } 95 96 func (lca *lcaEasy) depth(b *Block) int { 97 n := 0 98 for b != nil { 99 b = lca.parent[b.ID] 100 n++ 101 } 102 return n 103 }