sanitizer_bitvector.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. //===-- sanitizer_bitvector.h -----------------------------------*- 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. // Specializer BitVector implementation.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef SANITIZER_BITVECTOR_H
  13. #define SANITIZER_BITVECTOR_H
  14. #include "sanitizer_common.h"
  15. namespace __sanitizer {
  16. // Fixed size bit vector based on a single basic integer.
  17. template <class basic_int_t = uptr>
  18. class BasicBitVector {
  19. public:
  20. enum SizeEnum : uptr { kSize = sizeof(basic_int_t) * 8 };
  21. uptr size() const { return kSize; }
  22. // No CTOR.
  23. void clear() { bits_ = 0; }
  24. void setAll() { bits_ = ~(basic_int_t)0; }
  25. bool empty() const { return bits_ == 0; }
  26. // Returns true if the bit has changed from 0 to 1.
  27. bool setBit(uptr idx) {
  28. basic_int_t old = bits_;
  29. bits_ |= mask(idx);
  30. return bits_ != old;
  31. }
  32. // Returns true if the bit has changed from 1 to 0.
  33. bool clearBit(uptr idx) {
  34. basic_int_t old = bits_;
  35. bits_ &= ~mask(idx);
  36. return bits_ != old;
  37. }
  38. bool getBit(uptr idx) const { return (bits_ & mask(idx)) != 0; }
  39. uptr getAndClearFirstOne() {
  40. CHECK(!empty());
  41. uptr idx = LeastSignificantSetBitIndex(bits_);
  42. clearBit(idx);
  43. return idx;
  44. }
  45. // Do "this |= v" and return whether new bits have been added.
  46. bool setUnion(const BasicBitVector &v) {
  47. basic_int_t old = bits_;
  48. bits_ |= v.bits_;
  49. return bits_ != old;
  50. }
  51. // Do "this &= v" and return whether any bits have been removed.
  52. bool setIntersection(const BasicBitVector &v) {
  53. basic_int_t old = bits_;
  54. bits_ &= v.bits_;
  55. return bits_ != old;
  56. }
  57. // Do "this &= ~v" and return whether any bits have been removed.
  58. bool setDifference(const BasicBitVector &v) {
  59. basic_int_t old = bits_;
  60. bits_ &= ~v.bits_;
  61. return bits_ != old;
  62. }
  63. void copyFrom(const BasicBitVector &v) { bits_ = v.bits_; }
  64. // Returns true if 'this' intersects with 'v'.
  65. bool intersectsWith(const BasicBitVector &v) const {
  66. return (bits_ & v.bits_) != 0;
  67. }
  68. // for (BasicBitVector<>::Iterator it(bv); it.hasNext();) {
  69. // uptr idx = it.next();
  70. // use(idx);
  71. // }
  72. class Iterator {
  73. public:
  74. Iterator() { }
  75. explicit Iterator(const BasicBitVector &bv) : bv_(bv) {}
  76. bool hasNext() const { return !bv_.empty(); }
  77. uptr next() { return bv_.getAndClearFirstOne(); }
  78. void clear() { bv_.clear(); }
  79. private:
  80. BasicBitVector bv_;
  81. };
  82. private:
  83. basic_int_t mask(uptr idx) const {
  84. CHECK_LT(idx, size());
  85. return (basic_int_t)1UL << idx;
  86. }
  87. basic_int_t bits_;
  88. };
  89. // Fixed size bit vector of (kLevel1Size*BV::kSize**2) bits.
  90. // The implementation is optimized for better performance on
  91. // sparse bit vectors, i.e. the those with few set bits.
  92. template <uptr kLevel1Size = 1, class BV = BasicBitVector<> >
  93. class TwoLevelBitVector {
  94. // This is essentially a 2-level bit vector.
  95. // Set bit in the first level BV indicates that there are set bits
  96. // in the corresponding BV of the second level.
  97. // This structure allows O(kLevel1Size) time for clear() and empty(),
  98. // as well fast handling of sparse BVs.
  99. public:
  100. enum SizeEnum : uptr { kSize = BV::kSize * BV::kSize * kLevel1Size };
  101. // No CTOR.
  102. uptr size() const { return kSize; }
  103. void clear() {
  104. for (uptr i = 0; i < kLevel1Size; i++)
  105. l1_[i].clear();
  106. }
  107. void setAll() {
  108. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  109. l1_[i0].setAll();
  110. for (uptr i1 = 0; i1 < BV::kSize; i1++)
  111. l2_[i0][i1].setAll();
  112. }
  113. }
  114. bool empty() const {
  115. for (uptr i = 0; i < kLevel1Size; i++)
  116. if (!l1_[i].empty())
  117. return false;
  118. return true;
  119. }
  120. // Returns true if the bit has changed from 0 to 1.
  121. bool setBit(uptr idx) {
  122. check(idx);
  123. uptr i0 = idx0(idx);
  124. uptr i1 = idx1(idx);
  125. uptr i2 = idx2(idx);
  126. if (!l1_[i0].getBit(i1)) {
  127. l1_[i0].setBit(i1);
  128. l2_[i0][i1].clear();
  129. }
  130. bool res = l2_[i0][i1].setBit(i2);
  131. // Printf("%s: %zd => %zd %zd %zd; %d\n", __func__,
  132. // idx, i0, i1, i2, res);
  133. return res;
  134. }
  135. bool clearBit(uptr idx) {
  136. check(idx);
  137. uptr i0 = idx0(idx);
  138. uptr i1 = idx1(idx);
  139. uptr i2 = idx2(idx);
  140. bool res = false;
  141. if (l1_[i0].getBit(i1)) {
  142. res = l2_[i0][i1].clearBit(i2);
  143. if (l2_[i0][i1].empty())
  144. l1_[i0].clearBit(i1);
  145. }
  146. return res;
  147. }
  148. bool getBit(uptr idx) const {
  149. check(idx);
  150. uptr i0 = idx0(idx);
  151. uptr i1 = idx1(idx);
  152. uptr i2 = idx2(idx);
  153. // Printf("%s: %zd => %zd %zd %zd\n", __func__, idx, i0, i1, i2);
  154. return l1_[i0].getBit(i1) && l2_[i0][i1].getBit(i2);
  155. }
  156. uptr getAndClearFirstOne() {
  157. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  158. if (l1_[i0].empty()) continue;
  159. uptr i1 = l1_[i0].getAndClearFirstOne();
  160. uptr i2 = l2_[i0][i1].getAndClearFirstOne();
  161. if (!l2_[i0][i1].empty())
  162. l1_[i0].setBit(i1);
  163. uptr res = i0 * BV::kSize * BV::kSize + i1 * BV::kSize + i2;
  164. // Printf("getAndClearFirstOne: %zd %zd %zd => %zd\n", i0, i1, i2, res);
  165. return res;
  166. }
  167. CHECK(0);
  168. return 0;
  169. }
  170. // Do "this |= v" and return whether new bits have been added.
  171. bool setUnion(const TwoLevelBitVector &v) {
  172. bool res = false;
  173. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  174. BV t = v.l1_[i0];
  175. while (!t.empty()) {
  176. uptr i1 = t.getAndClearFirstOne();
  177. if (l1_[i0].setBit(i1))
  178. l2_[i0][i1].clear();
  179. if (l2_[i0][i1].setUnion(v.l2_[i0][i1]))
  180. res = true;
  181. }
  182. }
  183. return res;
  184. }
  185. // Do "this &= v" and return whether any bits have been removed.
  186. bool setIntersection(const TwoLevelBitVector &v) {
  187. bool res = false;
  188. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  189. if (l1_[i0].setIntersection(v.l1_[i0]))
  190. res = true;
  191. if (!l1_[i0].empty()) {
  192. BV t = l1_[i0];
  193. while (!t.empty()) {
  194. uptr i1 = t.getAndClearFirstOne();
  195. if (l2_[i0][i1].setIntersection(v.l2_[i0][i1]))
  196. res = true;
  197. if (l2_[i0][i1].empty())
  198. l1_[i0].clearBit(i1);
  199. }
  200. }
  201. }
  202. return res;
  203. }
  204. // Do "this &= ~v" and return whether any bits have been removed.
  205. bool setDifference(const TwoLevelBitVector &v) {
  206. bool res = false;
  207. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  208. BV t = l1_[i0];
  209. t.setIntersection(v.l1_[i0]);
  210. while (!t.empty()) {
  211. uptr i1 = t.getAndClearFirstOne();
  212. if (l2_[i0][i1].setDifference(v.l2_[i0][i1]))
  213. res = true;
  214. if (l2_[i0][i1].empty())
  215. l1_[i0].clearBit(i1);
  216. }
  217. }
  218. return res;
  219. }
  220. void copyFrom(const TwoLevelBitVector &v) {
  221. clear();
  222. setUnion(v);
  223. }
  224. // Returns true if 'this' intersects with 'v'.
  225. bool intersectsWith(const TwoLevelBitVector &v) const {
  226. for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
  227. BV t = l1_[i0];
  228. t.setIntersection(v.l1_[i0]);
  229. while (!t.empty()) {
  230. uptr i1 = t.getAndClearFirstOne();
  231. if (!v.l1_[i0].getBit(i1)) continue;
  232. if (l2_[i0][i1].intersectsWith(v.l2_[i0][i1]))
  233. return true;
  234. }
  235. }
  236. return false;
  237. }
  238. // for (TwoLevelBitVector<>::Iterator it(bv); it.hasNext();) {
  239. // uptr idx = it.next();
  240. // use(idx);
  241. // }
  242. class Iterator {
  243. public:
  244. Iterator() { }
  245. explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) {
  246. it1_.clear();
  247. it2_.clear();
  248. }
  249. bool hasNext() const {
  250. if (it1_.hasNext()) return true;
  251. for (uptr i = i0_; i < kLevel1Size; i++)
  252. if (!bv_.l1_[i].empty()) return true;
  253. return false;
  254. }
  255. uptr next() {
  256. // Printf("++++: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
  257. // it2_.hasNext(), kSize);
  258. if (!it1_.hasNext() && !it2_.hasNext()) {
  259. for (; i0_ < kLevel1Size; i0_++) {
  260. if (bv_.l1_[i0_].empty()) continue;
  261. it1_ = typename BV::Iterator(bv_.l1_[i0_]);
  262. // Printf("+i0: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
  263. // it2_.hasNext(), kSize);
  264. break;
  265. }
  266. }
  267. if (!it2_.hasNext()) {
  268. CHECK(it1_.hasNext());
  269. i1_ = it1_.next();
  270. it2_ = typename BV::Iterator(bv_.l2_[i0_][i1_]);
  271. // Printf("++i1: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
  272. // it2_.hasNext(), kSize);
  273. }
  274. CHECK(it2_.hasNext());
  275. uptr i2 = it2_.next();
  276. uptr res = i0_ * BV::kSize * BV::kSize + i1_ * BV::kSize + i2;
  277. // Printf("+ret: %zd %zd; %d %d; size %zd; res: %zd\n", i0_, i1_,
  278. // it1_.hasNext(), it2_.hasNext(), kSize, res);
  279. if (!it1_.hasNext() && !it2_.hasNext())
  280. i0_++;
  281. return res;
  282. }
  283. private:
  284. const TwoLevelBitVector &bv_;
  285. uptr i0_, i1_;
  286. typename BV::Iterator it1_, it2_;
  287. };
  288. private:
  289. void check(uptr idx) const { CHECK_LE(idx, size()); }
  290. uptr idx0(uptr idx) const {
  291. uptr res = idx / (BV::kSize * BV::kSize);
  292. CHECK_LE(res, kLevel1Size);
  293. return res;
  294. }
  295. uptr idx1(uptr idx) const {
  296. uptr res = (idx / BV::kSize) % BV::kSize;
  297. CHECK_LE(res, BV::kSize);
  298. return res;
  299. }
  300. uptr idx2(uptr idx) const {
  301. uptr res = idx % BV::kSize;
  302. CHECK_LE(res, BV::kSize);
  303. return res;
  304. }
  305. BV l1_[kLevel1Size];
  306. BV l2_[kLevel1Size][BV::kSize];
  307. };
  308. } // namespace __sanitizer
  309. #endif // SANITIZER_BITVECTOR_H