github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/liveness/bvset.go (about) 1 // Copyright 2013 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 liveness 6 7 import "github.com/go-asm/go/cmd/compile/bitvec" 8 9 // FNV-1 hash function constants. 10 const ( 11 h0 = 2166136261 12 hp = 16777619 13 ) 14 15 // bvecSet is a set of bvecs, in initial insertion order. 16 type bvecSet struct { 17 index []int // hash -> uniq index. -1 indicates empty slot. 18 uniq []bitvec.BitVec // unique bvecs, in insertion order 19 } 20 21 func (m *bvecSet) grow() { 22 // Allocate new index. 23 n := len(m.index) * 2 24 if n == 0 { 25 n = 32 26 } 27 newIndex := make([]int, n) 28 for i := range newIndex { 29 newIndex[i] = -1 30 } 31 32 // Rehash into newIndex. 33 for i, bv := range m.uniq { 34 h := hashbitmap(h0, bv) % uint32(len(newIndex)) 35 for { 36 j := newIndex[h] 37 if j < 0 { 38 newIndex[h] = i 39 break 40 } 41 h++ 42 if h == uint32(len(newIndex)) { 43 h = 0 44 } 45 } 46 } 47 m.index = newIndex 48 } 49 50 // add adds bv to the set and returns its index in m.extractUnique, 51 // and whether it is newly added. 52 // If it is newly added, the caller must not modify bv after this. 53 func (m *bvecSet) add(bv bitvec.BitVec) (int, bool) { 54 if len(m.uniq)*4 >= len(m.index) { 55 m.grow() 56 } 57 58 index := m.index 59 h := hashbitmap(h0, bv) % uint32(len(index)) 60 for { 61 j := index[h] 62 if j < 0 { 63 // New bvec. 64 index[h] = len(m.uniq) 65 m.uniq = append(m.uniq, bv) 66 return len(m.uniq) - 1, true 67 } 68 jlive := m.uniq[j] 69 if bv.Eq(jlive) { 70 // Existing bvec. 71 return j, false 72 } 73 74 h++ 75 if h == uint32(len(index)) { 76 h = 0 77 } 78 } 79 } 80 81 // extractUnique returns this slice of unique bit vectors in m, as 82 // indexed by the result of bvecSet.add. 83 func (m *bvecSet) extractUnique() []bitvec.BitVec { 84 return m.uniq 85 } 86 87 func hashbitmap(h uint32, bv bitvec.BitVec) uint32 { 88 n := int((bv.N + 31) / 32) 89 for i := 0; i < n; i++ { 90 w := bv.B[i] 91 h = (h * hp) ^ (w & 0xff) 92 h = (h * hp) ^ ((w >> 8) & 0xff) 93 h = (h * hp) ^ ((w >> 16) & 0xff) 94 h = (h * hp) ^ ((w >> 24) & 0xff) 95 } 96 97 return h 98 }