Skip to content

Commit cec0191

Browse files
committed
[RISCV]Add support for resolving encoding conflicts among vendor specific CSRs
This patch adds the framework for resolving encoding conflicts among CSRs. Specifically, this patch adds a support for emitting a second lookup function for the primary key which takes an additional arguemnt `List` of type `std::vector` and inside the function definition, will populate the `List` with all sysreg that matches primary key. While printing the CSR name during objdump, iterate over the `List` and print the name of only that CSR which satisifes the feature requirement of subtarget. Below are the signatures of the functions that are generated for primary key: ``` `const SysReg *lookupSysRegByEncoding(uint16_t Encoding);` `void lookupSysRegByEncoding(uint16_t Encoding, std::vector<const SysReg*> &List);` ``` Below is the definition for the second primary function: ``` void lookupSysRegByEncoding(uint16_t Encoding, std::vector<const SysReg*> &List) { struct KeyType { uint16_t Encoding; }; KeyType Key = {Encoding}; auto Table = ArrayRef(SysRegsList); auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, [](const SysReg &LHS, const KeyType &RHS) { if (LHS.Encoding < RHS.Encoding) return true; if (LHS.Encoding > RHS.Encoding) return false; return false; }); if (Idx == Table.end() || Key.Encoding != Idx->Encoding) return; auto UpperBound = std::upper_bound(Table.begin(), Table.end(), Key, [](const KeyType &LHS, const SysReg &RHS) { if (LHS.Encoding < RHS.Encoding) return true; if (LHS.Encoding > RHS.Encoding) return false; return false; }); while(Idx != UpperBound){ List.push_back(&SysRegsList[Idx - Table.begin()]); Idx++; } } ``` Usage: CSRs with same encodings need to be under separate features. Below is example illustrating the same- ``` let FeaturesRequired = [{ {Feature1} }] in { def : SysReg<"csr1", 0x123>; } let FeaturesRequired = [{ {Feature2} }] in { def : SysReg<"csr2", 0x123>; } ```
1 parent 0dd4377 commit cec0191

File tree

2 files changed

+99
-48
lines changed

2 files changed

+99
-48
lines changed

llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,15 @@ void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo,
121121
const MCSubtargetInfo &STI,
122122
raw_ostream &O) {
123123
unsigned Imm = MI->getOperand(OpNo).getImm();
124-
auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
125-
if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits()))
126-
markup(O, Markup::Register) << SysReg->Name;
127-
else
128-
markup(O, Markup::Register) << formatImm(Imm);
124+
std::vector<const RISCVSysReg::SysReg *> CSRList;
125+
RISCVSysReg::lookupSysRegByEncoding(Imm, CSRList);
126+
for(auto &Reg : CSRList){
127+
if (Reg->haveRequiredFeatures(STI.getFeatureBits())) {
128+
markup(O, Markup::Register) << Reg->Name;
129+
return;
130+
}
131+
}
132+
markup(O, Markup::Register) << formatImm(Imm);
129133
}
130134

131135
void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,

llvm/utils/TableGen/SearchableTableEmitter.cpp

Lines changed: 90 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,11 @@ class SearchableTableEmitter {
190190
void emitGenericTable(const GenericTable &Table, raw_ostream &OS);
191191
void emitGenericEnum(const GenericEnum &Enum, raw_ostream &OS);
192192
void emitLookupDeclaration(const GenericTable &Table,
193-
const SearchIndex &Index, raw_ostream &OS);
193+
const SearchIndex &Index, bool UseListArg,
194+
raw_ostream &OS);
194195
void emitLookupFunction(const GenericTable &Table, const SearchIndex &Index,
195-
bool IsPrimary, raw_ostream &OS);
196+
bool IsPrimary, bool UseListArg,
197+
raw_ostream &OS);
196198
void emitIfdef(StringRef Guard, raw_ostream &OS);
197199

