|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 | //
|
9 | 9 | // This tablegen backend emits a generic array initialized by specified fields,
|
10 |
| -// together with companion index tables and lookup functions (binary search, |
11 |
| -// currently). |
| 10 | +// together with companion index tables and lookup functions. The lookup |
| 11 | +// function generated is either a direct lookup (when a single primary key field |
| 12 | +// is integral and densely numbered) or a binary search otherwise. |
12 | 13 | //
|
13 | 14 | //===----------------------------------------------------------------------===//
|
14 | 15 |
|
15 | 16 | #include "CodeGenIntrinsics.h"
|
| 17 | +#include "CodeGenTarget.h" |
16 | 18 | #include "llvm/ADT/ArrayRef.h"
|
17 | 19 | #include "llvm/ADT/DenseMap.h"
|
18 | 20 | #include "llvm/ADT/STLExtras.h"
|
@@ -90,6 +92,7 @@ struct GenericTable {
|
90 | 92 |
|
91 | 93 | class SearchableTableEmitter {
|
92 | 94 | RecordKeeper &Records;
|
| 95 | + std::unique_ptr<CodeGenTarget> Target; |
93 | 96 | DenseMap<Init *, std::unique_ptr<CodeGenIntrinsic>> Intrinsics;
|
94 | 97 | std::vector<std::unique_ptr<GenericEnum>> Enums;
|
95 | 98 | DenseMap<Record *, GenericEnum *> EnumMap;
|
@@ -201,18 +204,23 @@ class SearchableTableEmitter {
|
201 | 204 | const std::vector<Record *> &Items);
|
202 | 205 | void collectTableEntries(GenericTable &Table,
|
203 | 206 | const std::vector<Record *> &Items);
|
| 207 | + int64_t getNumericKey(const SearchIndex &Index, Record *Rec); |
204 | 208 | };
|
205 | 209 |
|
206 | 210 | } // End anonymous namespace.
|
207 | 211 |
|
208 | 212 | // For search indices that consists of a single field whose numeric value is
|
209 | 213 | // known, return that numeric value.
|
210 |
| -static int64_t getNumericKey(const SearchIndex &Index, Record *Rec) { |
| 214 | +int64_t SearchableTableEmitter::getNumericKey(const SearchIndex &Index, |
| 215 | + Record *Rec) { |
211 | 216 | assert(Index.Fields.size() == 1);
|
212 | 217 |
|
213 | 218 | if (Index.Fields[0].Enum) {
|
214 | 219 | Record *EnumEntry = Rec->getValueAsDef(Index.Fields[0].Name);
|
215 | 220 | return Index.Fields[0].Enum->EntryMap[EnumEntry]->second;
|
| 221 | + } else if (Index.Fields[0].IsInstruction) { |
| 222 | + Record *TheDef = Rec->getValueAsDef(Index.Fields[0].Name); |
| 223 | + return Target->getInstrIntValue(TheDef); |
216 | 224 | }
|
217 | 225 |
|
218 | 226 | return getInt(Rec, Index.Fields[0].Name);
|
@@ -370,20 +378,31 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
|
370 | 378 | bool IsContiguous = false;
|
371 | 379 |
|
372 | 380 | if (Index.Fields.size() == 1 &&
|
373 |
| - (Index.Fields[0].Enum || isa<BitsRecTy>(Index.Fields[0].RecType))) { |
| 381 | + (Index.Fields[0].Enum || isa<BitsRecTy>(Index.Fields[0].RecType) || |
| 382 | + Index.Fields[0].IsInstruction)) { |
| 383 | + int64_t FirstKeyVal = getNumericKey(Index, IndexRows[0]); |
374 | 384 | IsContiguous = true;
|
375 | 385 | for (unsigned i = 0; i < IndexRows.size(); ++i) {
|
376 |
| - if (getNumericKey(Index, IndexRows[i]) != i) { |
| 386 | + if (getNumericKey(Index, IndexRows[i]) != (FirstKeyVal + i)) { |
377 | 387 | IsContiguous = false;
|
378 | 388 | break;
|
379 | 389 | }
|
380 | 390 | }
|
381 | 391 | }
|
382 | 392 |
|
383 | 393 | if (IsContiguous) {
|
| 394 | + const GenericField &Field = Index.Fields[0]; |
| 395 | + std::string FirstRepr = primaryRepresentation( |
| 396 | + Index.Loc, Field, IndexRows[0]->getValueInit(Field.Name)); |
| 397 | + std::string LastRepr = primaryRepresentation( |
| 398 | + Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name)); |
| 399 | + OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n"; |
| 400 | + OS << " (" << Field.Name << " > " << LastRepr << "))\n"; |
| 401 | + OS << " return nullptr;\n"; |
384 | 402 | OS << " auto Table = ArrayRef(" << IndexName << ");\n";
|
385 |
| - OS << " size_t Idx = " << Index.Fields[0].Name << ";\n"; |
386 |
| - OS << " return Idx >= Table.size() ? nullptr : "; |
| 403 | + OS << " size_t Idx = " << Index.Fields[0].Name << " - " << FirstRepr |
| 404 | + << ";\n"; |
| 405 | + OS << " return "; |
387 | 406 | if (IsPrimary)
|
388 | 407 | OS << "&Table[Idx]";
|
389 | 408 | else
|
@@ -663,6 +682,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
|
663 | 682 | // Emit tables in a deterministic order to avoid needless rebuilds.
|
664 | 683 | SmallVector<std::unique_ptr<GenericTable>, 4> Tables;
|
665 | 684 | DenseMap<Record *, GenericTable *> TableMap;
|
| 685 | + if (!Records.getAllDerivedDefinitionsIfDefined("Instruction").empty()) |
| 686 | + Target = std::make_unique<CodeGenTarget>(Records); |
666 | 687 |
|
667 | 688 | // Collect all definitions first.
|
668 | 689 | for (auto *EnumRec : Records.getAllDerivedDefinitions("GenericEnum")) {
|
|
0 commit comments