liyujie
2025-08-28 d9927380ed7c8366f762049be9f3fee225860833
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
package ssa
 
import "testing"
 
type lca interface {
   find(a, b *Block) *Block
}
 
func lcaEqual(f *Func, lca1, lca2 lca) bool {
   for _, b := range f.Blocks {
       for _, c := range f.Blocks {
           if lca1.find(b, c) != lca2.find(b, c) {
               return false
           }
       }
   }
   return true
}
 
func testLCAgen(t *testing.T, bg blockGen, size int) {
   c := testConfig(t)
   fun := c.Fun("entry", bg(size)...)
   CheckFunc(fun.f)
   if size == 4 {
       t.Logf(fun.f.String())
   }
   lca1 := makeLCArange(fun.f)
   lca2 := makeLCAeasy(fun.f)
   for _, b := range fun.f.Blocks {
       for _, c := range fun.f.Blocks {
           l1 := lca1.find(b, c)
           l2 := lca2.find(b, c)
           if l1 != l2 {
               t.Errorf("lca(%s,%s)=%s, want %s", b, c, l1, l2)
           }
       }
   }
}
 
func TestLCALinear(t *testing.T) {
   testLCAgen(t, genLinear, 10)
   testLCAgen(t, genLinear, 100)
}
 
func TestLCAFwdBack(t *testing.T) {
   testLCAgen(t, genFwdBack, 10)
   testLCAgen(t, genFwdBack, 100)
}
 
func TestLCAManyPred(t *testing.T) {
   testLCAgen(t, genManyPred, 10)
   testLCAgen(t, genManyPred, 100)
}
 
func TestLCAMaxPred(t *testing.T) {
   testLCAgen(t, genMaxPred, 10)
   testLCAgen(t, genMaxPred, 100)
}
 
func TestLCAMaxPredValue(t *testing.T) {
   testLCAgen(t, genMaxPredValue, 10)
   testLCAgen(t, genMaxPredValue, 100)
}
 
// Simple implementation of LCA to compare against.
type lcaEasy struct {
   parent []*Block
}
 
func makeLCAeasy(f *Func) *lcaEasy {
   return &lcaEasy{parent: dominators(f)}
}
 
func (lca *lcaEasy) find(a, b *Block) *Block {
   da := lca.depth(a)
   db := lca.depth(b)
   for da > db {
       da--
       a = lca.parent[a.ID]
   }
   for da < db {
       db--
       b = lca.parent[b.ID]
   }
   for a != b {
       a = lca.parent[a.ID]
       b = lca.parent[b.ID]
   }
   return a
}
 
func (lca *lcaEasy) depth(b *Block) int {
   n := 0
   for b != nil {
       b = lca.parent[b.ID]
       n++
   }
   return n
}