198200
bool parseFieldType(GenericField &Field, Init *II);
@@ -319,9 +321,10 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
319321
void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
320322
const SearchIndex &Index,
321323
bool IsPrimary,
324+
bool UseListArg,
322325
raw_ostream &OS) {
323326
OS << "\n";
324-
emitLookupDeclaration(Table, Index, OS);
327+
emitLookupDeclaration(Table, Index, UseListArg, OS);
325328
OS << " {\n";
326329

327330
std::vector<Record *> IndexRowsStorage;
@@ -401,16 +404,19 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
401404
Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name));
402405
OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n";
403406
OS << " (" << Field.Name << " > " << LastRepr << "))\n";
404-
OS << " return nullptr;\n";
407+
if (UseListArg)
408+
OS << " return;\n";
409+
else
410+
OS << " return nullptr;\n";
405411
OS << " auto Table = ArrayRef(" << IndexName << ");\n";
406412
OS << " size_t Idx = " << Index.Fields[0].Name << " - " << FirstRepr
407413
<< ";\n";
408-
OS << " return ";
409-
if (IsPrimary)
410-
OS << "&Table[Idx]";
414+
if (UseListArg)
415+
OS << " return;\n";
416+
else if (IsPrimary)
417+
OS << " return &Table[Idx];\n";
411418
else
412-
OS << "&" << Table.Name << "[Table[Idx]._index]";
413-
OS << ";\n";
419+
OS << " return &" << Table.Name << "[Table[Idx]._index];\n";
414420
OS << "}\n";
415421
return;
416422
}
@@ -423,7 +429,10 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
423429
Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name));
424430
OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n";
425431
OS << " (" << Field.Name << " > " << LastRepr << "))\n";
426-
OS << " return nullptr;\n\n";
432+
if (UseListArg)
433+
OS << " return;\n\n";
434+
else
435+
OS << " return nullptr;\n\n";
427436
}
428437

429438
OS << " struct KeyType {\n";
@@ -452,55 +461,80 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
452461
OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n";
453462
OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n";
454463

455-
for (const auto &Field : Index.Fields) {
456-
if (isa<StringRecTy>(Field.RecType)) {
457-
OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
458-
<< ").compare(RHS." << Field.Name << ");\n";
459-
OS << " if (Cmp" << Field.Name << " < 0) return true;\n";
460-
OS << " if (Cmp" << Field.Name << " > 0) return false;\n";
461-
} else if (Field.Enum) {
462-
// Explicitly cast to unsigned, because the signedness of enums is
463-
// compiler-dependent.
464-
OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
465-
<< Field.Name << ")\n";
466-
OS << " return true;\n";
467-
OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
468-
<< Field.Name << ")\n";
469-
OS << " return false;\n";
470-
} else {
471-
OS << " if (LHS." << Field.Name << " < RHS." << Field.Name << ")\n";
472-
OS << " return true;\n";
473-
OS << " if (LHS." << Field.Name << " > RHS." << Field.Name << ")\n";
474-
OS << " return false;\n";
464+
auto emitComparator = [&]() {
465+
for (const auto &Field : Index.Fields) {
466+
if (isa<StringRecTy>(Field.RecType)) {
467+
OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
468+
<< ").compare(RHS." << Field.Name << ");\n";
469+
OS << " if (Cmp" << Field.Name << " < 0) return true;\n";
470+
OS << " if (Cmp" << Field.Name << " > 0) return false;\n";
471+
} else if (Field.Enum) {
472+
// Explicitly cast to unsigned, because the signedness of enums is
473+
// compiler-dependent.
474+
OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
475+
<< Field.Name << ")\n";
476+
OS << " return true;\n";
477+
OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
478+
<< Field.Name << ")\n";
479+
OS << " return false;\n";
480+
} else {
481+
OS << " if (LHS." << Field.Name << " < RHS." << Field.Name
482+
<< ")\n";
483+
OS << " return true;\n";
484+
OS << " if (LHS." << Field.Name << " > RHS." << Field.Name
485+
<< ")\n";
486+
OS << " return false;\n";
487+
}
475488
}
476-
}
477489

478-
OS << " return false;\n";
479-
OS << " });\n\n";
490+
OS << " return false;\n";
491+
OS << " });\n\n";
492+
};
493+
emitComparator();
480494

481495
OS << " if (Idx == Table.end()";
482496

483497
for (const auto &Field : Index.Fields)
484498
OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name;
485-
OS << ")\n return nullptr;\n";
486499

487-
if (IsPrimary)
500+
if (UseListArg) {
501+
OS << ")\n return;\n\n";
502+
OS << " auto UpperBound = std::upper_bound(Table.begin(), Table.end(), "
503+
"Key,\n";
504+
OS << " [](const KeyType &LHS, const " << IndexTypeName << " &RHS) {\n";
505+
emitComparator();
506+
OS << " while(Idx != UpperBound){\n";
507+
OS << " List.push_back(&" << Table.Name << "[Idx - Table.begin()]);\n";
508+
OS << " Idx++;\n";
509+
OS << " }\n";
510+
} else if (IsPrimary) {
511+
OS << ")\n return nullptr;\n\n";
488512
OS << " return &*Idx;\n";
489-
else
513+
} else {
514+
OS << ")\n return nullptr;\n\n";
490515
OS << " return &" << Table.Name << "[Idx->_index];\n";
516+
}
491517

492518
OS << "}\n";
493519
}
494520

