diff options
| author | Justin Bogner <mail@justinbogner.com> | 2019-07-16 22:39:18 +0000 |
|---|---|---|
| committer | Justin Bogner <mail@justinbogner.com> | 2019-07-16 22:39:18 +0000 |
| commit | 418516c7b8658994622273a2a44a9fba3280dcfc (patch) | |
| tree | 25e0f63f03db3f05d0c000e627a5ee905ca76cee /llvm/utils/TableGen | |
| parent | fdeed837edf354558cf0c6b0a0dd3af2124906b8 (diff) | |
| download | bcm5719-llvm-418516c7b8658994622273a2a44a9fba3280dcfc.tar.gz bcm5719-llvm-418516c7b8658994622273a2a44a9fba3280dcfc.zip | |
[TableGen] Generate offsets into a flat array for getOperandType
Rather than an array of std::initializer_list, generate a table of
offsets and a flat array of the operands for getOperandType. This is a
bit more efficient on platforms that don't manage to get the array of
inintializer_lists initialized at link time (I'm looking at you
macOS). It's also quite quite a bit faster to compile.
llvm-svn: 366278
Diffstat (limited to 'llvm/utils/TableGen')
| -rw-r--r-- | llvm/utils/TableGen/InstrInfoEmitter.cpp | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index d92585685e1..2d367f538b7 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -213,7 +213,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, } /// Initialize data structures for generating operand name mappings. -/// +/// /// \param Operands [out] A map used to generate the OpName enum with operand /// names as its keys and operand enum values as its values. /// \param OperandMap [out] A map for representing the operand name mappings for @@ -360,41 +360,54 @@ void InstrInfoEmitter::emitOperandTypeMappings( OS << "LLVM_READONLY\n"; OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n"; if (!NumberedInstructions.empty()) { - OS << " static const std::initializer_list<int> OpcodeOperandTypes[] = " - "{\n"; + std::vector<int> OperandOffsets; + std::vector<Record *> OperandRecords; + int CurrentOffset = 0; for (const CodeGenInstruction *Inst : NumberedInstructions) { - OS << " { "; + OperandOffsets.push_back(CurrentOffset); for (const auto &Op : Inst->Operands) { - // Handle aggregate operands and normal operands the same way by - // expanding either case into a list of operands for this op. - std::vector<CGIOperandList::OperandInfo> OperandList; - const DagInit *MIOI = Op.MIOperandInfo; if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. - OperandList.push_back(Op); + OperandRecords.push_back(Op.Rec); + ++CurrentOffset; } else { - for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { - OperandList.push_back(Op); - - auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); - OperandList.back().Rec = OpR; + for (Init *Arg : make_range(MIOI->arg_begin(), MIOI->arg_end())) { + OperandRecords.push_back(cast<DefInit>(Arg)->getDef()); + ++CurrentOffset; } } - - for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { - Record *OpR = OperandList[j].Rec; - if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous()) - OS << "OpTypes::" << OpR->getName(); - else - OS << -1; - OS << ", "; - } } - OS << "},\n"; } + + // Emit the table of offsets for the opcode lookup. + OS << " const int Offsets[] = {\n"; + for (int I = 0, E = OperandOffsets.size(); I != E; ++I) + OS << " " << OperandOffsets[I] << ",\n"; OS << " };\n"; - OS << " return OpcodeOperandTypes[Opcode].begin()[OpIdx];\n"; + + // Add an entry for the end so that we don't need to special case it below. + OperandOffsets.push_back(OperandRecords.size()); + // Emit the actual operand types in a flat table. + OS << " const int OpcodeOperandTypes[] = {\n "; + for (int I = 0, E = OperandRecords.size(), CurOffset = 1; I != E; ++I) { + // We print each Opcode's operands in its own row. + if (I == OperandOffsets[CurOffset]) { + OS << "\n "; + // If there are empty rows, mark them with an empty comment. + while (OperandOffsets[++CurOffset] == I) + OS << "/**/\n "; + } + Record *OpR = OperandRecords[I]; + if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous()) + OS << "OpTypes::" << OpR->getName(); + else + OS << -1; + OS << ", "; + } + OS << "\n };\n"; + + OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n"; } else { OS << " llvm_unreachable(\"No instructions defined\");\n"; } |

