UnitBitVector.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #define FOREACH_BITSET_IN_UNITBV(index, bv, BVUnitT) \
  7. { \
  8. BVIndex index; \
  9. BVUnitT _unit = bv; \
  10. for(index = _unit.GetNextBit(); index != -1; index = _unit.GetNextBit()) \
  11. { \
  12. _unit.Clear(index); \
  13. \
  14. #define NEXT_BITSET_IN_UNITBV }}
  15. // Typedef
  16. typedef uint32 UnitWord32;
  17. typedef uint64 UnitWord64;
  18. inline BOOLEAN
  19. GetFirstBitSet(DWORD *Index, UnitWord32 Mask)
  20. {
  21. return _BitScanForward(Index, Mask);
  22. }
  23. inline BOOLEAN
  24. GetFirstBitSet(DWORD *Index, UnitWord64 Mask)
  25. {
  26. #if defined(TARGET_64)
  27. return _BitScanForward64(Index, Mask);
  28. #else
  29. //_BitScanForward64 intrinsic is not available in x86 & ARM
  30. if (_BitScanForward(Index, (UnitWord32)Mask))
  31. {
  32. return true;
  33. }
  34. if(_BitScanForward(Index, (UnitWord32) (Mask >> 32)))
  35. {
  36. *Index = *Index + 32;
  37. return true;
  38. }
  39. return false;
  40. #endif
  41. }
  42. inline BOOLEAN
  43. GetLastBitSet(DWORD *Index, UnitWord32 Mask)
  44. {
  45. return _BitScanReverse(Index, Mask);
  46. }
  47. inline BOOLEAN
  48. GetLastBitSet(DWORD *Index, UnitWord64 Mask)
  49. {
  50. #if defined(TARGET_64)
  51. return _BitScanReverse64(Index, Mask);
  52. #else
  53. //_BitScanReverse64 intrinsic is not available in x86 & ARM
  54. if (_BitScanReverse(Index, (UnitWord32)(Mask >> 32)))
  55. {
  56. *Index = *Index + 32;
  57. return true;
  58. }
  59. return _BitScanReverse(Index, (UnitWord32)Mask);
  60. #endif
  61. }
  62. namespace {
  63. //ShiftValue is essentially log(sizeof(T))
  64. template <typename T> constexpr LONG BVUnitT_GetShiftValue();
  65. template<> constexpr LONG BVUnitT_GetShiftValue<UnitWord32>() { return 5; }
  66. template<> constexpr LONG BVUnitT_GetShiftValue<UnitWord64>() { return 6; }
  67. }
  68. template <typename T>
  69. class BVUnitT
  70. {
  71. // Data
  72. private:
  73. Field(T) word;
  74. // Constructor
  75. public:
  76. BVUnitT(T initial = 0)
  77. {
  78. word = initial;
  79. }
  80. typedef T BVUnitTContainer;
  81. // Implementation
  82. private:
  83. static void AssertRange(BVIndex index)
  84. {
  85. AssertMsg(index < BitsPerWord, "index out of bound");
  86. }
  87. static UnitWord32 Reverse(UnitWord32 bitsToReverse) {
  88. bitsToReverse = (bitsToReverse & 0x55555555) << 1 | (bitsToReverse & 0xAAAAAAAA) >> 1;
  89. bitsToReverse = (bitsToReverse & 0x33333333) << 2 | (bitsToReverse & 0xCCCCCCCC) >> 2;
  90. bitsToReverse = (bitsToReverse & 0x0F0F0F0F) << 4 | (bitsToReverse & 0xF0F0F0F0) >> 4;
  91. bitsToReverse = (bitsToReverse & 0x00FF00FF) << 8 | (bitsToReverse & 0xFF00FF00) >> 8;
  92. bitsToReverse = (bitsToReverse & 0x0000FFFF) << 16 | (bitsToReverse & 0xFFFF0000) >> 16;
  93. return bitsToReverse;
  94. }
  95. static UnitWord64 Reverse(UnitWord64 bits)
  96. {
  97. UnitWord32 lower = (UnitWord32) bits;
  98. UnitWord32 upper = (UnitWord32) (bits >> 32);
  99. UnitWord64 result = ((UnitWord64) Reverse(lower)) << 32;
  100. result |= Reverse(upper);
  101. return result;
  102. }
  103. static BVIndex CountBit(UnitWord32 bits)
  104. {
  105. const uint _5_32 = 0x55555555;
  106. const uint _3_32 = 0x33333333;
  107. const uint _F1_32 = 0x0f0f0f0f;
  108. // In-place adder tree: perform 16 1-bit adds, 8 2-bit adds, 4 4-bit adds,
  109. // 2 8=bit adds, and 1 16-bit add.
  110. // From Dr. Dobb's Nov. 2000 letters, from Phil Bagwell, on reducing
  111. // the cost by removing some of the masks that can be "forgotten" dbitse
  112. // to the max # of bits set (32) that will fit in a byte.
  113. //
  114. bits -= (bits >> 1) & _5_32;
  115. bits = ((bits >> 2) & _3_32) + (bits & _3_32);
  116. bits = ((bits >> 4) & _F1_32) + (bits & _F1_32);
  117. bits += bits >> 8;
  118. bits += bits >> 16;
  119. return BVIndex(bits & 0xff);
  120. }
  121. static BVIndex CountBit(UnitWord64 bits)
  122. {
  123. #if DBG
  124. unsigned countBits = CountBit((UnitWord32)bits) + CountBit((UnitWord32)(bits >> 32));
  125. #endif
  126. const uint64 _5_64 = 0x5555555555555555ui64;
  127. const uint64 _3_64 = 0x3333333333333333ui64;
  128. const uint64 _F1_64 = 0x0f0f0f0f0f0f0f0fui64;
  129. // In-place adder tree: perform 32 1-bit adds, 16 2-bit adds, 8 4-bit adds,
  130. // 4 8-bit adds, 2 16-bit adds, and 1 32-bit add.
  131. // From Dr. Dobb's Nov. 2000 letters, from Phil Bagwell, on reducing
  132. // the cost by removing some of the masks that can be "forgotten" due
  133. // to the max # of bits set (64) that will fit in a byte.
  134. //
  135. bits -= (bits >> 1) & _5_64;
  136. bits = ((bits >> 2) & _3_64) + (bits & _3_64);
  137. bits = ((bits >> 4) & _F1_64) + (bits & _F1_64);
  138. bits += bits >> 8;
  139. bits += bits >> 16;
  140. bits += bits >> 32;
  141. AssertMsg(countBits == (bits & 0xff), "Wrong count?");
  142. return (BVIndex)(bits & 0xff);
  143. }
  144. static unsigned int NumLeadingZeroes(UnitWord32 bits)
  145. {
  146. int n = 0;
  147. if (bits == 0) return 32;
  148. // Binary search to figure out the number of leading zeroes
  149. if (bits <= 0x0000FFFF)
  150. {
  151. // At least 16 leading zeroes- so remove them, and
  152. // let's figure out how many leading zeroes in the last 16 bits
  153. n = n + 16;
  154. bits = bits << 16;
  155. }
  156. if (bits <= 0x00FFFFFF)
  157. {
  158. // At least 8 more zeroes- remove them, and repeat process
  159. n = n + 8;
  160. bits = bits << 8;
  161. }
  162. if (bits <= 0x0FFFFFFF)
  163. {
  164. n = n + 4;
  165. bits = bits << 4;
  166. }
  167. if (bits <= 0x3FFFFFFF)
  168. {
  169. n = n + 2;
  170. bits = bits << 2;
  171. }
  172. if (bits <= 0x7FFFFFFF)
  173. {
  174. n = n + 1;
  175. }
  176. return n;
  177. }
  178. static unsigned int NumLeadingZeroes(UnitWord64 bits)
  179. {
  180. UnitWord32 lower = (UnitWord32) bits;
  181. UnitWord32 upper = (UnitWord32) (bits >> 32);
  182. if (upper == 0)
  183. {
  184. return 32 + NumLeadingZeroes(lower);
  185. }
  186. else
  187. {
  188. return NumLeadingZeroes(upper);
  189. }
  190. }
  191. public:
  192. enum
  193. {
  194. BitsPerWord = sizeof(T) * MachBits,
  195. BitMask = BitsPerWord - 1,
  196. AllOnesMask = -1
  197. };
  198. enum : LONG {
  199. ShiftValue = BVUnitT_GetShiftValue<T>()
  200. };
  201. static BVIndex Position(BVIndex index)
  202. {
  203. return index >> ShiftValue;
  204. }
  205. static BVIndex Offset(BVIndex index)
  206. {
  207. return index & BitMask;
  208. }
  209. static BVIndex Floor(BVIndex index)
  210. {
  211. return index & (~BitMask);
  212. }
  213. static T GetTopBitsClear(BVIndex len)
  214. {
  215. return ((T)1 << Offset(len)) - 1;
  216. }
  217. bool Equal(BVUnitT unit) const
  218. {
  219. return this->word == unit.word;
  220. }
  221. void Set(BVIndex index)
  222. {
  223. AssertRange(index);
  224. this->word |= (T)1 << index;
  225. }
  226. void Clear(BVIndex index)
  227. {
  228. AssertRange(index);
  229. this->word &= ~((T)1 << index);
  230. }
  231. void Complement(BVIndex index)
  232. {
  233. AssertRange(index);
  234. this->word ^= (T)1 << index;
  235. }
  236. BOOLEAN Test(const BVIndex index) const
  237. {
  238. AssertRange(index);
  239. return (this->word & ( (T)1 << index)) != 0;
  240. }
  241. BOOLEAN Test(BVUnitT const unit) const
  242. {
  243. return (this->word & unit.word) != 0;
  244. }
  245. BOOLEAN TestRange(const BVIndex index, uint length) const
  246. {
  247. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  248. return (this->word & mask) == mask;
  249. }
  250. BOOLEAN TestAnyInRange(const BVIndex index, uint length) const
  251. {
  252. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  253. return (this->word & mask) != 0;
  254. }
  255. void SetRange(const BVIndex index, uint length)
  256. {
  257. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  258. this->word |= mask;
  259. }
  260. void ClearRange(const BVIndex index, uint length)
  261. {
  262. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  263. this->word &= ~mask;
  264. }
  265. BVIndex GetNextBit() const
  266. {
  267. DWORD index;
  268. if(GetFirstBitSet(&index, this->word))
  269. {
  270. return index;
  271. }
  272. else
  273. {
  274. return BVInvalidIndex;
  275. }
  276. }
  277. BVIndex GetNextBit(BVIndex index) const
  278. {
  279. AssertRange(index);
  280. BVUnitT temp = *this;
  281. temp.ClearAllTill(index);
  282. return temp.GetNextBit();
  283. }
  284. BVIndex GetPrevBit() const
  285. {
  286. DWORD index;
  287. if(GetLastBitSet(&index, this->word))
  288. {
  289. return index;
  290. }
  291. else
  292. {
  293. return BVInvalidIndex;
  294. }
  295. }
  296. inline unsigned int GetNumberOfLeadingZeroes()
  297. {
  298. return NumLeadingZeroes(this->word);
  299. }
  300. T GetWord() const
  301. {
  302. return this->word;
  303. }
  304. inline BVIndex FirstStringOfOnes(unsigned int l)
  305. {
  306. unsigned int leadingZeroes;
  307. BVIndex i = 0;
  308. if (this->word == 0)
  309. {
  310. return BVInvalidIndex;
  311. }
  312. T bitVector = Reverse(this->word);
  313. while (bitVector != 0) {
  314. // Find the number of leading zeroes
  315. leadingZeroes = NumLeadingZeroes(bitVector);
  316. // Skip over leading zeroes
  317. bitVector = bitVector << leadingZeroes;
  318. i = i + leadingZeroes;
  319. // Invert the bit vector- leading number of leading zeroes = number of leading 1's in the original bit vector
  320. leadingZeroes = NumLeadingZeroes(~bitVector); // Count first/next group of 1's.
  321. if (leadingZeroes >= l)
  322. return i;
  323. // If there aren't enough ones, we skip over them, iterate again
  324. bitVector = bitVector << leadingZeroes;
  325. i = i + leadingZeroes;
  326. }
  327. // No sub-sequence of 1's of length l found in this bit vector
  328. return BVInvalidIndex;
  329. }
  330. void ClearAllTill(BVIndex index)
  331. {
  332. AssertRange(index);
  333. this->word &= ((T)BVUnitT::AllOnesMask) <<(T)index;
  334. }
  335. BVIndex Count() const
  336. {
  337. return CountBit(this->word);
  338. }
  339. bool IsEmpty() const
  340. {
  341. return 0 == this->word;
  342. }
  343. bool IsFull() const
  344. {
  345. return this->word == AllOnesMask;
  346. }
  347. void SetAll()
  348. {
  349. this->word = (T)AllOnesMask;
  350. }
  351. void ClearAll()
  352. {
  353. this->word = 0;
  354. }
  355. void ComplimentAll()
  356. {
  357. this->word = ~this->word;
  358. }
  359. void Or(BVUnitT x)
  360. {
  361. this->word |= x.word;
  362. }
  363. void OrComplimented(BVUnitT x)
  364. {
  365. this->word |= (~x.word);
  366. }
  367. void And(BVUnitT x)
  368. {
  369. this->word &= x.word;
  370. }
  371. void Xor(BVUnitT x)
  372. {
  373. this->word ^= x.word;
  374. }
  375. uint DiffCount(BVUnitT x) const
  376. {
  377. return CountBit(x.word ^ this->word);
  378. }
  379. void Minus(BVUnitT x)
  380. {
  381. this->word &= (~x.word);
  382. }
  383. void Copy(BVUnitT x)
  384. {
  385. this->word = x.word;
  386. }
  387. void ShiftLeft(BVIndex count)
  388. {
  389. this->word <<= count;
  390. }
  391. void ShiftRight(BVIndex count)
  392. {
  393. this->word >>= count;
  394. }
  395. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  396. void DumpWord()
  397. {
  398. Output::Print(_u("%p"), this->word);
  399. }
  400. bool Dump(BVIndex base = 0, bool hasBits = false) const
  401. {
  402. FOREACH_BITSET_IN_UNITBV(index, *this, BVUnitT)
  403. {
  404. if (hasBits)
  405. {
  406. Output::Print(_u(", "));
  407. }
  408. Output::Print(_u("%u"), index + base);
  409. hasBits = true;
  410. }
  411. NEXT_BITSET_IN_UNITBV;
  412. return hasBits;
  413. }
  414. #endif
  415. };
  416. typedef BVUnitT<UnitWord32> BVUnit32;
  417. typedef BVUnitT<UnitWord64> BVUnit64;
  418. #if defined(TARGET_64)
  419. typedef BVUnit64 BVUnit;
  420. #else
  421. typedef BVUnit32 BVUnit;
  422. #endif