| // Copyright 2013 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 liveness |
| |
| import "cmd/compile/internal/bitvec" |
| |
| // FNV-1 hash function constants. |
| const ( |
| h0 = 2166136261 |
| hp = 16777619 |
| ) |
| |
| // bvecSet is a set of bvecs, in initial insertion order. |
| type bvecSet struct { |
| index []int // hash -> uniq index. -1 indicates empty slot. |
| uniq []bitvec.BitVec // unique bvecs, in insertion order |
| } |
| |
| func (m *bvecSet) grow() { |
| // Allocate new index. |
| n := len(m.index) * 2 |
| if n == 0 { |
| n = 32 |
| } |
| newIndex := make([]int, n) |
| for i := range newIndex { |
| newIndex[i] = -1 |
| } |
| |
| // Rehash into newIndex. |
| for i, bv := range m.uniq { |
| h := hashbitmap(h0, bv) % uint32(len(newIndex)) |
| for { |
| j := newIndex[h] |
| if j < 0 { |
| newIndex[h] = i |
| break |
| } |
| h++ |
| if h == uint32(len(newIndex)) { |
| h = 0 |
| } |
| } |
| } |
| m.index = newIndex |
| } |
| |
| // add adds bv to the set and returns its index in m.extractUnique. |
| // The caller must not modify bv after this. |
| func (m *bvecSet) add(bv bitvec.BitVec) int { |
| if len(m.uniq)*4 >= len(m.index) { |
| m.grow() |
| } |
| |
| index := m.index |
| h := hashbitmap(h0, bv) % uint32(len(index)) |
| for { |
| j := index[h] |
| if j < 0 { |
| // New bvec. |
| index[h] = len(m.uniq) |
| m.uniq = append(m.uniq, bv) |
| return len(m.uniq) - 1 |
| } |
| jlive := m.uniq[j] |
| if bv.Eq(jlive) { |
| // Existing bvec. |
| return j |
| } |
| |
| h++ |
| if h == uint32(len(index)) { |
| h = 0 |
| } |
| } |
| } |
| |
| // extractUnique returns this slice of unique bit vectors in m, as |
| // indexed by the result of bvecSet.add. |
| func (m *bvecSet) extractUnique() []bitvec.BitVec { |
| return m.uniq |
| } |
| |
| func hashbitmap(h uint32, bv bitvec.BitVec) uint32 { |
| n := int((bv.N + 31) / 32) |
| for i := 0; i < n; i++ { |
| w := bv.B[i] |
| h = (h * hp) ^ (w & 0xff) |
| h = (h * hp) ^ ((w >> 8) & 0xff) |
| h = (h * hp) ^ ((w >> 16) & 0xff) |
| h = (h * hp) ^ ((w >> 24) & 0xff) |
| } |
| |
| return h |
| } |