Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions llvm/test/TableGen/MixedCasedMnemonic.td
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def :MnemonicAlias<"InstB", "BInst">;

// Check that the writer preserves the case of the mnemonics.
// WRITER: static const char AsmStrs[] = {
// WRITER: "BInst\0"
// WRITER-NEXT: "aInst\0"
// WRITER: "BInst\000"
// WRITER-NEXT: "aInst\000"
// WRITER-NEXT: };

// ALIAS: static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID) {
Expand All @@ -73,4 +73,3 @@ def :MnemonicAlias<"InstB", "BInst">;
// ALIAS-NEXT case 'b': // 1 string to match.
// ALIAS-NEXT Mnemonic = "binst"; // "instb"
// ALIAS-NEXT return;

54 changes: 37 additions & 17 deletions llvm/utils/TableGen/Basic/SequenceToOffsetTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
//
//===----------------------------------------------------------------------===//
//
// SequenceToOffsetTable can be used to emit a number of null-terminated
// sequences as one big array. Use the same memory when a sequence is a suffix
// of another.
// SequenceToOffsetTable can be used to emit a number of sequences as one big
// array. Uses the same memory when a sequence is a suffix of another.
//
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -65,21 +64,28 @@ class SequenceToOffsetTable {
// Sequences added so far, with suffixes removed.
SeqMap Seqs;

// Terminator element to be appended to each added sequence.
std::optional<ElemT> Terminator;

// True if `layout` method was called.
bool IsLaidOut = false;

// Entries in the final table, or 0 before layout was called.
unsigned Entries;
unsigned Entries = 0;

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

public:
SequenceToOffsetTable() : Entries(0) {}
explicit SequenceToOffsetTable(std::optional<ElemT> Terminator = ElemT())
: Terminator(Terminator) {}

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

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

unsigned size() const {
assert((empty() || Entries) && "Call layout() before size()");
assert(IsLaidOut && "Call layout() before size()");
return Entries;
}

/// layout - Computes the final table layout.
void layout() {
assert(Entries == 0 && "Can only call layout() once");
assert(!IsLaidOut && "Can only call layout() once");
IsLaidOut = true;

// Lay out the table in Seqs iteration order.
for (typename SeqMap::iterator I = Seqs.begin(), E = Seqs.end(); I != E;
++I) {
I->second = Entries;
// Include space for a terminator.
Entries += I->first.size() + 1;
Entries += I->first.size() + Terminator.has_value();
}
}

/// get - Returns the offset of Seq in the final table.
unsigned get(const SeqT &Seq) const {
assert(Entries && "Call layout() before get()");
assert(IsLaidOut && "Call layout() before get()");
typename SeqMap::const_iterator I = Seqs.lower_bound(Seq);
assert(I != Seqs.end() && isSuffix(Seq, I->first) &&
"get() called with sequence that wasn't added first");
Expand All @@ -127,10 +135,10 @@ class SequenceToOffsetTable {
/// `\0`. Falls back to emitting a comma-separated integer list if
/// `EmitLongStrLiterals` is false
void emitStringLiteralDef(raw_ostream &OS, const Twine &Decl) const {
assert(Entries && "Call layout() before emitStringLiteralDef()");
assert(IsLaidOut && "Call layout() before emitStringLiteralDef()");
if (!EmitLongStrLiterals) {
OS << Decl << " = {\n";
emit(OS, printChar, "0");
emit(OS, printChar);
OS << " 0\n};\n\n";
return;
}
Expand All @@ -143,7 +151,9 @@ class SequenceToOffsetTable {
for (const auto &[Seq, Offset] : Seqs) {
OS << " /* " << Offset << " */ \"";
OS.write_escaped(Seq);
OS << "\\0\"\n";
if (Terminator)
OS.write_escaped(StringRef(&*Terminator, 1));
OS << "\"\n";
}
OS << "};\n"
<< "#ifdef __GNUC__\n"
Expand All @@ -153,16 +163,26 @@ class SequenceToOffsetTable {

/// emit - Print out the table as the body of an array initializer.
/// Use the Print function to print elements.
void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT),
const char *Term = "0") const {
assert((empty() || Entries) && "Call layout() before emit()");
void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT)) const {
assert(IsLaidOut && "Call layout() before emit()");
for (const auto &[Seq, Offset] : Seqs) {
OS << " /* " << Offset << " */ ";
for (const ElemT &Element : Seq) {
Print(OS, Element);
OS << ", ";
}
OS << Term << ",\n";
if (Terminator) {
Print(OS, *Terminator);
OS << ',';
}
OS << '\n';
}

// Print a dummy element if the array would be empty otherwise.
if (!Entries) {
OS << " /* dummy */ ";
Print(OS, ElemT());
OS << '\n';
}
}
};
Expand Down
9 changes: 3 additions & 6 deletions llvm/utils/TableGen/DFAEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,9 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
Table.layout();
OS << "const std::array<NfaStatePair, " << Table.size() << "> " << Name
<< "TransitionInfo = {{\n";
Table.emit(
OS,
[](raw_ostream &OS, std::pair<uint64_t, uint64_t> P) {
OS << "{" << P.first << ", " << P.second << "}";
},
"{0ULL, 0ULL}");
Table.emit(OS, [](raw_ostream &OS, std::pair<uint64_t, uint64_t> P) {
OS << "{" << P.first << ", " << P.second << "}";
});

OS << "}};\n\n";

Expand Down
20 changes: 10 additions & 10 deletions llvm/utils/TableGen/RegisterInfoEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS,
<< " return PressureLimitTable[Idx];\n"
<< "}\n\n";

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

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

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

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

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

// Differentially encoded register and regunit lists allow for better
Expand Down Expand Up @@ -875,13 +875,14 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
SmallVector<DiffVec, 4> RegUnitLists(Regs.size());

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

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

SequenceToOffsetTable<std::string> RegStrings;
Expand Down Expand Up @@ -936,9 +937,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {

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

// Emit the table of sub-register indexes.
Expand Down Expand Up @@ -1209,7 +1208,8 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) {
unsigned NumModes = CGH.getNumModeIds();

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

// Emit SubRegIndex names, skipping 0.
Expand Down
Loading