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