Skip to content

Commit 19ec50c

Browse files
arsenmpetrhosek
authored andcommitted
Reapply "IR: Remove reference counts from ConstantData (llvm#137314)" (llvm#138962)
This reverts commit 0274232.
1 parent 4b357df commit 19ec50c

File tree

9 files changed

+103
-105
lines changed

9 files changed

+103
-105
lines changed

llvm/docs/ReleaseNotes.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ Makes programs 10x faster by doing Special New Thing.
5656
Changes to the LLVM IR
5757
----------------------
5858

59-
* It is no longer permitted to inspect the uses of ConstantData
59+
* It is no longer permitted to inspect the uses of ConstantData. Use
60+
count APIs will behave as if they have no uses (i.e. use_empty() is
61+
always true).
6062

6163
* The `nocapture` attribute has been replaced by `captures(none)`.
6264
* The constant expression variants of the following instructions have been

llvm/include/llvm/IR/Constants.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ template <class ConstantClass> struct ConstantAggrKeyType;
5151
/// Since they can be in use by unrelated modules (and are never based on
5252
/// GlobalValues), it never makes sense to RAUW them.
5353
///
54-
/// These do not have use lists. It is illegal to inspect the uses.
54+
/// These do not have use lists. It is illegal to inspect the uses. These behave
55+
/// as if they have no uses (i.e. use_empty() is always true).
5556
class ConstantData : public Constant {
5657
constexpr static IntrusiveOperandsAllocMarker AllocMarker{0};
5758

llvm/include/llvm/IR/Use.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
namespace llvm {
2424

2525
template <typename> struct simplify_type;
26-
class ConstantData;
2726
class User;
2827
class Value;
2928

@@ -43,7 +42,7 @@ class Use {
4342

4443
private:
4544
/// Destructor - Only for zap()
46-
~Use();
45+
~Use() { removeFromList(); }
4746

4847
/// Constructor
4948
Use(User *Parent) : Parent(Parent) {}
@@ -85,10 +84,25 @@ class Use {
8584
Use **Prev = nullptr;
8685
User *Parent = nullptr;
8786

88-
inline void addToList(unsigned &Count);
89-
inline void addToList(Use *&List);
90-
inline void removeFromList(unsigned &Count);
91-
inline void removeFromList(Use *&List);
87+
void addToList(Use **List) {
88+
Next = *List;
89+
if (Next)
90+
Next->Prev = &Next;
91+
Prev = List;
92+
*Prev = this;
93+
}
94+
95+
void removeFromList() {
96+
if (Prev) {
97+
*Prev = Next;
98+
if (Next) {
99+
Next->Prev = Prev;
100+
Next = nullptr;
101+
}
102+
103+
Prev = nullptr;
104+
}
105+
}
92106
};
93107

94108
/// Allow clients to treat uses just like values when using

llvm/include/llvm/IR/Value.h

Lines changed: 20 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,7 @@ class Value {
116116

117117
private:
118118
Type *VTy;
119-
union {
120-
Use *List = nullptr;
121-
unsigned Count;
122-
} Uses;
119+
Use *UseList = nullptr;
123120

124121
friend class ValueAsMetadata; // Allow access to IsUsedByMD.
125122
friend class ValueHandleBase; // Allow access to HasValueHandle.
@@ -347,23 +344,21 @@ class Value {
347344

348345
bool use_empty() const {
349346
assertModuleIsMaterialized();
350-
return hasUseList() ? Uses.List == nullptr : Uses.Count == 0;
347+
return UseList == nullptr;
351348
}
352349

353-
bool materialized_use_empty() const {
354-
return hasUseList() ? Uses.List == nullptr : !Uses.Count;
355-
}
350+
bool materialized_use_empty() const { return UseList == nullptr; }
356351

357352
using use_iterator = use_iterator_impl<Use>;
358353
using const_use_iterator = use_iterator_impl<const Use>;
359354

360355
use_iterator materialized_use_begin() {
361356
assert(hasUseList());
362-
return use_iterator(Uses.List);
357+
return use_iterator(UseList);
363358
}
364359
const_use_iterator materialized_use_begin() const {
365360
assert(hasUseList());
366-
return const_use_iterator(Uses.List);
361+
return const_use_iterator(UseList);
367362
}
368363
use_iterator use_begin() {
369364
assertModuleIsMaterialized();
@@ -397,11 +392,11 @@ class Value {
397392

398393
user_iterator materialized_user_begin() {
399394
assert(hasUseList());
400-
return user_iterator(Uses.List);
395+
return user_iterator(UseList);
401396
}
402397
const_user_iterator materialized_user_begin() const {
403398
assert(hasUseList());
404-
return const_user_iterator(Uses.List);
399+
return const_user_iterator(UseList);
405400
}
406401
user_iterator user_begin() {
407402
assertModuleIsMaterialized();
@@ -440,11 +435,7 @@ class Value {
440435
///
441436
/// This is specialized because it is a common request and does not require
442437
/// traversing the whole use list.
443-
bool hasOneUse() const {
444-
if (!hasUseList())
445-
return Uses.Count == 1;
446-
return hasSingleElement(uses());
447-
}
438+
bool hasOneUse() const { return UseList && hasSingleElement(uses()); }
448439

449440
/// Return true if this Value has exactly N uses.
450441
bool hasNUses(unsigned N) const;
@@ -518,17 +509,8 @@ class Value {
518509

519510
/// This method should only be used by the Use class.
520511
void addUse(Use &U) {
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);
512+
if (UseList || hasUseList())
513+
U.addToList(&UseList);
532514
}
533515

534516
/// Concrete subclass of this.
@@ -870,8 +852,7 @@ class Value {
870852
///
871853
/// \return the first element in the list.
872854
///
873-
/// \note Completely ignores \a Use::PrevOrCount (doesn't read, doesn't
874-
/// update).
855+
/// \note Completely ignores \a Use::Prev (doesn't read, doesn't update).
875856
template <class Compare>
876857
static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) {
877858
Use *Merged;
@@ -917,47 +898,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
917898
return OS;
918899
}
919900

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-
958901
void Use::set(Value *V) {
959-
if (Val)
960-
Val->removeUse(*this);
902+
removeFromList();
961903
Val = V;
962904
if (V)
963905
V->addUse(*this);
@@ -974,7 +916,7 @@ const Use &Use::operator=(const Use &RHS) {
974916
}
975917

976918
template <class Compare> void Value::sortUseList(Compare Cmp) {
977-
if (!hasUseList() || !Uses.List || !Uses.List->Next)
919+
if (!UseList || !UseList->Next)
978920
// No need to sort 0 or 1 uses.
979921
return;
980922

@@ -987,10 +929,10 @@ template <class Compare> void Value::sortUseList(Compare Cmp) {
987929
Use *Slots[MaxSlots];
988930

989931
// Collect the first use, turning it into a single-item list.
990-
Use *Next = Uses.List->Next;
991-
Uses.List->Next = nullptr;
932+
Use *Next = UseList->Next;
933+
UseList->Next = nullptr;
992934
unsigned NumSlots = 1;
993-
Slots[0] = Uses.List;
935+
Slots[0] = UseList;
994936

995937
// Collect all but the last use.
996938
while (Next->Next) {
@@ -1026,15 +968,15 @@ template <class Compare> void Value::sortUseList(Compare Cmp) {
1026968
// Merge all the lists together.
1027969
assert(Next && "Expected one more Use");
1028970
assert(!Next->Next && "Expected only one Use");
1029-
Uses.List = Next;
971+
UseList = Next;
1030972
for (unsigned I = 0; I < NumSlots; ++I)
1031973
if (Slots[I])
1032-
// Since the uses in Slots[I] originally preceded those in Uses.List, send
974+
// Since the uses in Slots[I] originally preceded those in UseList, send
1033975
// Slots[I] in as the left parameter to maintain a stable sort.
1034-
Uses.List = mergeUseLists(Slots[I], Uses.List, Cmp);
976+
UseList = mergeUseLists(Slots[I], UseList, Cmp);
1035977

1036978
// Fix the Prev pointers.
1037-
for (Use *I = Uses.List, **Prev = &Uses.List; I; I = I->Next) {
979+
for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) {
1038980
I->Prev = Prev;
1039981
Prev = &I->Next;
1040982
}

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4004,7 +4004,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
40044004
// Globals with sub-elements such as combinations of arrays and structs
40054005
// are handled recursively by emitGlobalConstantImpl. Keep track of the
40064006
// constant symbol base and the current position with BaseCV and Offset.
4007-
if (!isa<ConstantData>(CV) && !BaseCV && CV->hasOneUse())
4007+
if (!BaseCV && CV->hasOneUse())
40084008
BaseCV = dyn_cast<Constant>(CV->user_back());
40094009

40104010
if (isa<ConstantAggregateZero>(CV)) {

llvm/lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,7 @@ static UseListOrderMap predictUseListOrder(const Module *M) {
279279
UseListOrderMap ULOM;
280280
for (const auto &Pair : OM) {
281281
const Value *V = Pair.first;
282-
if (!V->hasUseList() || V->use_empty() ||
283-
std::next(V->use_begin()) == V->use_end())
282+
if (V->use_empty() || std::next(V->use_begin()) == V->use_end())
284283
continue;
285284

286285
std::vector<unsigned> Shuffle =

llvm/lib/IR/Instruction.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,7 @@ std::optional<BasicBlock::iterator> Instruction::getInsertionPointAfterDef() {
373373
}
374374

375375
bool Instruction::isOnlyUserOfAnyOperand() {
376-
return any_of(operands(), [](const Value *V) {
377-
return V->hasUseList() && V->hasOneUser();
378-
});
376+
return any_of(operands(), [](const Value *V) { return V->hasOneUser(); });
379377
}
380378

381379
void Instruction::setHasNoUnsignedWrap(bool b) {

llvm/lib/IR/Value.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,18 @@ void Value::destroyValueName() {
148148
}
149149

150150
bool Value::hasNUses(unsigned N) const {
151-
if (!hasUseList())
152-
return Uses.Count == N;
151+
if (!UseList)
152+
return N == 0;
153+
154+
// TODO: Disallow for ConstantData and remove !UseList check?
153155
return hasNItems(use_begin(), use_end(), N);
154156
}
155157

156158
bool Value::hasNUsesOrMore(unsigned N) const {
157-
if (!hasUseList())
158-
return Uses.Count >= N;
159+
// TODO: Disallow for ConstantData and remove !UseList check?
160+
if (!UseList)
161+
return N == 0;
162+
159163
return hasNItemsOrMore(use_begin(), use_end(), N);
160164
}
161165

@@ -259,9 +263,9 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
259263
}
260264

261265
unsigned Value::getNumUses() const {
262-
if (!hasUseList())
263-
return Uses.Count;
264-
266+
// TODO: Disallow for ConstantData and remove !UseList check?
267+
if (!UseList)
268+
return 0;
265269
return (unsigned)std::distance(use_begin(), use_end());
266270
}
267271

@@ -522,7 +526,7 @@ void Value::doRAUW(Value *New, ReplaceMetadataUses ReplaceMetaUses) {
522526
ValueAsMetadata::handleRAUW(this, New);
523527

524528
while (!materialized_use_empty()) {
525-
Use &U = *Uses.List;
529+
Use &U = *UseList;
526530
// Must handle Constants specially, we cannot call replaceUsesOfWith on a
527531
// constant because they are uniqued.
528532
if (auto *C = dyn_cast<Constant>(U.getUser())) {
@@ -1102,12 +1106,12 @@ const Value *Value::DoPHITranslation(const BasicBlock *CurBB,
11021106
LLVMContext &Value::getContext() const { return VTy->getContext(); }
11031107

11041108
void Value::reverseUseList() {
1105-
if (!Uses.List || !Uses.List->Next || !hasUseList())
1109+
if (!UseList || !UseList->Next)
11061110
// No need to reverse 0 or 1 uses.
11071111
return;
11081112

1109-
Use *Head = Uses.List;
1110-
Use *Current = Uses.List->Next;
1113+
Use *Head = UseList;
1114+
Use *Current = UseList->Next;
11111115
Head->Next = nullptr;
11121116
while (Current) {
11131117
Use *Next = Current->Next;
@@ -1116,8 +1120,8 @@ void Value::reverseUseList() {
11161120
Head = Current;
11171121
Current = Next;
11181122
}
1119-
Uses.List = Head;
1120-
Head->Prev = &Uses.List;
1123+
UseList = Head;
1124+
Head->Prev = &UseList;
11211125
}
11221126

11231127
bool Value::isSwiftError() const {

0 commit comments

Comments
 (0)