SPIRV-Tools/source/util/bit_vector.h
Steven Perron 2c0ce87210
Vector DCE (#1512)
Introduce a pass that does a DCE type analysis for vector elements
instead of the whole vector as a single element.

It will then rewrite instructions that are not used with something else.
For example, an instruction whose value are not used, even though it is
referenced, is replaced with an OpUndef.
2018-04-23 11:13:07 -04:00

120 lines
3.3 KiB
C++

// Copyright (c) 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSPIRV_UTILS_BIT_VECTOR_H_
#define LIBSPIRV_UTILS_BIT_VECTOR_H_
#include <cstdint>
#include <iosfwd>
#include <vector>
namespace spvtools {
namespace utils {
// Implements a bit vector class.
//
// All bits default to zero, and the upper bound is 2^32-1.
class BitVector {
private:
using BitContainer = uint64_t;
enum { kBitContainerSize = 64 };
enum { kInitialNumBits = 1024 };
public:
// Creates a bit vector contianing 0s.
BitVector(uint32_t reserved_size = kInitialNumBits)
: bits_((reserved_size - 1) / kBitContainerSize + 1, 0) {}
// Sets the |i|th bit to 1. Returns the |i|th bit before it was set.
bool Set(uint32_t i) {
uint32_t element_index = i / kBitContainerSize;
uint32_t bit_in_element = i % kBitContainerSize;
if (element_index >= bits_.size()) {
bits_.resize(element_index + 1, 0);
}
BitContainer original = bits_[element_index];
BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element;
if ((original & ith_bit) != 0) {
return true;
} else {
bits_[element_index] = original | ith_bit;
return false;
}
}
// Sets the |i|th bit to 0. Return the |i|th bit before it was cleared.
bool Clear(uint32_t i) {
uint32_t element_index = i / kBitContainerSize;
uint32_t bit_in_element = i % kBitContainerSize;
if (element_index >= bits_.size()) {
return false;
}
BitContainer original = bits_[element_index];
BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element;
if ((original & ith_bit) == 0) {
return false;
} else {
bits_[element_index] = original & (~ith_bit);
return true;
}
}
// Returns the |i|th bit.
bool Get(uint32_t i) const {
uint32_t element_index = i / kBitContainerSize;
uint32_t bit_in_element = i % kBitContainerSize;
if (element_index >= bits_.size()) {
return false;
}
return (bits_[element_index] &
(static_cast<BitContainer>(1) << bit_in_element)) != 0;
}
// Returns true if every bit is 0.
bool Empty() const {
for (BitContainer b : bits_) {
if (b != 0) {
return false;
}
}
return true;
}
// Print a report on the densicy of the bit vector, number of 1 bits, number
// of bytes, and average bytes for 1 bit, to |out|.
void ReportDensity(std::ostream& out);
friend std::ostream& operator<<(std::ostream&, const BitVector&);
// Performs a bitwise-or operation on |this| and |that|, storing the result in
// |this|. Return true if |this| changed.
bool Or(const BitVector& that);
private:
std::vector<BitContainer> bits_;
};
} // namespace utils
} // namespace spvtools
#endif // LIBSPIRV_UTILS_BIT_VECTOR_H_