[llvm] r366278 - [TableGen] Generate offsets into a flat array for getOperandType
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 16 15:39:18 PDT 2019
Author: bogner
Date: Tue Jul 16 15:39:18 2019
New Revision: 366278
URL: http://llvm.org/viewvc/llvm-project?rev=366278&view=rev
Log:
[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.
Modified:
llvm/trunk/test/TableGen/get-operand-type.td
llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
Modified: llvm/trunk/test/TableGen/get-operand-type.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/get-operand-type.td?rev=366278&r1=366277&r2=366278&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/get-operand-type.td (original)
+++ llvm/trunk/test/TableGen/get-operand-type.td Tue Jul 16 15:39:18 2019
@@ -35,6 +35,6 @@ def InstB : Instruction {
}
// CHECK: #ifdef GET_INSTRINFO_OPERAND_TYPE
-// CHECK: { OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm, }
-// CHECK-NEXT: { OpTypes::i32imm, -1, }
+// CHECK: OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm,
+// CHECK-NEXT: OpTypes::i32imm, -1,
// CHECK: #endif //GET_INSTRINFO_OPERAND_TYPE
Modified: llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp?rev=366278&r1=366277&r2=366278&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp Tue Jul 16 15:39:18 2019
@@ -213,7 +213,7 @@ void InstrInfoEmitter::EmitOperandInfo(r
}
/// 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::emitOperandTypeMa
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";
}
More information about the llvm-commits
mailing list