1
2
3
4
5 package ssacompile
6
7 import (
8 "math/bits"
9
10 "cmd/compile/internal/ssa"
11 )
12
13
14
15
16
17
18
19 type lcaRange struct {
20
21 blocks []lcaRangeBlock
22
23
24
25
26 rangeMin [][]ssa.ID
27 }
28
29 type lcaRangeBlock struct {
30 b *ssa.Block
31 parent ssa.ID
32 firstChild ssa.ID
33 sibling ssa.ID
34 pos int32
35 depth int32
36 }
37
38 func makeLCArange(f *ssa.Func) *lcaRange {
39 dom := f.Idom()
40
41
42 blocks := make([]lcaRangeBlock, f.NumBlocks())
43 for _, b := range f.Blocks {
44 blocks[b.ID].b = b
45 if dom[b.ID] == nil {
46 continue
47 }
48 parent := dom[b.ID].ID
49 blocks[b.ID].parent = parent
50 blocks[b.ID].sibling = blocks[parent].firstChild
51 blocks[parent].firstChild = b.ID
52 }
53
54
55
56 tour := make([]ssa.ID, 0, f.NumBlocks()*2-1)
57 type queueEntry struct {
58 bid ssa.ID
59 cid ssa.ID
60 }
61 q := []queueEntry{{f.Entry.ID, 0}}
62 for len(q) > 0 {
63 n := len(q) - 1
64 bid := q[n].bid
65 cid := q[n].cid
66 q = q[:n]
67
68
69 blocks[bid].pos = int32(len(tour))
70 tour = append(tour, bid)
71
72
73 if cid == 0 {
74
75 blocks[bid].depth = blocks[blocks[bid].parent].depth + 1
76
77 cid = blocks[bid].firstChild
78 } else {
79
80 cid = blocks[cid].sibling
81 }
82 if cid != 0 {
83 q = append(q, queueEntry{bid, cid}, queueEntry{cid, 0})
84 }
85 }
86
87
88 rangeMin := make([][]ssa.ID, 0, bits.Len64(uint64(len(tour))))
89 rangeMin = append(rangeMin, tour)
90 for logS, s := 1, 2; s < len(tour); logS, s = logS+1, s*2 {
91 r := make([]ssa.ID, len(tour)-s+1)
92 for i := 0; i < len(tour)-s+1; i++ {
93 bid := rangeMin[logS-1][i]
94 bid2 := rangeMin[logS-1][i+s/2]
95 if blocks[bid2].depth < blocks[bid].depth {
96 bid = bid2
97 }
98 r[i] = bid
99 }
100 rangeMin = append(rangeMin, r)
101 }
102
103 return &lcaRange{blocks: blocks, rangeMin: rangeMin}
104 }
105
106
107 func (lca *lcaRange) find(a, b *ssa.Block) *ssa.Block {
108 if a == b {
109 return a
110 }
111
112 p1 := lca.blocks[a.ID].pos
113 p2 := lca.blocks[b.ID].pos
114 if p1 > p2 {
115 p1, p2 = p2, p1
116 }
117
118
119
120
121
122 logS := uint(ssa.Log64(int64(p2 - p1)))
123 bid1 := lca.rangeMin[logS][p1]
124 bid2 := lca.rangeMin[logS][p2-1<<logS+1]
125 if lca.blocks[bid1].depth < lca.blocks[bid2].depth {
126 return lca.blocks[bid1].b
127 }
128 return lca.blocks[bid2].b
129 }
130
View as plain text