github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/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  }