LLVM 23.0.0git
Bitset.h
Go to the documentation of this file.
1//=== llvm/ADT/Bitset.h - constexpr std::bitset -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines a std::bitset like container that can be used in constexprs.
10// That constructor and many of the methods are constexpr. std::bitset doesn't
11// get constexpr methods until C++23. This class also provides a constexpr
12// constructor that accepts an initializer_list of bits to set.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_BITSET_H
17#define LLVM_ADT_BITSET_H
18
19#include "llvm/ADT/bit.h"
20#include <array>
21#include <cassert>
22#include <climits>
23#include <cstdint>
24
25namespace llvm {
26
27/// This is a constexpr reimplementation of a subset of std::bitset. It would be
28/// nice to use std::bitset directly, but it doesn't support constant
29/// initialization.
30template <unsigned NumBits> class Bitset {
31 using BitWord = uintptr_t;
32
33 static constexpr unsigned BitwordBits = sizeof(BitWord) * CHAR_BIT;
34 static constexpr unsigned RemainderNumBits = NumBits % BitwordBits;
35 static constexpr BitWord RemainderMask =
36 RemainderNumBits == 0 ? ~BitWord(0)
37 : ((BitWord(1) << RemainderNumBits) - 1);
38
39 static_assert(BitwordBits == 64 || BitwordBits == 32,
40 "Unsupported word size");
41
42 static constexpr unsigned NumWords =
43 (NumBits + BitwordBits - 1) / BitwordBits;
44
45 // Returns the index of the last word (0-based). The last word may be
46 // partially filled and requires masking to maintain the invariant that
47 // unused high bits are always zero.
48 static constexpr unsigned getLastWordIndex() { return NumWords - 1; }
49
50 using StorageType = std::array<BitWord, NumWords>;
51 StorageType Bits{};
52
53 constexpr void maskLastWord() { Bits[getLastWordIndex()] &= RemainderMask; }
54
55public:
56 explicit constexpr Bitset(
57 const std::array<uint64_t, (NumBits + 63) / 64> &B) {
58 if constexpr (sizeof(BitWord) == sizeof(uint64_t)) {
59 for (size_t I = 0; I != B.size(); ++I)
60 Bits[I] = B[I];
61 } else {
62 unsigned BitsToAssign = NumBits;
63 for (size_t I = 0; I != B.size() && BitsToAssign; ++I) {
64 uint64_t Elt = B[I];
65 // On a 32-bit system the storage type will be 32-bit, so we may only
66 // need half of a uint64_t.
67 for (size_t Offset = 0; Offset != 2 && BitsToAssign; ++Offset) {
68 Bits[2 * I + Offset] = static_cast<uint32_t>(Elt >> (32 * Offset));
69 BitsToAssign = BitsToAssign >= 32 ? BitsToAssign - 32 : 0;
70 }
71 }
72 }
73 maskLastWord();
74 }
75 constexpr Bitset() = default;
76 constexpr Bitset(std::initializer_list<unsigned> Init) {
77 for (auto I : Init)
78 set(I);
79 }
80
81 constexpr Bitset &set() {
82 constexpr const BitWord AllOnes = ~BitWord(0);
83 for (BitWord &B : Bits)
84 B = AllOnes;
85 maskLastWord();
86 return *this;
87 }
88
89 constexpr Bitset &set(unsigned I) {
90 Bits[I / BitwordBits] |= BitWord(1) << (I % BitwordBits);
91 return *this;
92 }
93
94 constexpr Bitset &reset(unsigned I) {
95 Bits[I / BitwordBits] &= ~(BitWord(1) << (I % BitwordBits));
96 return *this;
97 }
98
99 constexpr Bitset &flip(unsigned I) {
100 Bits[I / BitwordBits] ^= BitWord(1) << (I % BitwordBits);
101 return *this;
102 }
103
104 constexpr bool operator[](unsigned I) const {
105 BitWord Mask = BitWord(1) << (I % BitwordBits);
106 return (Bits[I / BitwordBits] & Mask) != 0;
107 }
108
109 constexpr bool test(unsigned I) const { return (*this)[I]; }
110
111 constexpr size_t size() const { return NumBits; }
112
113 constexpr bool any() const {
114 for (BitWord B : Bits)
115 if (B != 0)
116 return true;
117 return false;
118 }
119
120 constexpr bool none() const { return !any(); }
121
122 constexpr bool all() const {
123 constexpr const BitWord AllOnes = ~BitWord(0);
124 for (unsigned I = 0; I < getLastWordIndex(); ++I)
125 if (Bits[I] != AllOnes)
126 return false;
127 return Bits[getLastWordIndex()] == RemainderMask;
128 }
129
130 constexpr size_t count() const {
131 size_t Count = 0;
132 for (BitWord Word : Bits)
133 Count += popcount(Word);
134 return Count;
135 }
136
137 constexpr Bitset &operator^=(const Bitset &RHS) {
138 for (unsigned I = 0, E = Bits.size(); I != E; ++I) {
139 Bits[I] ^= RHS.Bits[I];
140 }
141 return *this;
142 }
143 constexpr Bitset operator^(const Bitset &RHS) const {
144 Bitset Result = *this;
145 Result ^= RHS;
146 return Result;
147 }
148
149 constexpr Bitset &operator&=(const Bitset &RHS) {
150 for (unsigned I = 0, E = Bits.size(); I != E; ++I)
151 Bits[I] &= RHS.Bits[I];
152 return *this;
153 }
154 constexpr Bitset operator&(const Bitset &RHS) const {
155 Bitset Result = *this;
156 Result &= RHS;
157 return Result;
158 }
159
160 constexpr Bitset &operator|=(const Bitset &RHS) {
161 for (unsigned I = 0, E = Bits.size(); I != E; ++I) {
162 Bits[I] |= RHS.Bits[I];
163 }
164 return *this;
165 }
166 constexpr Bitset operator|(const Bitset &RHS) const {
167 Bitset Result = *this;
168 Result |= RHS;
169 return Result;
170 }
171
172 constexpr Bitset operator~() const {
173 Bitset Result = *this;
174 for (BitWord &B : Result.Bits)
175 B = ~B;
176 Result.maskLastWord();
177 return Result;
178 }
179
180 constexpr bool operator==(const Bitset &RHS) const {
181 for (unsigned I = 0; I < NumWords; ++I)
182 if (Bits[I] != RHS.Bits[I])
183 return false;
184 return true;
185 }
186
187 constexpr bool operator!=(const Bitset &RHS) const { return !(*this == RHS); }
188
189 constexpr bool operator<(const Bitset &Other) const {
190 for (unsigned I = 0, E = size(); I != E; ++I) {
191 bool LHS = test(I), RHS = Other.test(I);
192 if (LHS != RHS)
193 return LHS < RHS;
194 }
195 return false;
196 }
197
198 constexpr Bitset &operator<<=(unsigned N) {
199 if (N == 0)
200 return *this;
201 if (N >= NumBits)
202 return *this = Bitset();
203 const unsigned WordShift = N / BitwordBits;
204 const unsigned BitShift = N % BitwordBits;
205 if (BitShift == 0) {
206 for (unsigned I = NumWords; I > WordShift;) {
207 --I;
208 Bits[I] = Bits[I - WordShift];
209 }
210 } else {
211 const unsigned CarryShift = BitwordBits - BitShift;
212 for (unsigned I = NumWords - 1; I > WordShift; --I) {
213 Bits[I] = (Bits[I - WordShift] << BitShift) |
214 (Bits[I - WordShift - 1] >> CarryShift);
215 }
216 Bits[WordShift] = Bits[0] << BitShift;
217 }
218 for (unsigned I = 0; I < WordShift; ++I)
219 Bits[I] = 0;
220 maskLastWord();
221 return *this;
222 }
223
224 constexpr Bitset operator<<(unsigned N) const {
225 Bitset Result(*this);
226 Result <<= N;
227 return Result;
228 }
229
230 constexpr Bitset &operator>>=(unsigned N) {
231 if (N == 0)
232 return *this;
233 if (N >= NumBits)
234 return *this = Bitset();
235 const unsigned WordShift = N / BitwordBits;
236 const unsigned BitShift = N % BitwordBits;
237 if (BitShift == 0) {
238 for (unsigned I = 0; I < NumWords - WordShift; ++I)
239 Bits[I] = Bits[I + WordShift];
240 } else {
241 const unsigned CarryShift = BitwordBits - BitShift;
242 for (unsigned I = 0; I < NumWords - WordShift - 1; ++I) {
243 Bits[I] = (Bits[I + WordShift] >> BitShift) |
244 (Bits[I + WordShift + 1] << CarryShift);
245 }
246 Bits[NumWords - WordShift - 1] = Bits[NumWords - 1] >> BitShift;
247 }
248 for (unsigned I = NumWords - WordShift; I < NumWords; ++I)
249 Bits[I] = 0;
250 maskLastWord();
251 return *this;
252 }
253
254 constexpr Bitset operator>>(unsigned N) const {
255 Bitset Result(*this);
256 Result >>= N;
257 return Result;
258 }
259
260 /// Return the I-th 64-bit word of the bitset, from least significant to most.
261 ///
262 /// All words other than the last contain exactly 64 stored bits. The last
263 /// word (\p I == \c getNumWords64() - 1) may cover fewer than 64 stored bits
264 /// when \c NumBits is not a multiple of 64; in that case the unused high bits
265 /// are reported as 0.
266 constexpr uint64_t getWord64(unsigned I) const {
267 assert(I < getNumWords64() && "Word index out of range");
268 if constexpr (BitwordBits == 64) {
269 return Bits[I];
270 } else {
271 uint64_t Lo = Bits[2 * I];
272 uint64_t Hi = (2 * I + 1 < NumWords) ? Bits[2 * I + 1] : 0;
273 return Lo | (Hi << 32);
274 }
275 }
276
277 /// Return the index of the highest set bit, or -1 if no bits are set.
278 constexpr int findLastSet() const {
279 for (unsigned I = NumWords; I > 0;) {
280 --I;
281 if (Bits[I] != 0)
282 return I * BitwordBits +
283 (BitwordBits - 1 - countl_zero_constexpr(Bits[I]));
284 }
285 return -1;
286 }
287
288 /// Return the number of 64-bit words needed to hold all bits.
289 static constexpr unsigned getNumWords64() { return (NumBits + 63) / 64; }
290};
291
292} // end namespace llvm
293
294#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define I(x, y, z)
Definition MD5.cpp:57
modulo schedule test
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
constexpr Bitset operator^(const Bitset &RHS) const
Definition Bitset.h:143
constexpr size_t count() const
Definition Bitset.h:130
constexpr Bitset & set(unsigned I)
Definition Bitset.h:89
constexpr Bitset & flip(unsigned I)
Definition Bitset.h:99
constexpr bool all() const
Definition Bitset.h:122
constexpr Bitset & operator>>=(unsigned N)
Definition Bitset.h:230
constexpr bool any() const
Definition Bitset.h:113
constexpr Bitset(const std::array< uint64_t,(NumBits+63)/64 > &B)
Definition Bitset.h:56
constexpr Bitset()=default
constexpr Bitset & operator<<=(unsigned N)
Definition Bitset.h:198
constexpr bool operator==(const Bitset &RHS) const
Definition Bitset.h:180
constexpr bool operator<(const Bitset &Other) const
Definition Bitset.h:189
constexpr Bitset & operator^=(const Bitset &RHS)
Definition Bitset.h:137
static constexpr unsigned getNumWords64()
Return the number of 64-bit words needed to hold all bits.
Definition Bitset.h:289
constexpr Bitset & set()
Definition Bitset.h:81
constexpr uint64_t getWord64(unsigned I) const
Return the I-th 64-bit word of the bitset, from least significant to most.
Definition Bitset.h:266
constexpr Bitset operator&(const Bitset &RHS) const
Definition Bitset.h:154
constexpr bool none() const
Definition Bitset.h:120
constexpr bool operator!=(const Bitset &RHS) const
Definition Bitset.h:187
constexpr int findLastSet() const
Return the index of the highest set bit, or -1 if no bits are set.
Definition Bitset.h:278
constexpr bool operator[](unsigned I) const
Definition Bitset.h:104
constexpr Bitset operator<<(unsigned N) const
Definition Bitset.h:224
constexpr size_t size() const
Definition Bitset.h:111
constexpr Bitset & operator|=(const Bitset &RHS)
Definition Bitset.h:160
constexpr Bitset(std::initializer_list< unsigned > Init)
Definition Bitset.h:76
constexpr Bitset operator>>(unsigned N) const
Definition Bitset.h:254
constexpr Bitset & operator&=(const Bitset &RHS)
Definition Bitset.h:149
constexpr bool test(unsigned I) const
Definition Bitset.h:109
constexpr Bitset operator|(const Bitset &RHS) const
Definition Bitset.h:166
constexpr Bitset & reset(unsigned I)
Definition Bitset.h:94
constexpr Bitset operator~() const
Definition Bitset.h:172
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
constexpr int countl_zero_constexpr(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:240
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
@ Other
Any other memory.
Definition ModRef.h:68
#define N