llvm.org GIT mirror llvm / c50b982
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366278 91177308-0d34-0410-b5e6-96231b3b80d8 Justin Bogner a month ago
2 changed file(s) with 41 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
3434 }
3535
3636 // CHECK: #ifdef GET_INSTRINFO_OPERAND_TYPE
37 // CHECK: { OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm, }
38 // CHECK-NEXT: { OpTypes::i32imm, -1, }
37 // CHECK: OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm,
38 // CHECK-NEXT: OpTypes::i32imm, -1,
3939 // CHECK: #endif //GET_INSTRINFO_OPERAND_TYPE
212212 }
213213
214214 /// Initialize data structures for generating operand name mappings.
215 ///
215 ///
216216 /// \param Operands [out] A map used to generate the OpName enum with operand
217217 /// names as its keys and operand enum values as its values.
218218 /// \param OperandMap [out] A map for representing the operand name mappings for
359359 OS << "LLVM_READONLY\n";
360360 OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";
361361 if (!NumberedInstructions.empty()) {
362 OS << " static const std::initializer_list OpcodeOperandTypes[] = "
363 "{\n";
362 std::vector OperandOffsets;
363 std::vector OperandRecords;
364 int CurrentOffset = 0;
364365 for (const CodeGenInstruction *Inst : NumberedInstructions) {
365 OS << " { ";
366 OperandOffsets.push_back(CurrentOffset);
366367 for (const auto &Op : Inst->Operands) {
367 // Handle aggregate operands and normal operands the same way by
368 // expanding either case into a list of operands for this op.
369 std::vector OperandList;
370
371368 const DagInit *MIOI = Op.MIOperandInfo;
372369 if (!MIOI || MIOI->getNumArgs() == 0) {
373370 // Single, anonymous, operand.
374 OperandList.push_back(Op);
371 OperandRecords.push_back(Op.Rec);
372 ++CurrentOffset;
375373 } else {
376 for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
377 OperandList.push_back(Op);
378
379 auto *OpR = cast(MIOI->getArg(j))->getDef();
380 OperandList.back().Rec = OpR;
374 for (Init *Arg : make_range(MIOI->arg_begin(), MIOI->arg_end())) {
375 OperandRecords.push_back(cast(Arg)->getDef());
376 ++CurrentOffset;
381377 }
382378 }
383
384 for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
385 Record *OpR = OperandList[j].Rec;
386 if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous())
387 OS << "OpTypes::" << OpR->getName();
388 else
389 OS << -1;
390 OS << ", ";
391 }
392379 }
393 OS << "},\n";
394 }
380 }
381
382 // Emit the table of offsets for the opcode lookup.
383 OS << " const int Offsets[] = {\n";
384 for (int I = 0, E = OperandOffsets.size(); I != E; ++I)
385 OS << " " << OperandOffsets[I] << ",\n";
395386 OS << " };\n";
396 OS << " return OpcodeOperandTypes[Opcode].begin()[OpIdx];\n";
387
388 // Add an entry for the end so that we don't need to special case it below.
389 OperandOffsets.push_back(OperandRecords.size());
390 // Emit the actual operand types in a flat table.
391 OS << " const int OpcodeOperandTypes[] = {\n ";
392 for (int I = 0, E = OperandRecords.size(), CurOffset = 1; I != E; ++I) {
393 // We print each Opcode's operands in its own row.
394 if (I == OperandOffsets[CurOffset]) {
395 OS << "\n ";
396 // If there are empty rows, mark them with an empty comment.
397 while (OperandOffsets[++CurOffset] == I)
398 OS << "/**/\n ";
399 }
400 Record *OpR = OperandRecords[I];
401 if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous())
402 OS << "OpTypes::" << OpR->getName();
403 else
404 OS << -1;
405 OS << ", ";
406 }
407 OS << "\n };\n";
408
409 OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";
397410 } else {
398411 OS << " llvm_unreachable(\"No instructions defined\");\n";
399412 }