@@ -116,7 +116,10 @@ class Value {
116116
117117private:
118118 Type *VTy;
119- Use *UseList = nullptr ;
119+ union {
120+ Use *List = nullptr ;
121+ unsigned Count;
122+ } Uses;
120123
121124 friend class ValueAsMetadata ; // Allow access to IsUsedByMD.
122125 friend class ValueHandleBase ; // Allow access to HasValueHandle.
@@ -344,21 +347,23 @@ class Value {
344347
345348 bool use_empty () const {
346349 assertModuleIsMaterialized ();
347- return UseList == nullptr ;
350+ return hasUseList () ? Uses. List == nullptr : Uses. Count == 0 ;
348351 }
349352
350- bool materialized_use_empty () const { return UseList == nullptr ; }
353+ bool materialized_use_empty () const {
354+ return hasUseList () ? Uses.List == nullptr : !Uses.Count ;
355+ }
351356
352357 using use_iterator = use_iterator_impl<Use>;
353358 using const_use_iterator = use_iterator_impl<const Use>;
354359
355360 use_iterator materialized_use_begin () {
356361 assert (hasUseList ());
357- return use_iterator (UseList );
362+ return use_iterator (Uses. List );
358363 }
359364 const_use_iterator materialized_use_begin () const {
360365 assert (hasUseList ());
361- return const_use_iterator (UseList );
366+ return const_use_iterator (Uses. List );
362367 }
363368 use_iterator use_begin () {
364369 assertModuleIsMaterialized ();
@@ -392,11 +397,11 @@ class Value {
392397
393398 user_iterator materialized_user_begin () {
394399 assert (hasUseList ());
395- return user_iterator (UseList );
400+ return user_iterator (Uses. List );
396401 }
397402 const_user_iterator materialized_user_begin () const {
398403 assert (hasUseList ());
399- return const_user_iterator (UseList );
404+ return const_user_iterator (Uses. List );
400405 }
401406 user_iterator user_begin () {
402407 assertModuleIsMaterialized ();
@@ -435,7 +440,11 @@ class Value {
435440 // /
436441 // / This is specialized because it is a common request and does not require
437442 // / traversing the whole use list.
438- bool hasOneUse () const { return UseList && hasSingleElement (uses ()); }
443+ bool hasOneUse () const {
444+ if (!hasUseList ())
445+ return Uses.Count == 1 ;
446+ return hasSingleElement (uses ());
447+ }
439448
440449 // / Return true if this Value has exactly N uses.
441450 bool hasNUses (unsigned N) const ;
@@ -509,8 +518,17 @@ class Value {
509518
510519 // / This method should only be used by the Use class.
511520 void addUse (Use &U) {
512- if (UseList || hasUseList ())
513- U.addToList (&UseList);
521+ if (hasUseList ())
522+ U.addToList (Uses.List );
523+ else
524+ U.addToList (Uses.Count );
525+ }
526+
527+ void removeUse (Use &U) {
528+ if (hasUseList ())
529+ U.removeFromList (Uses.List );
530+ else
531+ U.removeFromList (Uses.Count );
514532 }
515533
516534 // / Concrete subclass of this.
@@ -852,7 +870,8 @@ class Value {
852870 // /
853871 // / \return the first element in the list.
854872 // /
855- // / \note Completely ignores \a Use::Prev (doesn't read, doesn't update).
873+ // / \note Completely ignores \a Use::PrevOrCount (doesn't read, doesn't
874+ // / update).
856875 template <class Compare >
857876 static Use *mergeUseLists (Use *L, Use *R, Compare Cmp) {
858877 Use *Merged;
@@ -898,8 +917,47 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
898917 return OS;
899918}
900919
920+ inline Use::~Use () {
921+ if (Val)
922+ Val->removeUse (*this );
923+ }
924+
925+ void Use::addToList (unsigned &Count) {
926+ assert (isa<ConstantData>(Val) && " Only ConstantData is ref-counted" );
927+ ++Count;
928+
929+ // We don't have a uselist - clear the remnant if we are replacing a
930+ // non-constant value.
931+ Prev = nullptr ;
932+ Next = nullptr ;
933+ }
934+
935+ void Use::addToList (Use *&List) {
936+ assert (!isa<ConstantData>(Val) && " ConstantData has no use-list" );
937+
938+ Next = List;
939+ if (Next)
940+ Next->Prev = &Next;
941+ Prev = &List;
942+ List = this ;
943+ }
944+
945+ void Use::removeFromList (unsigned &Count) {
946+ assert (isa<ConstantData>(Val));
947+ assert (Count > 0 && " reference count underflow" );
948+ assert (!Prev && !Next && " should not have uselist remnant" );
949+ --Count;
950+ }
951+
952+ void Use::removeFromList (Use *&List) {
953+ *Prev = Next;
954+ if (Next)
955+ Next->Prev = Prev;
956+ }
957+
901958void Use::set (Value *V) {
902- removeFromList ();
959+ if (Val)
960+ Val->removeUse (*this );
903961 Val = V;
904962 if (V)
905963 V->addUse (*this );
@@ -916,7 +974,7 @@ const Use &Use::operator=(const Use &RHS) {
916974}
917975
918976template <class Compare > void Value::sortUseList (Compare Cmp) {
919- if (!UseList || !UseList ->Next )
977+ if (!hasUseList () || !Uses. List || !Uses. List ->Next )
920978 // No need to sort 0 or 1 uses.
921979 return ;
922980
@@ -929,10 +987,10 @@ template <class Compare> void Value::sortUseList(Compare Cmp) {
929987 Use *Slots[MaxSlots];
930988
931989 // Collect the first use, turning it into a single-item list.
932- Use *Next = UseList ->Next ;
933- UseList ->Next = nullptr ;
990+ Use *Next = Uses. List ->Next ;
991+ Uses. List ->Next = nullptr ;
934992 unsigned NumSlots = 1 ;
935- Slots[0 ] = UseList ;
993+ Slots[0 ] = Uses. List ;
936994
937995 // Collect all but the last use.
938996 while (Next->Next ) {
@@ -968,15 +1026,15 @@ template <class Compare> void Value::sortUseList(Compare Cmp) {
9681026 // Merge all the lists together.
9691027 assert (Next && " Expected one more Use" );
9701028 assert (!Next->Next && " Expected only one Use" );
971- UseList = Next;
1029+ Uses. List = Next;
9721030 for (unsigned I = 0 ; I < NumSlots; ++I)
9731031 if (Slots[I])
974- // Since the uses in Slots[I] originally preceded those in UseList , send
1032+ // Since the uses in Slots[I] originally preceded those in Uses.List , send
9751033 // Slots[I] in as the left parameter to maintain a stable sort.
976- UseList = mergeUseLists (Slots[I], UseList , Cmp);
1034+ Uses. List = mergeUseLists (Slots[I], Uses. List , Cmp);
9771035
9781036 // Fix the Prev pointers.
979- for (Use *I = UseList , **Prev = &UseList ; I; I = I->Next ) {
1037+ for (Use *I = Uses. List , **Prev = &Uses. List ; I; I = I->Next ) {
9801038 I->Prev = Prev;
9811039 Prev = &I->Next ;
9821040 }
0 commit comments