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
5package ssa
6
7import (
8	"math/bits"
9)
10
11// Code to compute lowest common ancestors in the dominator tree.
12// https://en.wikipedia.org/wiki/Lowest_common_ancestor
13// https://en.wikipedia.org/wiki/Range_minimum_query#Solution_using_constant_time_and_linearithmic_space
14
15// lcaRange is a data structure that can compute lowest common ancestor queries
16// in O(n lg n) precomputed space and O(1) time per query.
17type lcaRange struct {
18	// Additional information about each block (indexed by block ID).
19	blocks []lcaRangeBlock
20
21	// Data structure for range minimum queries.
22	// rangeMin[k][i] contains the ID of the minimum depth block
23	// in the Euler tour from positions i to i+1<<k-1, inclusive.
24	rangeMin [][]ID
25}
26
27type lcaRangeBlock struct {
28	b          *Block
29	parent     ID    // parent in dominator tree.  0 = no parent (entry or unreachable)
30	firstChild ID    // first child in dominator tree
31	sibling    ID    // next child of parent
32	pos        int32 // an index in the Euler tour where this block appears (any one of its occurrences)
33	depth      int32 // depth in dominator tree (root=0, its children=1, etc.)
34}
35
36func makeLCArange(f *Func) *lcaRange {
37	dom := f.Idom()
38
39	// Build tree
40	blocks := make([]lcaRangeBlock, f.NumBlocks())
41	for _, b := range f.Blocks {
42		blocks[b.ID].b = b
43		if dom[b.ID] == nil {
44			continue // entry or unreachable
45		}
46		parent := dom[b.ID].ID
47		blocks[b.ID].parent = parent
48		blocks[b.ID].sibling = blocks[parent].firstChild
49		blocks[parent].firstChild = b.ID
50	}
51
52	// Compute euler tour ordering.
53	// Each reachable block will appear #children+1 times in the tour.
54	tour := make([]ID, 0, f.NumBlocks()*2-1)
55	type queueEntry struct {
56		bid ID // block to work on
57		cid ID // child we're already working on (0 = haven't started yet)
58	}
59	q := []queueEntry{{f.Entry.ID, 0}}
60	for len(q) > 0 {
61		n := len(q) - 1
62		bid := q[n].bid
63		cid := q[n].cid
64		q = q[:n]
65
66		// Add block to tour.
67		blocks[bid].pos = int32(len(tour))
68		tour = append(tour, bid)
69
70		// Proceed down next child edge (if any).
71		if cid == 0 {
72			// This is our first visit to b. Set its depth.
73			blocks[bid].depth = blocks[blocks[bid].parent].depth + 1
74			// Then explore its first child.
75			cid = blocks[bid].firstChild
76		} else {
77			// We've seen b before. Explore the next child.
78			cid = blocks[cid].sibling
79		}
80		if cid != 0 {
81			q = append(q, queueEntry{bid, cid}, queueEntry{cid, 0})
82		}
83	}
84
85	// Compute fast range-minimum query data structure
86	rangeMin := make([][]ID, 0, bits.Len64(uint64(len(tour))))
87	rangeMin = append(rangeMin, tour) // 1-size windows are just the tour itself.
88	for logS, s := 1, 2; s < len(tour); logS, s = logS+1, s*2 {
89		r := make([]ID, len(tour)-s+1)
90		for i := 0; i < len(tour)-s+1; i++ {
91			bid := rangeMin[logS-1][i]
92			bid2 := rangeMin[logS-1][i+s/2]
93			if blocks[bid2].depth < blocks[bid].depth {
94				bid = bid2
95			}
96			r[i] = bid
97		}
98		rangeMin = append(rangeMin, r)
99	}
100
101	return &lcaRange{blocks: blocks, rangeMin: rangeMin}
102}
103
104// find returns the lowest common ancestor of a and b.
105func (lca *lcaRange) find(a, b *Block) *Block {
106	if a == b {
107		return a
108	}
109	// Find the positions of a and b in the Euler tour.
110	p1 := lca.blocks[a.ID].pos
111	p2 := lca.blocks[b.ID].pos
112	if p1 > p2 {
113		p1, p2 = p2, p1
114	}
115
116	// The lowest common ancestor is the minimum depth block
117	// on the tour from p1 to p2.  We've precomputed minimum
118	// depth blocks for powers-of-two subsequences of the tour.
119	// Combine the right two precomputed values to get the answer.
120	logS := uint(log64(int64(p2 - p1)))
121	bid1 := lca.rangeMin[logS][p1]
122	bid2 := lca.rangeMin[logS][p2-1<<logS+1]
123	if lca.blocks[bid1].depth < lca.blocks[bid2].depth {
124		return lca.blocks[bid1].b
125	}
126	return lca.blocks[bid2].b
127}
128