495521
void SearchableTableEmitter::emitLookupDeclaration(const GenericTable &Table,
496522
const SearchIndex &Index,
523+
bool UseListArg,
497524
raw_ostream &OS) {
498-
OS << "const " << Table.CppTypeName << " *" << Index.Name << "(";
499-
525+
if (UseListArg)
526+
OS << "void ";
527+
else
528+
OS << "const " << Table.CppTypeName << " *";
529+
OS << Index.Name << "(";
500530
ListSeparator LS;
501531
for (const auto &Field : Index.Fields)
502532
OS << LS << searchableFieldType(Table, Index, Field, TypeInArgument) << " "
503533
<< Field.Name;
534+
535+
if (UseListArg)
536+
OS << ", std::vector<const " << Table.CppTypeName << "*> &List";
537+
504538
OS << ")";
505539
}
506540

@@ -510,11 +544,14 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
510544

511545
// Emit the declarations for the functions that will perform lookup.
512546
if (Table.PrimaryKey) {
513-
emitLookupDeclaration(Table, *Table.PrimaryKey, OS);
547+
auto &Index = *Table.PrimaryKey;
548+
emitLookupDeclaration(Table, Index, /*UseListArg=*/false, OS);
549+
OS << ";\n";
550+
emitLookupDeclaration(Table, Index, /*UseListArg=*/true, OS);
514551
OS << ";\n";
515552
}
516553
for (const auto &Index : Table.Indices) {
517-
emitLookupDeclaration(Table, *Index, OS);
554+
emitLookupDeclaration(Table, *Index, /*UseListArg=*/false, OS);
518555
OS << ";\n";
519556
}
520557

@@ -540,10 +577,20 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
540577

541578
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542579
// search can be performed by "Thing".
543-
if (Table.PrimaryKey)
544-
emitLookupFunction(Table, *Table.PrimaryKey, true, OS);
580+
if (Table.PrimaryKey) {
581+
auto &Index = *Table.PrimaryKey;
582+
// Two lookupfunction functions need to be generated to allow more than one
583+
// lookup signature for the primary key lookup : first will return a SysReg
584+
// that matches the primary key, second will populate a vector passed as
585+
// argument with all the SysRegs that match the primary key.
586+
emitLookupFunction(Table, Index, /*IsPrimary=*/true,
587+
/*UseListArg=*/false, OS);
588+
emitLookupFunction(Table, Index, /*IsPrimary=*/true,
589+
/*UseListArg=*/true, OS);
590+
}
545591
for (const auto &Index : Table.Indices)
546-
emitLookupFunction(Table, *Index, false, OS);
592+
emitLookupFunction(Table, *Index, /*IsPrimary=*/false,
593+
/*UseListArg=*/false, OS);
547594

548595
OS << "#endif\n\n";
549596
}

0 commit comments

Comments
 (0)