llvm.org GIT mirror llvm / f73f5cd
Add a new insert_as() method to DenseMap and use it for ConstantUniqueMap Just like the existing find_as() method, the new insert_as() accepts an extra parameter which is used as a key to find the bucket in the map. When creating a Constant, we want to check the map before actually creating the object. In this case we have to perform two queries to the map, and this extra parameter can save recomputing the hash value for the second query. This is a reapply of r260458, that was reverted because it was suspected to be the cause of instability of an internal bot, but wasn't confirmed. Differential Revision: http://reviews.llvm.org/D16268 From: Mehdi Amini <mehdi.amini@apple.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262812 91177308-0d34-0410-b5e6-96231b3b80d8 Mehdi Amini 4 years ago
2 changed file(s) with 61 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
194194 true);
195195 }
196196
197 /// Alternate version of insert() which allows a different, and possibly
198 /// less expensive, key type.
199 /// The DenseMapInfo is responsible for supplying methods
200 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
201 /// type used.
202 template
203 std::pair insert_as(std::pair &&KV,
204 const LookupKeyT &Val) {
205 BucketT *TheBucket;
206 if (LookupBucketFor(Val, TheBucket))
207 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
208 false); // Already in map.
209
210 // Otherwise, insert the new element.
211 TheBucket = InsertIntoBucket(std::move(KV.first), std::move(KV.second), Val,
212 TheBucket);
213 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
214 true);
215 }
216
197217 /// insert - Range insertion of pairs.
198218 template
199219 void insert(InputIt I, InputIt E) {
398418
399419 BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
400420 BucketT *TheBucket) {
401 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
421 TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
402422
403423 TheBucket->getFirst() = Key;
404424 ::new (&TheBucket->getSecond()) ValueT(Value);
407427
408428 BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
409429 BucketT *TheBucket) {
410 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
430 TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
411431
412432 TheBucket->getFirst() = Key;
413433 ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
415435 }
416436
417437 BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {
418 TheBucket = InsertIntoBucketImpl(Key, TheBucket);
438 TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
419439
420440 TheBucket->getFirst() = std::move(Key);
421441 ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
422442 return TheBucket;
423443 }
424444
425 BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
445 template
446 BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, LookupKeyT &Lookup,
447 BucketT *TheBucket) {
448 TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
449
450 TheBucket->getFirst() = std::move(Key);
451 ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
452 return TheBucket;
453 }
454
455 template
456 BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
457 BucketT *TheBucket) {
426458 incrementEpoch();
427459
428460 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
438470 unsigned NumBuckets = getNumBuckets();
439471 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
440472 this->grow(NumBuckets * 2);
441 LookupBucketFor(Key, TheBucket);
473 LookupBucketFor(Lookup, TheBucket);
442474 NumBuckets = getNumBuckets();
443475 } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
444476 NumBuckets/8)) {
445477 this->grow(NumBuckets);
446 LookupBucketFor(Key, TheBucket);
478 LookupBucketFor(Lookup, TheBucket);
447479 }
448480 assert(TheBucket);
449481
545545 typedef typename ConstantInfo::TypeClass TypeClass;
546546 typedef std::pair LookupKey;
547547
548 /// Key and hash together, so that we compute the hash only once and reuse it.
549 typedef std::pair LookupKeyHashed;
550
548551 private:
549552 struct MapInfo {
550553 typedef DenseMapInfo ConstantClassInfo;
563566 }
564567 static unsigned getHashValue(const LookupKey &Val) {
565568 return hash_combine(Val.first, Val.second.getHash());
569 }
570 static unsigned getHashValue(const LookupKeyHashed &Val) {
571 return Val.first;
566572 }
567573 static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
568574 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
571577 return false;
572578 return LHS.second == RHS;
573579 }
580 static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
581 return isEqual(LHS.second, RHS);
582 }
574583 };
575584
576585 public:
588597 // Asserts that use_empty().
589598 delete I.first;
590599 }
591
592600 private:
593 ConstantClass *create(TypeClass *Ty, ValType V) {
601 ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
594602 ConstantClass *Result = V.create(Ty);
595603
596604 assert(Result->getType() == Ty && "Type specified is not correct!");
597 insert(Result);
605 Map.insert_as(std::make_pair(Result, '\0'), HashKey);
598606
599607 return Result;
600608 }
602610 public:
603611 /// Return the specified constant from the map, creating it if necessary.
604612 ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
605 LookupKey Lookup(Ty, V);
613 LookupKey Key(Ty, V);
614 /// Hash once, and reuse it for the lookup and the insertion if needed.
615 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
616
606617 ConstantClass *Result = nullptr;
607618
608 auto I = find(Lookup);
619 auto I = Map.find_as(Lookup);
609620 if (I == Map.end())
610 Result = create(Ty, V);
621 Result = create(Ty, V, Lookup);
611622 else
612623 Result = I->first;
613624 assert(Result && "Unexpected nullptr");
614625
615626 return Result;
616627 }
617
618 /// Find the constant by lookup key.
619 typename MapTy::iterator find(LookupKey Lookup) {
620 return Map.find_as(Lookup);
621 }
622
623 /// Insert the constant into its proper slot.
624 void insert(ConstantClass *CP) { Map[CP] = '\0'; }
625628
626629 /// Remove this constant from the map
627630 void remove(ConstantClass *CP) {
635638 ConstantClass *CP, Value *From,
636639 Constant *To, unsigned NumUpdated = 0,
637640 unsigned OperandNo = ~0u) {
638 LookupKey Lookup(CP->getType(), ValType(Operands, CP));
639 auto I = find(Lookup);
641 LookupKey Key(CP->getType(), ValType(Operands, CP));
642 /// Hash once, and reuse it for the lookup and the insertion if needed.
643 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
644
645 auto I = Map.find_as(Lookup);
640646 if (I != Map.end())
641647 return I->first;
642648
652658 if (CP->getOperand(I) == From)
653659 CP->setOperand(I, To);
654660 }
655 insert(CP);
661 Map.insert_as(std::make_pair(CP, '\0'), Lookup);
656662 return nullptr;
657663 }
658664