1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
10 // --------------------------------------------------------------------
11 // --------------------------------------------------------------------
14 void hashBvNode::dump()
16 printf("base: %d { ", baseIndex);
17 this->foreachBit(pBit);
22 void hashBvNode::Reconstruct(indexType base)
26 assert(!(baseIndex % BITS_PER_NODE));
28 for (int i = 0; i < this->numElements(); i++)
35 hashBvNode::hashBvNode(indexType base)
37 this->Reconstruct(base);
40 hashBvNode* hashBvNode::Create(indexType base, Compiler* compiler)
42 hashBvNode* result = nullptr;
44 if (compiler->hbvGlobalData.hbvNodeFreeList)
46 result = compiler->hbvGlobalData.hbvNodeFreeList;
47 compiler->hbvGlobalData.hbvNodeFreeList = result->next;
51 result = new (compiler, CMK_hashBv) hashBvNode;
53 result->Reconstruct(base);
57 void hashBvNode::freeNode(hashBvGlobalData* glob)
59 this->next = glob->hbvNodeFreeList;
60 glob->hbvNodeFreeList = this;
63 void hashBvNode::setBit(indexType base)
65 assert(base >= baseIndex);
66 assert(base - baseIndex < BITS_PER_NODE);
69 indexType elem = base / BITS_PER_ELEMENT;
70 indexType posi = base % BITS_PER_ELEMENT;
72 elements[elem] |= indexType(1) << posi;
75 void hashBvNode::setLowest(indexType numToSet)
77 assert(numToSet <= BITS_PER_NODE);
80 while (numToSet > BITS_PER_ELEMENT)
82 elements[elemIndex] = ~(elemType(0));
83 numToSet -= BITS_PER_ELEMENT;
88 elemType allOnes = ~(elemType(0));
89 int numToShift = (int)(BITS_PER_ELEMENT - numToSet);
90 elements[elemIndex] = allOnes >> numToShift;
94 void hashBvNode::clrBit(indexType base)
96 assert(base >= baseIndex);
97 assert(base - baseIndex < BITS_PER_NODE);
100 indexType elem = base / BITS_PER_ELEMENT;
101 indexType posi = base % BITS_PER_ELEMENT;
103 elements[elem] &= ~(indexType(1) << posi);
106 bool hashBvNode::belongsIn(indexType index)
108 if (index < baseIndex)
112 if (index >= baseIndex + BITS_PER_NODE)
119 int countBitsInWord(unsigned int bits)
121 // In-place adder tree: perform 16 1-bit adds, 8 2-bit adds,
122 // 4 4-bit adds, 2 8=bit adds, and 1 16-bit add.
123 bits = ((bits >> 1) & 0x55555555) + (bits & 0x55555555);
124 bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
125 bits = ((bits >> 4) & 0x0F0F0F0F) + (bits & 0x0F0F0F0F);
126 bits = ((bits >> 8) & 0x00FF00FF) + (bits & 0x00FF00FF);
127 bits = ((bits >> 16) & 0x0000FFFF) + (bits & 0x0000FFFF);
131 int countBitsInWord(unsigned __int64 bits)
133 bits = ((bits >> 1) & 0x5555555555555555) + (bits & 0x5555555555555555);
134 bits = ((bits >> 2) & 0x3333333333333333) + (bits & 0x3333333333333333);
135 bits = ((bits >> 4) & 0x0F0F0F0F0F0F0F0F) + (bits & 0x0F0F0F0F0F0F0F0F);
136 bits = ((bits >> 8) & 0x00FF00FF00FF00FF) + (bits & 0x00FF00FF00FF00FF);
137 bits = ((bits >> 16) & 0x0000FFFF0000FFFF) + (bits & 0x0000FFFF0000FFFF);
138 bits = ((bits >> 32) & 0x00000000FFFFFFFF) + (bits & 0x00000000FFFFFFFF);
142 int hashBvNode::countBits()
146 for (int i = 0; i < this->numElements(); i++)
148 elemType bits = elements[i];
150 result += countBitsInWord(bits);
157 bool hashBvNode::anyBits()
159 for (int i = 0; i < this->numElements(); i++)
169 bool hashBvNode::getBit(indexType base)
171 assert(base >= baseIndex);
172 assert(base - baseIndex < BITS_PER_NODE);
175 indexType elem = base / BITS_PER_ELEMENT;
176 indexType posi = base % BITS_PER_ELEMENT;
178 if (elements[elem] & (indexType(1) << posi))
188 bool hashBvNode::anySet()
190 for (int i = 0; i < this->numElements(); i++)
200 void hashBvNode::copyFrom(hashBvNode* other)
202 this->baseIndex = other->baseIndex;
203 for (int i = 0; i < this->numElements(); i++)
205 this->elements[i] = other->elements[i];
209 void hashBvNode::foreachBit(bitAction a)
212 for (int i = 0; i < this->numElements(); i++)
214 base = baseIndex + i * BITS_PER_ELEMENT;
215 elemType e = elements[i];
228 elemType hashBvNode::AndWithChange(hashBvNode* other)
232 for (int i = 0; i < this->numElements(); i++)
234 elemType src = this->elements[i];
237 dst = src & other->elements[i];
239 this->elements[i] = dst;
244 elemType hashBvNode::OrWithChange(hashBvNode* other)
248 for (int i = 0; i < this->numElements(); i++)
250 elemType src = this->elements[i];
253 dst = src | other->elements[i];
255 this->elements[i] = dst;
260 elemType hashBvNode::XorWithChange(hashBvNode* other)
264 for (int i = 0; i < this->numElements(); i++)
266 elemType src = this->elements[i];
269 dst = src ^ other->elements[i];
271 this->elements[i] = dst;
276 elemType hashBvNode::SubtractWithChange(hashBvNode* other)
280 for (int i = 0; i < this->numElements(); i++)
282 elemType src = this->elements[i];
285 dst = src & ~other->elements[i];
287 this->elements[i] = dst;
292 bool hashBvNode::Intersects(hashBvNode* other)
294 for (int i = 0; i < this->numElements(); i++)
296 if ((this->elements[i] & other->elements[i]) != 0)
305 void hashBvNode::AndWith(hashBvNode* other)
307 for (int i = 0; i < this->numElements(); i++)
309 this->elements[i] &= other->elements[i];
313 void hashBvNode::OrWith(hashBvNode* other)
315 for (int i = 0; i < this->numElements(); i++)
317 this->elements[i] |= other->elements[i];
321 void hashBvNode::XorWith(hashBvNode* other)
323 for (int i = 0; i < this->numElements(); i++)
325 this->elements[i] ^= other->elements[i];
329 void hashBvNode::Subtract(hashBvNode* other)
331 for (int i = 0; i < this->numElements(); i++)
333 this->elements[i] &= ~other->elements[i];
337 bool hashBvNode::sameAs(hashBvNode* other)
339 if (this->baseIndex != other->baseIndex)
344 for (int i = 0; i < this->numElements(); i++)
346 if (this->elements[i] != other->elements[i])
355 // --------------------------------------------------------------------
356 // --------------------------------------------------------------------
358 hashBv::hashBv(Compiler* comp)
360 this->compiler = comp;
361 this->log2_hashSize = globalData()->hbvHashSizeLog2;
363 int hts = hashtable_size();
364 nodeArr = getNewVector(hts);
366 for (int i = 0; i < hts; i++)
368 nodeArr[i] = nullptr;
373 hashBv* hashBv::Create(Compiler* compiler)
376 hashBvGlobalData* gd = &compiler->hbvGlobalData;
380 result = hbvFreeList(gd);
381 hbvFreeList(gd) = result->next;
382 assert(result->nodeArr);
386 result = new (compiler, CMK_hashBv) hashBv(compiler);
387 memset(result, 0, sizeof(hashBv));
388 result->nodeArr = result->initialVector;
391 result->compiler = compiler;
392 result->log2_hashSize = 0;
393 result->numNodes = 0;
398 void hashBv::Init(Compiler* compiler)
400 memset(&compiler->hbvGlobalData, 0, sizeof(hashBvGlobalData));
403 hashBvGlobalData* hashBv::globalData()
405 return &compiler->hbvGlobalData;
408 hashBvNode** hashBv::getNewVector(int vectorLength)
410 assert(vectorLength > 0);
411 assert(isPow2(vectorLength));
413 hashBvNode** newVector = new (compiler, CMK_hashBv) hashBvNode*[vectorLength]();
417 hashBvNode*& hashBv::nodeFreeList(hashBvGlobalData* data)
419 return data->hbvNodeFreeList;
422 hashBv*& hashBv::hbvFreeList(hashBvGlobalData* data)
424 return data->hbvFreeList;
427 void hashBv::freeVector(hashBvNode* vect, int vectorLength)
429 // not enough space to do anything with it
430 if (vectorLength < 2)
435 hbvFreeListNode* f = (hbvFreeListNode*)vect;
436 f->next = globalData()->hbvFreeVectorList;
437 globalData()->hbvFreeVectorList = f;
438 f->size = vectorLength;
441 void hashBv::hbvFree()
443 Compiler* comp = this->compiler;
445 int hts = hashtable_size();
446 for (int i = 0; i < hts; i++)
450 hashBvNode* curr = nodeArr[i];
451 nodeArr[i] = curr->next;
452 curr->freeNode(globalData());
455 // keep the vector attached because the whole thing is freelisted
456 // plus you don't even know if it's freeable
458 this->next = hbvFreeList(globalData());
459 hbvFreeList(globalData()) = this;
462 hashBv* hashBv::CreateFrom(hashBv* other, Compiler* comp)
464 hashBv* result = hashBv::Create(comp);
465 result->copyFrom(other, comp);
469 void hashBv::MergeLists(hashBvNode** root1, hashBvNode** root2)
473 bool hashBv::TooSmall()
475 return this->numNodes > this->hashtable_size() * 4;
478 bool hashBv::TooBig()
480 return this->hashtable_size() > this->numNodes * 4;
483 int hashBv::getNodeCount()
485 int size = hashtable_size();
488 for (int i = 0; i < size; i++)
490 hashBvNode* last = nodeArr[i];
501 bool hashBv::IsValid()
503 int size = hashtable_size();
505 assert(((size - 1) & size) == 0);
507 for (int i = 0; i < size; i++)
509 hashBvNode* last = nodeArr[i];
515 // the node has been hashed correctly
516 assert((int)last->baseIndex > lastIndex);
517 lastIndex = (int)last->baseIndex;
518 assert(i == getHashForIndex(last->baseIndex, size));
520 // the order is monotonically increasing bases
523 assert(curr->baseIndex > last->baseIndex);
531 void hashBv::Resize()
533 // resize to 'optimal' size
535 this->Resize(this->numNodes);
538 void hashBv::Resize(int newSize)
541 newSize = nearest_pow2(newSize);
543 int oldSize = hashtable_size();
545 if (newSize == oldSize)
550 int oldSizeLog2 = log2_hashSize;
551 int log2_newSize = genLog2((unsigned)newSize);
553 hashBvNode** newNodes = this->getNewVector(newSize);
555 hashBvNode*** insertionPoints = (hashBvNode***)alloca(sizeof(hashBvNode*) * newSize);
556 memset(insertionPoints, 0, sizeof(hashBvNode*) * newSize);
558 for (int i = 0; i < newSize; i++)
560 insertionPoints[i] = &(newNodes[i]);
563 if (newSize > oldSize)
565 // for each src list, expand it into multiple dst lists
566 for (int i = 0; i < oldSize; i++)
568 hashBvNode* next = nodeArr[i];
572 hashBvNode* curr = next;
574 int destination = getHashForIndex(curr->baseIndex, newSize);
578 // stick the current node on the end of the selected list
579 *(insertionPoints[destination]) = curr;
580 insertionPoints[destination] = &(curr->next);
581 curr->next = nullptr;
585 log2_hashSize = (unsigned short)log2_newSize;
587 else if (oldSize > newSize)
589 int shrinkFactor = oldSize / newSize;
591 // shrink multiple lists into one list
592 // more efficient ways to do this but...
593 // if the lists are long, you shouldn't be shrinking.
594 for (int i = 0; i < oldSize; i++)
596 hashBvNode* next = nodeArr[i];
600 // all nodes in this list should have the same destination list
601 int destination = getHashForIndex(next->baseIndex, newSize);
602 hashBvNode** insertionPoint = &newNodes[destination];
605 hashBvNode* curr = next;
606 // figure out where to insert it
607 while (*insertionPoint && (*insertionPoint)->baseIndex < curr->baseIndex)
609 insertionPoint = &((*insertionPoint)->next);
613 hashBvNode* temp = *insertionPoint;
614 *insertionPoint = curr;
621 log2_hashSize = (unsigned short)log2_newSize;
626 assert(oldSize == newSize);
628 assert(this->IsValid());
637 // uncomment to print internal implementation details
638 // DBEXEC(TRUE, printf("[%d(%d)(nodes:%d)]{ ", hashtable_size(), countBits(), this->numNodes));
641 FOREACH_HBV_BIT_SET(index, this)
654 void hashBv::dumpFancy()
657 indexType last_1 = -1;
658 indexType last_0 = -1;
661 printf("count:%d", this->countBits());
662 FOREACH_HBV_BIT_SET(index, this)
664 if (last_1 != index - 1)
666 if (last_0 + 1 != last_1)
668 printf(" %d-%d", last_0 + 1, last_1);
672 printf(" %d", last_1);
680 // Print the last one
681 if (last_0 + 1 != last_1)
683 printf(" %d-%d", last_0 + 1, last_1);
687 printf(" %d", last_1);
694 void hashBv::removeNodeAtBase(indexType index)
696 hashBvNode** insertionPoint = this->getInsertionPointForIndex(index);
698 hashBvNode* node = *insertionPoint;
700 // make sure that we were called to remove something
701 // that really was there
705 *insertionPoint = node->next;
709 int hashBv::getHashForIndex(indexType index, int table_size)
713 hashIndex = index >> LOG2_BITS_PER_NODE;
714 hashIndex &= (table_size - 1);
716 return (int)hashIndex;
719 int hashBv::getRehashForIndex(indexType thisIndex, int thisTableSize, int newTableSize)
725 hashBvNode** hashBv::getInsertionPointForIndex(indexType index)
727 indexType indexInNode;
733 hashIndex = getHashForIndex(index, hashtable_size());
735 baseIndex = index & ~(BITS_PER_NODE - 1);
736 indexInNode = index & (BITS_PER_NODE - 1);
738 // printf("(%x) : hsh=%x, base=%x, index=%x\n", index,
739 // hashIndex, baseIndex, indexInNode);
742 hashBvNode** prev = &nodeArr[hashIndex];
743 result = nodeArr[hashIndex];
747 if (result->baseIndex == baseIndex)
751 else if (result->baseIndex > baseIndex)
757 prev = &(result->next);
758 result = result->next;
764 hashBvNode* hashBv::getNodeForIndexHelper(indexType index, bool canAdd)
766 // determine the base index of the node containing this index
767 index = index & ~(BITS_PER_NODE - 1);
769 hashBvNode** prev = getInsertionPointForIndex(index);
771 hashBvNode* node = *prev;
773 if (node && node->belongsIn(index))
779 // missing node, insert it before the current one
780 hashBvNode* temp = hashBvNode::Create(index, this->compiler);
792 hashBvNode* hashBv::getNodeForIndex(indexType index)
794 // determine the base index of the node containing this index
795 index = index & ~(BITS_PER_NODE - 1);
797 hashBvNode** prev = getInsertionPointForIndex(index);
799 hashBvNode* node = *prev;
801 if (node && node->belongsIn(index))
811 void hashBv::setBit(indexType index)
814 assert(this->numNodes == this->getNodeCount());
815 hashBvNode* result = nullptr;
817 indexType baseIndex = index & ~(BITS_PER_NODE - 1);
818 indexType base = index - baseIndex;
819 indexType elem = base / BITS_PER_ELEMENT;
820 indexType posi = base % BITS_PER_ELEMENT;
822 // this should be the 99% case : when there is only one node in the structure
823 if ((result = nodeArr[0]) && result->baseIndex == baseIndex)
825 result->elements[elem] |= indexType(1) << posi;
829 result = getOrAddNodeForIndex(index);
830 result->setBit(index);
832 assert(this->numNodes == this->getNodeCount());
834 // if it's getting out of control resize it
835 if (this->numNodes > this->hashtable_size() * 4)
843 void hashBv::setAll(indexType numToSet)
845 // TODO-Throughput: this could be more efficient
846 for (unsigned int i = 0; i < numToSet; i += BITS_PER_NODE)
848 hashBvNode* node = getOrAddNodeForIndex(i);
849 indexType bits_to_set = min(BITS_PER_NODE, numToSet - i);
850 node->setLowest(bits_to_set);
854 void hashBv::clearBit(indexType index)
857 assert(this->numNodes == this->getNodeCount());
858 hashBvNode* result = nullptr;
860 indexType baseIndex = index & ~(BITS_PER_NODE - 1);
861 indexType hashIndex = getHashForIndex(index, hashtable_size());
863 hashBvNode** prev = &nodeArr[hashIndex];
864 result = nodeArr[hashIndex];
868 if (result->baseIndex == baseIndex)
870 result->clrBit(index);
871 // if nothing left set free it
872 if (!result->anySet())
874 *prev = result->next;
875 result->freeNode(globalData());
880 else if (result->baseIndex > baseIndex)
886 prev = &(result->next);
887 result = result->next;
890 assert(this->numNodes == this->getNodeCount());
894 bool hashBv::testBit(indexType index)
896 // determine the base index of the node containing this index
897 indexType baseIndex = index & ~(BITS_PER_NODE - 1);
899 if (nodeArr[0] && nodeArr[0]->baseIndex == baseIndex)
901 return nodeArr[0]->getBit(index);
904 indexType hashIndex = getHashForIndex(baseIndex, hashtable_size());
906 hashBvNode* iter = nodeArr[hashIndex];
910 if (iter->baseIndex == baseIndex)
912 return iter->getBit(index);
922 int hashBv::countBits()
925 int hts = this->hashtable_size();
926 for (int hashNum = 0; hashNum < hts; hashNum++)
928 hashBvNode* node = nodeArr[hashNum];
931 result += node->countBits();
938 bool hashBv::anySet()
942 int hts = this->hashtable_size();
943 for (int hashNum = 0; hashNum < hts; hashNum++)
945 hashBvNode* node = nodeArr[hashNum];
961 static inline void PreAction(hashBv* lhs, hashBv* rhs)
964 static inline void PostAction(hashBv* lhs, hashBv* rhs)
967 static inline bool DefaultResult()
972 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
974 // it's in other, not this
978 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
980 // it's in LHS, not RHS
981 // so have to remove it
982 hashBvNode* old = *l;
985 old->freeNode(lhs->globalData());
989 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
991 if ((*l)->AndWithChange(r))
1002 hashBvNode* old = *l;
1004 old->freeNode(lhs->globalData());
1014 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1020 class SubtractAction
1023 static inline void PreAction(hashBv* lhs, hashBv* rhs)
1026 static inline void PostAction(hashBv* lhs, hashBv* rhs)
1029 static inline bool DefaultResult()
1033 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1035 // it's in other, not this
1039 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1045 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1047 if ((*l)->SubtractWithChange(r))
1058 hashBvNode* old = *l;
1060 old->freeNode(lhs->globalData());
1070 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1079 static inline void PreAction(hashBv* lhs, hashBv* rhs)
1082 static inline void PostAction(hashBv* lhs, hashBv* rhs)
1085 static inline bool DefaultResult()
1090 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1092 // it's in other, not this
1095 hashBvNode* temp = hashBvNode::Create(r->baseIndex, lhs->compiler);
1098 temp->next = (*l)->next;
1105 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1107 // it's in LHS, not RHS
1108 // so LHS remains the same
1112 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1114 if ((*l)->XorWithChange(r))
1122 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1124 // it's in other, not this
1127 hashBvNode* temp = hashBvNode::Create(r->baseIndex, lhs->compiler);
1130 temp->next = nullptr;
1141 static inline void PreAction(hashBv* lhs, hashBv* rhs)
1143 if (lhs->log2_hashSize + 2 < rhs->log2_hashSize)
1145 lhs->Resize(rhs->numNodes);
1147 if (rhs->numNodes > rhs->hashtable_size() * 4)
1149 rhs->Resize(rhs->numNodes);
1152 static inline void PostAction(hashBv* lhs, hashBv* rhs)
1155 static inline bool DefaultResult()
1160 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1162 // it's in other, not this
1165 hashBvNode* temp = hashBvNode::Create(r->baseIndex, lhs->compiler);
1174 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1180 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1182 if ((*l)->OrWithChange(r))
1189 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1191 // other contains something this does not
1193 // LeftGap(lhs, l, r, result, terminate);
1195 hashBvNode* temp = hashBvNode::Create(r->baseIndex, lhs->compiler);
1198 temp->next = nullptr;
1209 static inline void PreAction(hashBv* lhs, hashBv* rhs)
1212 static inline void PostAction(hashBv* lhs, hashBv* rhs)
1215 static inline bool DefaultResult()
1220 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1225 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1232 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1234 if (!(*l)->sameAs(r))
1242 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1249 class IntersectsAction
1252 static inline void PreAction(hashBv* lhs, hashBv* rhs)
1255 static inline void PostAction(hashBv* lhs, hashBv* rhs)
1258 static inline bool DefaultResult()
1263 static inline void LeftGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1269 static inline void RightGap(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1275 static inline void BothPresent(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1277 if ((*l)->Intersects(r))
1283 static inline void LeftEmpty(hashBv* lhs, hashBvNode**& l, hashBvNode*& r, bool& result, bool& terminate)
1289 template <typename Action>
1290 bool hashBv::MultiTraverseLHSBigger(hashBv* other)
1292 int hts = this->hashtable_size();
1293 int ots = other->hashtable_size();
1295 bool result = Action::DefaultResult();
1296 bool terminate = false;
1299 hashBvNode*** cursors;
1300 int shiftFactor = this->log2_hashSize - other->log2_hashSize;
1301 int expansionFactor = hts / ots;
1302 cursors = (hashBvNode***)alloca(expansionFactor * sizeof(void*));
1304 for (int h = 0; h < other->hashtable_size(); h++)
1306 // set up cursors for the expansion of nodes
1307 for (int i = 0; i < expansionFactor; i++)
1309 // ex: for [1024] &= [8]
1311 // cursors point to lhs: 0, 8, 16, 24, ...
1312 cursors[i] = &nodeArr[ots * i + h];
1315 hashBvNode* o = other->nodeArr[h];
1318 hashBvNode* next = o->next;
1319 // figure out what dst list this goes to
1320 int hash = getHashForIndex(o->baseIndex, hts);
1321 int dstIndex = (hash - h) >> other->log2_hashSize;
1322 hashBvNode** cursor = cursors[dstIndex];
1323 hashBvNode* c = *cursor;
1325 // figure out where o fits in the cursor
1329 Action::LeftEmpty(this, cursors[dstIndex], o, result, terminate);
1335 else if (c->baseIndex == o->baseIndex)
1337 Action::BothPresent(this, cursors[dstIndex], o, result, terminate);
1343 else if (c->baseIndex > o->baseIndex)
1345 Action::LeftGap(this, cursors[dstIndex], o, result, terminate);
1351 else if (c->baseIndex < o->baseIndex)
1353 Action::RightGap(this, cursors[dstIndex], o, result, terminate);
1360 for (int i = 0; i < expansionFactor; i++)
1362 while (*(cursors[i]))
1364 Action::RightGap(this, cursors[i], o, result, terminate);
1375 template <typename Action>
1376 bool hashBv::MultiTraverseRHSBigger(hashBv* other)
1378 int hts = this->hashtable_size();
1379 int ots = other->hashtable_size();
1381 bool result = Action::DefaultResult();
1382 bool terminate = false;
1384 for (int hashNum = 0; hashNum < ots; hashNum++)
1386 int destination = getHashForIndex(BITS_PER_NODE * hashNum, this->hashtable_size());
1387 assert(hashNum == getHashForIndex(BITS_PER_NODE * hashNum, other->hashtable_size()));
1389 hashBvNode** pa = &this->nodeArr[destination];
1390 hashBvNode** pb = &other->nodeArr[hashNum];
1391 hashBvNode* b = *pb;
1395 hashBvNode* a = *pa;
1396 if (a->baseIndex < b->baseIndex)
1398 // in a but not in b
1399 // but maybe it's someplace else in b
1400 if (getHashForIndex(a->baseIndex, ots) == hashNum)
1402 // this contains something other does not
1404 Action::RightGap(this, pa, b, result, terminate);
1412 // other might contain this, we don't know yet
1416 else if (a->baseIndex == b->baseIndex)
1418 Action::BothPresent(this, pa, b, result, terminate);
1424 else if (a->baseIndex > b->baseIndex)
1426 // other contains something this does not
1427 Action::LeftGap(this, pa, b, result, terminate);
1436 // if it's in the dest but not in src
1437 // then make sure it's expected to be in this list
1438 if (getHashForIndex((*pa)->baseIndex, ots) == hashNum)
1440 Action::RightGap(this, pa, b, result, terminate);
1448 pa = &((*pa)->next);
1453 Action::LeftEmpty(this, pa, b, result, terminate);
1460 assert(this->numNodes == this->getNodeCount());
1464 // LHSBigger and RHSBigger algorithms both work for equal
1465 // this is a specialized version of RHSBigger which is simpler (and faster)
1466 // because equal sizes are the 99% case
1467 template <typename Action>
1468 bool hashBv::MultiTraverseEqual(hashBv* other)
1470 int hts = this->hashtable_size();
1471 assert(other->hashtable_size() == hts);
1473 bool result = Action::DefaultResult();
1474 bool terminate = false;
1476 for (int hashNum = 0; hashNum < hts; hashNum++)
1478 int destination = getHashForIndex(BITS_PER_NODE * hashNum, this->hashtable_size());
1480 hashBvNode** pa = &this->nodeArr[hashNum];
1481 hashBvNode** pb = &other->nodeArr[hashNum];
1482 hashBvNode* b = *pb;
1486 hashBvNode* a = *pa;
1487 if (a->baseIndex < b->baseIndex)
1489 // in a but not in b
1490 Action::RightGap(this, pa, b, result, terminate);
1496 else if (a->baseIndex == b->baseIndex)
1498 Action::BothPresent(this, pa, b, result, terminate);
1504 else if (a->baseIndex > b->baseIndex)
1506 // other contains something this does not
1507 Action::LeftGap(this, pa, b, result, terminate);
1516 // if it's in the dest but not in src
1517 Action::RightGap(this, pa, b, result, terminate);
1525 Action::LeftEmpty(this, pa, b, result, terminate);
1532 assert(this->numNodes == this->getNodeCount());
1536 template <class Action>
1537 bool hashBv::MultiTraverse(hashBv* other)
1539 bool result = false;
1541 assert(this->numNodes == this->getNodeCount());
1543 Action::PreAction(this, other);
1545 int hts = this->log2_hashSize;
1546 int ots = other->log2_hashSize;
1550 return MultiTraverseEqual<Action>(other);
1554 return MultiTraverseLHSBigger<Action>(other);
1558 return MultiTraverseRHSBigger<Action>(other);
1562 bool hashBv::Intersects(hashBv* other)
1564 return MultiTraverse<IntersectsAction>(other);
1567 bool hashBv::AndWithChange(hashBv* other)
1569 return MultiTraverse<AndAction>(other);
1573 bool hashBv::SubtractWithChange(hashBv* other)
1575 return MultiTraverse<SubtractAction>(other);
1578 void hashBv::Subtract(hashBv* other)
1580 this->SubtractWithChange(other);
1583 void hashBv::Subtract3(hashBv* o1, hashBv* o2)
1585 this->copyFrom(o1, compiler);
1589 void hashBv::UnionMinus(hashBv* src1, hashBv* src2, hashBv* src3)
1591 this->Subtract3(src1, src2);
1592 this->OrWithChange(src3);
1595 void hashBv::ZeroAll()
1597 int hts = this->hashtable_size();
1599 for (int hashNum = 0; hashNum < hts; hashNum++)
1601 while (nodeArr[hashNum])
1603 hashBvNode* n = nodeArr[hashNum];
1604 nodeArr[hashNum] = n->next;
1605 n->freeNode(globalData());
1611 bool hashBv::OrWithChange(hashBv* other)
1613 return MultiTraverse<OrAction>(other);
1616 bool hashBv::XorWithChange(hashBv* other)
1618 return MultiTraverse<XorAction>(other);
1620 void hashBv::OrWith(hashBv* other)
1622 this->OrWithChange(other);
1625 void hashBv::AndWith(hashBv* other)
1627 this->AndWithChange(other);
1630 bool hashBv::CompareWith(hashBv* other)
1632 return MultiTraverse<CompareAction>(other);
1635 void hashBv::copyFrom(hashBv* other, Compiler* comp)
1637 assert(this != other);
1639 hashBvNode* freeList = nullptr;
1643 if (this->log2_hashSize != other->log2_hashSize)
1645 this->nodeArr = this->getNewVector(other->hashtable_size());
1646 this->log2_hashSize = other->log2_hashSize;
1647 assert(this->hashtable_size() == other->hashtable_size());
1650 int hts = this->hashtable_size();
1651 // printf("in copyfrom\n");
1652 for (int h = 0; h < hts; h++)
1654 // put the current list on the free list
1655 freeList = this->nodeArr[h];
1656 this->nodeArr[h] = nullptr;
1658 hashBvNode** splicePoint = &(this->nodeArr[h]);
1659 hashBvNode* otherNode = other->nodeArr[h];
1660 hashBvNode* newNode = nullptr;
1664 // printf("otherNode is True...\n");
1665 hashBvNode* next = *splicePoint;
1672 freeList = freeList->next;
1673 newNode->Reconstruct(otherNode->baseIndex);
1677 newNode = hashBvNode::Create(otherNode->baseIndex, this->compiler);
1679 newNode->copyFrom(otherNode);
1681 newNode->next = *splicePoint;
1682 *splicePoint = newNode;
1683 splicePoint = &(newNode->next);
1685 otherNode = otherNode->next;
1690 hashBvNode* next = freeList->next;
1691 freeList->freeNode(globalData());
1695 for (int h=0; h<hashtable_size(); h++)
1697 printf("%p %p\n", this->nodeArr[h], other->nodeArr[h]);
1702 int nodeSort(const void* x, const void* y)
1704 hashBvNode* a = (hashBvNode*)x;
1705 hashBvNode* b = (hashBvNode*)y;
1706 return (int)(b->baseIndex - a->baseIndex);
1709 void hashBv::InorderTraverse(nodeAction n)
1711 int hts = hashtable_size();
1713 hashBvNode** x = new (compiler, CMK_hashBv) hashBvNode*[hts];
1716 // keep an array of the current pointers
1717 // into each of the the bitvector lists
1719 for (int i = 0; i < hts; i++)
1726 // pick the lowest node in the hashtable
1728 indexType lowest = INT_MAX;
1729 int lowest_index = -1;
1730 for (int i = 0; i < hts; i++)
1732 if (x[i] && x[i]->baseIndex < lowest)
1734 lowest = x[i]->baseIndex;
1738 // if there was anything left, use it and update
1739 // the list pointers otherwise we are done
1740 if (lowest_index != -1)
1743 x[lowest_index] = x[lowest_index]->next;
1755 void hashBv::InorderTraverseTwo(hashBv* other, dualNodeAction a)
1757 int sizeThis, sizeOther;
1758 hashBvNode **nodesThis, **nodesOther;
1760 sizeThis = this->hashtable_size();
1761 sizeOther = other->hashtable_size();
1763 nodesThis = new (compiler, CMK_hashBv) hashBvNode*[sizeThis];
1764 nodesOther = new (compiler, CMK_hashBv) hashBvNode*[sizeOther];
1766 // populate the arrays
1767 for (int i = 0; i < sizeThis; i++)
1769 nodesThis[i] = this->nodeArr[i];
1772 for (int i = 0; i < sizeOther; i++)
1774 nodesOther[i] = other->nodeArr[i];
1779 indexType lowestThis = INT_MAX;
1780 indexType lowestOther = INT_MAX;
1781 int lowestHashIndexThis = -1;
1782 int lowestHashIndexOther = -1;
1784 // find the lowest remaining node in each BV
1785 for (int i = 0; i < sizeThis; i++)
1787 if (nodesThis[i] && nodesThis[i]->baseIndex < lowestThis)
1789 lowestHashIndexThis = i;
1790 lowestThis = nodesThis[i]->baseIndex;
1793 for (int i = 0; i < sizeOther; i++)
1795 if (nodesOther[i] && nodesOther[i]->baseIndex < lowestOther)
1797 lowestHashIndexOther = i;
1798 lowestOther = nodesOther[i]->baseIndex;
1801 hashBvNode *nodeThis, *nodeOther;
1802 nodeThis = lowestHashIndexThis == -1 ? nullptr : nodesThis[lowestHashIndexThis];
1803 nodeOther = lowestHashIndexOther == -1 ? nullptr : nodesOther[lowestHashIndexOther];
1804 // no nodes left in either, so return
1805 if ((!nodeThis) && (!nodeOther))
1809 // there are only nodes left in one bitvector
1811 else if ((!nodeThis) || (!nodeOther))
1813 a(this, other, nodeThis, nodeOther);
1816 nodesThis[lowestHashIndexThis] = nodesThis[lowestHashIndexThis]->next;
1820 nodesOther[lowestHashIndexOther] = nodesOther[lowestHashIndexOther]->next;
1823 // nodes are left in both so determine if the lowest ones
1824 // match. if so process them in a pair. if not then
1825 // process the lower of the two alone
1826 else if (nodeThis && nodeOther)
1828 if (nodeThis->baseIndex == nodeOther->baseIndex)
1830 a(this, other, nodeThis, nodeOther);
1831 nodesThis[lowestHashIndexThis] = nodesThis[lowestHashIndexThis]->next;
1832 nodesOther[lowestHashIndexOther] = nodesOther[lowestHashIndexOther]->next;
1834 else if (nodeThis->baseIndex < nodeOther->baseIndex)
1836 a(this, other, nodeThis, nullptr);
1837 nodesThis[lowestHashIndexThis] = nodesThis[lowestHashIndexThis]->next;
1839 else if (nodeOther->baseIndex < nodeThis->baseIndex)
1841 a(this, other, nullptr, nodeOther);
1842 nodesOther[lowestHashIndexOther] = nodesOther[lowestHashIndexOther]->next;
1847 delete[] nodesOther;
1850 // --------------------------------------------------------------------
1851 // --------------------------------------------------------------------
1854 void SimpleDumpNode(hashBvNode* n)
1856 printf("base: %d\n", n->baseIndex);
1859 void DumpNode(hashBvNode* n)
1864 void SimpleDumpDualNode(hashBv* a, hashBv* b, hashBvNode* n, hashBvNode* m)
1869 printf("%d,", n->baseIndex);
1877 printf("%d\n", m->baseIndex);
1886 hashBvIterator::hashBvIterator()
1891 hashBvIterator::hashBvIterator(hashBv* bv)
1894 this->hashtable_index = 0;
1895 this->current_element = 0;
1896 this->current_base = 0;
1897 this->current_data = 0;
1901 this->hashtable_size = bv->hashtable_size();
1902 this->currNode = bv->nodeArr[0];
1904 if (!this->currNode)
1911 void hashBvIterator::initFrom(hashBv* bv)
1914 this->hashtable_size = bv->hashtable_size();
1915 this->hashtable_index = 0;
1916 this->currNode = bv->nodeArr[0];
1917 this->current_element = 0;
1918 this->current_base = 0;
1919 this->current_data = 0;
1921 if (!this->currNode)
1927 this->current_data = this->currNode->elements[0];
1931 void hashBvIterator::nextNode()
1933 // if we have a valid node then just get the next one in the chain
1936 this->currNode = this->currNode->next;
1939 // else step to the next one in the hash table
1940 while (!this->currNode)
1944 if (hashtable_index >= hashtable_size)
1946 // printf("nextnode bailed\n");
1950 this->currNode = bv->nodeArr[hashtable_index];
1952 // first element in the new node
1953 this->current_element = 0;
1954 this->current_base = this->currNode->baseIndex;
1955 this->current_data = this->currNode->elements[0];
1956 // printf("nextnode returned base %d\n", this->current_base);
1957 // printf("hti = %d ", hashtable_index);
1960 indexType hashBvIterator::nextBit()
1963 // printf("in nextbit for bv:\n");
1964 // this->bv->dump();
1966 if (!this->currNode)
1973 if (!this->currNode)
1979 if (!this->current_data)
1982 // printf("current element is %d\n", current_element);
1983 // reached the end of this node
1984 if (current_element == (indexType) this->currNode->numElements())
1986 // printf("going to next node\n");
1992 assert(current_element < (indexType) this->currNode->numElements());
1993 // printf("getting more data\n");
1994 current_data = this->currNode->elements[current_element];
1995 current_base = this->currNode->baseIndex + current_element * BITS_PER_ELEMENT;
2001 while (current_data)
2003 if (current_data & 1)
2008 return current_base - 1;
2020 indexType HbvNext(hashBv* bv, Compiler* comp)
2024 bv->globalData()->hashBvNextIterator.initFrom(bv);
2026 return bv->globalData()->hashBvNextIterator.nextBit();