Skip to content

Commit 2ecc51c

Browse files
committed
[TableGen] Allow empty terminator in SequenceToOffsetTable
Some clients do not want to emit a terminator after each sub-sequence (they have other means of determining the length of the sub-sequence). This moves `Term` argument from `emit` method to the constructor and makes it optional. It couldn't be made optional while still on the `emit` method because if the terminator wasn't specified, it has to be taken into account in `layout` method as well. The fact that `layout` method was called is now recorded in a dedicated member variable, `IsLaidOut`. `Entries != 0` can no longer be used to reliably check if `layout` method was called because it may be zero for a different reason: the terminator wasn't specified and all added sequences (if any) were empty. This reduces the size of `*LaneMaskLists` and `*SubRegIdxLists` a bit and resolves the removed FIXME.
1 parent 6cfad63 commit 2ecc51c

File tree

7 files changed

+56
-44
lines changed

7 files changed

+56
-44
lines changed

llvm/utils/TableGen/AsmWriterEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ void AsmWriterEmitter::EmitGetMnemonic(
338338
<< "::getMnemonic(const MCInst &MI) const {\n";
339339

340340
// Build an aggregate string, and build a table of offsets into it.
341-
SequenceToOffsetTable<std::string> StringTable;
341+
SequenceToOffsetTable<std::string> StringTable(/*Terminator=*/'\0');
342342

343343
/// OpcodeInfo - This encodes the index of the string to use for the first
344344
/// chunk of the output as well as indices used for operand printing.
@@ -583,7 +583,7 @@ void AsmWriterEmitter::EmitPrintInstruction(
583583
static void
584584
emitRegisterNameString(raw_ostream &O, StringRef AltName,
585585
const std::deque<CodeGenRegister> &Registers) {
586-
SequenceToOffsetTable<std::string> StringTable;
586+
SequenceToOffsetTable<std::string> StringTable(/*Terminator=*/'\0');
587587
SmallVector<std::string, 4> AsmNames(Registers.size());
588588
unsigned i = 0;
589589
for (const auto &Reg : Registers) {

llvm/utils/TableGen/Basic/SequenceToOffsetTable.h

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// SequenceToOffsetTable can be used to emit a number of null-terminated
10-
// sequences as one big array. Use the same memory when a sequence is a suffix
11-
// of another.
9+
// SequenceToOffsetTable can be used to emit a number of sequences as one big
10+
// array. Uses the same memory when a sequence is a suffix of another.
1211
//
1312
//===----------------------------------------------------------------------===//
1413

@@ -65,21 +64,28 @@ class SequenceToOffsetTable {
6564
// Sequences added so far, with suffixes removed.
6665
SeqMap Seqs;
6766

67+
// Terminator element to be appended to each added sequence.
68+
std::optional<ElemT> Terminator;
69+
70+
// True if `layout` method was called.
71+
bool IsLaidOut = false;
72+
6873
// Entries in the final table, or 0 before layout was called.
69-
unsigned Entries;
74+
unsigned Entries = 0;
7075

7176
// isSuffix - Returns true if A is a suffix of B.
7277
static bool isSuffix(const SeqT &A, const SeqT &B) {
7378
return A.size() <= B.size() && std::equal(A.rbegin(), A.rend(), B.rbegin());
7479
}
7580

7681
public:
77-
SequenceToOffsetTable() : Entries(0) {}
82+
explicit SequenceToOffsetTable(std::optional<ElemT> Terminator)
83+
: Terminator(Terminator) {}
7884

7985
/// add - Add a sequence to the table.
8086
/// This must be called before layout().
8187
void add(const SeqT &Seq) {
82-
assert(Entries == 0 && "Cannot call add() after layout()");
88+
assert(!IsLaidOut && "Cannot call add() after layout()");
8389
typename SeqMap::iterator I = Seqs.lower_bound(Seq);
8490

8591
// If SeqMap contains a sequence that has Seq as a suffix, I will be
@@ -97,25 +103,27 @@ class SequenceToOffsetTable {
97103
bool empty() const { return Seqs.empty(); }
98104

99105
unsigned size() const {
100-
assert((empty() || Entries) && "Call layout() before size()");
106+
assert(IsLaidOut && "Call layout() before size()");
101107
return Entries;
102108
}
103109

104110
/// layout - Computes the final table layout.
105111
void layout() {
106-
assert(Entries == 0 && "Can only call layout() once");
112+
assert(!IsLaidOut && "Can only call layout() once");
113+
IsLaidOut = true;
114+
107115
// Lay out the table in Seqs iteration order.
108116
for (typename SeqMap::iterator I = Seqs.begin(), E = Seqs.end(); I != E;
109117
++I) {
110118
I->second = Entries;
111119
// Include space for a terminator.
112-
Entries += I->first.size() + 1;
120+
Entries += I->first.size() + Terminator.has_value();
113121
}
114122
}
115123

116124
/// get - Returns the offset of Seq in the final table.
117125
unsigned get(const SeqT &Seq) const {
118-
assert(Entries && "Call layout() before get()");
126+
assert(IsLaidOut && "Call layout() before get()");
119127
typename SeqMap::const_iterator I = Seqs.lower_bound(Seq);
120128
assert(I != Seqs.end() && isSuffix(Seq, I->first) &&
121129
"get() called with sequence that wasn't added first");
@@ -127,10 +135,10 @@ class SequenceToOffsetTable {
127135
/// `\0`. Falls back to emitting a comma-separated integer list if
128136
/// `EmitLongStrLiterals` is false
129137
void emitStringLiteralDef(raw_ostream &OS, const Twine &Decl) const {
130-
assert(Entries && "Call layout() before emitStringLiteralDef()");
138+
assert(IsLaidOut && "Call layout() before emitStringLiteralDef()");
131139
if (!EmitLongStrLiterals) {
132140
OS << Decl << " = {\n";
133-
emit(OS, printChar, "0");
141+
emit(OS, printChar);
134142
OS << " 0\n};\n\n";
135143
return;
136144
}
@@ -143,7 +151,9 @@ class SequenceToOffsetTable {
143151
for (const auto &[Seq, Offset] : Seqs) {
144152
OS << " /* " << Offset << " */ \"";
145153
OS.write_escaped(Seq);
146-
OS << "\\0\"\n";
154+
if (Terminator)
155+
OS.write_escaped(StringRef(&*Terminator, 1));
156+
OS << "\"\n";
147157
}
148158
OS << "};\n"
149159
<< "#ifdef __GNUC__\n"
@@ -153,16 +163,19 @@ class SequenceToOffsetTable {
153163

154164
/// emit - Print out the table as the body of an array initializer.
155165
/// Use the Print function to print elements.
156-
void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT),
157-
const char *Term = "0") const {
158-
assert((empty() || Entries) && "Call layout() before emit()");
166+
void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT)) const {
167+
assert(IsLaidOut && "Call layout() before emit()");
159168
for (const auto &[Seq, Offset] : Seqs) {
160169
OS << " /* " << Offset << " */ ";
161170
for (const ElemT &Element : Seq) {
162171
Print(OS, Element);
163172
OS << ", ";
164173
}
165-
OS << Term << ",\n";
174+
if (Terminator) {
175+
Print(OS, *Terminator);
176+
OS << ',';
177+
}
178+
OS << '\n';
166179
}
167180
}
168181
};

llvm/utils/TableGen/DFAEmitter.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,17 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
117117
OS << "// transition implies a set of NFA transitions. These are referred\n";
118118
OS << "// to by index in " << Name << "Transitions[].\n";
119119

120-
SequenceToOffsetTable<DfaTransitionInfo> Table;
120+
SequenceToOffsetTable<DfaTransitionInfo> Table(
121+
/*Terminator=*/std::pair(0, 0));
121122
std::map<DfaTransitionInfo, unsigned> EmittedIndices;
122123
for (auto &T : DfaTransitions)
123124
Table.add(T.second.second);
124125
Table.layout();
125126
OS << "const std::array<NfaStatePair, " << Table.size() << "> " << Name
126127
<< "TransitionInfo = {{\n";
127-
Table.emit(
128-
OS,
129-
[](raw_ostream &OS, std::pair<uint64_t, uint64_t> P) {
130-
OS << "{" << P.first << ", " << P.second << "}";
131-
},
132-
"{0ULL, 0ULL}");
128+
Table.emit(OS, [](raw_ostream &OS, std::pair<uint64_t, uint64_t> P) {
129+
OS << "{" << P.first << ", " << P.second << "}";
130+
});
133131

134132
OS << "}};\n\n";
135133

llvm/utils/TableGen/DXILEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,8 @@ static void emitDXILIntrinsicArgSelectTypes(const RecordKeeper &Records,
449449
static void emitDXILOperationTable(ArrayRef<DXILOperationDesc> Ops,
450450
raw_ostream &OS) {
451451
// Collect Names.
452-
SequenceToOffsetTable<std::string> OpClassStrings;
453-
SequenceToOffsetTable<std::string> OpStrings;
452+
SequenceToOffsetTable<std::string> OpClassStrings(/*Terminator=*/'\0');
453+
SequenceToOffsetTable<std::string> OpStrings(/*Terminator=*/'\0');
454454

455455
StringSet<> ClassSet;
456456
for (const auto &Op : Ops) {

llvm/utils/TableGen/InstrInfoEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
988988

989989
OS << "extern const " << TargetName << "InstrTable " << TargetName
990990
<< "Descs = {\n {\n";
991-
SequenceToOffsetTable<std::string> InstrNames;
991+
SequenceToOffsetTable<std::string> InstrNames(/*Terminator=*/'\0');
992992
unsigned Num = NumberedInstructions.size();
993993
for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) {
994994
// Keep a list of the instruction names.

llvm/utils/TableGen/IntrinsicEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
338338
// If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
339339
// capture it in this vector, otherwise store a ~0U.
340340
std::vector<FixedEncodingTy> FixedEncodings;
341-
SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
341+
SequenceToOffsetTable<TypeSigTy> LongEncodingTable(/*Terminator=*/0);
342342

343343
FixedEncodings.reserve(Ints.size());
344344

llvm/utils/TableGen/RegisterInfoEmitter.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS,
288288
<< " return PressureLimitTable[Idx];\n"
289289
<< "}\n\n";
290290

291-
SequenceToOffsetTable<std::vector<int>> PSetsSeqs;
291+
SequenceToOffsetTable<std::vector<int>> PSetsSeqs(/*Terminator=*/-1);
292292

293293
// This table may be larger than NumRCs if some register units needed a list
294294
// of unit sets that did not correspond to a register class.
@@ -309,7 +309,7 @@ void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS,
309309

310310
OS << "/// Table of pressure sets per register class or unit.\n"
311311
<< "static const int RCSetsTable[] = {\n";
312-
PSetsSeqs.emit(OS, printInt, "-1");
312+
PSetsSeqs.emit(OS, printInt);
313313
OS << "};\n\n";
314314

315315
OS << "/// Get the dimensions of register pressure impacted by this "
@@ -610,7 +610,7 @@ static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
610610
}
611611

612612
static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) {
613-
OS << Idx->EnumValue;
613+
OS << (Idx ? Idx->EnumValue : 0);
614614
}
615615

616616
// Differentially encoded register and regunit lists allow for better
@@ -869,22 +869,23 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
869869
typedef std::vector<const CodeGenRegister *> RegVec;
870870

871871
// Differentially encoded lists.
872-
SequenceToOffsetTable<DiffVec> DiffSeqs;
872+
SequenceToOffsetTable<DiffVec> DiffSeqs(/*Terminator=*/0);
873873
SmallVector<DiffVec, 4> SubRegLists(Regs.size());
874874
SmallVector<DiffVec, 4> SuperRegLists(Regs.size());
875875
SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
876876

877877
// List of lane masks accompanying register unit sequences.
878-
SequenceToOffsetTable<MaskVec> LaneMaskSeqs;
878+
SequenceToOffsetTable<MaskVec> LaneMaskSeqs(/*Terminator=*/std::nullopt);
879879
SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size());
880880

881881
// Keep track of sub-register names as well. These are not differentially
882882
// encoded.
883883
typedef SmallVector<const CodeGenSubRegIndex *, 4> SubRegIdxVec;
884-
SequenceToOffsetTable<SubRegIdxVec, deref<std::less<>>> SubRegIdxSeqs;
884+
SequenceToOffsetTable<SubRegIdxVec, deref<std::less<>>> SubRegIdxSeqs(
885+
/*Terminator=*/std::nullopt);
885886
SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
886887

887-
SequenceToOffsetTable<std::string> RegStrings;
888+
SequenceToOffsetTable<std::string> RegStrings(/*Terminator=*/'\0');
888889

889890
// Precompute register lists for the SequenceToOffsetTable.
890891
unsigned i = 0;
@@ -936,9 +937,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
936937

937938
// Emit the shared table of regunit lane mask sequences.
938939
OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
939-
// TODO: Omit the terminator since it is never used. The length of this list
940-
// is known implicitly from the corresponding reg unit list.
941-
LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
940+
LaneMaskSeqs.emit(OS, printMask);
942941
OS << "};\n\n";
943942

944943
// Emit the table of sub-register indexes.
@@ -994,7 +993,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
994993
// Loop over all of the register classes... emitting each one.
995994
OS << "namespace { // Register classes...\n";
996995

997-
SequenceToOffsetTable<std::string> RegClassStrings;
996+
SequenceToOffsetTable<std::string> RegClassStrings(/*Terminator=*/'\0');
998997

999998
// Emit the register enum value arrays for each RegisterClass
1000999
for (const auto &RC : RegisterClasses) {
@@ -1209,7 +1208,8 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) {
12091208
unsigned NumModes = CGH.getNumModeIds();
12101209

12111210
// Build a shared array of value types.
1212-
SequenceToOffsetTable<std::vector<MVT::SimpleValueType>> VTSeqs;
1211+
SequenceToOffsetTable<std::vector<MVT::SimpleValueType>> VTSeqs(
1212+
/*Terminator=*/MVT::Other);
12131213
for (unsigned M = 0; M < NumModes; ++M) {
12141214
for (const auto &RC : RegisterClasses) {
12151215
std::vector<MVT::SimpleValueType> S;
@@ -1221,7 +1221,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) {
12211221
}
12221222
VTSeqs.layout();
12231223
OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n";
1224-
VTSeqs.emit(OS, printSimpleValueType, "MVT::Other");
1224+
VTSeqs.emit(OS, printSimpleValueType);
12251225
OS << "};\n";
12261226

12271227
// Emit SubRegIndex names, skipping 0.
@@ -1307,7 +1307,8 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) {
13071307
// Compress the sub-reg index lists.
13081308
typedef std::vector<const CodeGenSubRegIndex *> IdxList;
13091309
SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
1310-
SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs;
1310+
SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs(
1311+
/*Terminator=*/nullptr);
13111312
BitVector MaskBV(RegisterClasses.size());
13121313

13131314
for (const auto &RC : RegisterClasses) {

0 commit comments

Comments
 (0)