|
19 | 19 | #include "SequenceToOffsetTable.h"
|
20 | 20 | #include "TableGenBackends.h"
|
21 | 21 | #include "llvm/ADT/ArrayRef.h"
|
| 22 | +#include "llvm/ADT/STLExtras.h" |
22 | 23 | #include "llvm/ADT/StringExtras.h"
|
23 | 24 | #include "llvm/Support/Casting.h"
|
24 | 25 | #include "llvm/Support/raw_ostream.h"
|
|
27 | 28 | #include "llvm/TableGen/TableGenBackend.h"
|
28 | 29 | #include <cassert>
|
29 | 30 | #include <cstdint>
|
| 31 | +#include <iterator> |
30 | 32 | #include <map>
|
31 | 33 | #include <string>
|
32 | 34 | #include <utility>
|
@@ -87,6 +89,13 @@ class InstrInfoEmitter {
|
87 | 89 | void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target,
|
88 | 90 | ArrayRef<const CodeGenInstruction*> NumberedInstructions);
|
89 | 91 |
|
| 92 | + void emitLogicalOperandSizeMappings( |
| 93 | + raw_ostream &OS, StringRef Namespace, |
| 94 | + ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
| 95 | + void emitLogicalOperandTypeMappings( |
| 96 | + raw_ostream &OS, StringRef Namespace, |
| 97 | + ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
| 98 | + |
90 | 99 | // Operand information.
|
91 | 100 | void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
|
92 | 101 | std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
|
@@ -442,6 +451,182 @@ void InstrInfoEmitter::emitOperandTypeMappings(
|
442 | 451 | OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n";
|
443 | 452 | }
|
444 | 453 |
|
| 454 | +void InstrInfoEmitter::emitLogicalOperandSizeMappings( |
| 455 | + raw_ostream &OS, StringRef Namespace, |
| 456 | + ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
| 457 | + std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap; |
| 458 | + |
| 459 | + std::map<unsigned, std::vector<std::string>> InstMap; |
| 460 | + |
| 461 | + size_t LogicalOpListSize = 0U; |
| 462 | + std::vector<unsigned> LogicalOpList; |
| 463 | + for (const auto *Inst : NumberedInstructions) { |
| 464 | + if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings")) |
| 465 | + continue; |
| 466 | + |
| 467 | + LogicalOpList.clear(); |
| 468 | + llvm::transform(Inst->Operands, std::back_inserter(LogicalOpList), |
| 469 | + [](const CGIOperandList::OperandInfo &Op) -> unsigned { |
| 470 | + auto *MIOI = Op.MIOperandInfo; |
| 471 | + if (!MIOI || MIOI->getNumArgs() == 0) |
| 472 | + return 1; |
| 473 | + return MIOI->getNumArgs(); |
| 474 | + }); |
| 475 | + LogicalOpListSize = std::max(LogicalOpList.size(), LogicalOpListSize); |
| 476 | + |
| 477 | + auto I = |
| 478 | + LogicalOpSizeMap.insert({LogicalOpList, LogicalOpSizeMap.size()}).first; |
| 479 | + InstMap[I->second].push_back( |
| 480 | + (Namespace + "::" + Inst->TheDef->getName()).str()); |
| 481 | + } |
| 482 | + |
| 483 | + OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n"; |
| 484 | + OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n"; |
| 485 | + OS << "namespace llvm {\n"; |
| 486 | + OS << "namespace " << Namespace << " {\n"; |
| 487 | + OS << "LLVM_READONLY static unsigned\n"; |
| 488 | + OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n"; |
| 489 | + if (!InstMap.empty()) { |
| 490 | + std::vector<const std::vector<unsigned> *> LogicalOpSizeList( |
| 491 | + LogicalOpSizeMap.size()); |
| 492 | + for (auto &P : LogicalOpSizeMap) { |
| 493 | + LogicalOpSizeList[P.second] = &P.first; |
| 494 | + } |
| 495 | + OS << " static const unsigned SizeMap[][" << LogicalOpListSize |
| 496 | + << "] = {\n"; |
| 497 | + for (int r = 0, rs = LogicalOpSizeList.size(); r < rs; ++r) { |
| 498 | + const auto &Row = *LogicalOpSizeList[r]; |
| 499 | + OS << " {"; |
| 500 | + int i; |
| 501 | + for (i = 0; i < static_cast<int>(Row.size()); ++i) { |
| 502 | + OS << Row[i] << ", "; |
| 503 | + } |
| 504 | + for (; i < static_cast<int>(LogicalOpListSize); ++i) { |
| 505 | + OS << "0, "; |
| 506 | + } |
| 507 | + OS << "}, "; |
| 508 | + OS << "\n"; |
| 509 | + } |
| 510 | + OS << " };\n"; |
| 511 | + |
| 512 | + OS << " switch (Opcode) {\n"; |
| 513 | + OS << " default: return LogicalOpIdx;\n"; |
| 514 | + for (auto &P : InstMap) { |
| 515 | + auto OpMapIdx = P.first; |
| 516 | + const auto &Insts = P.second; |
| 517 | + for (const auto &Inst : Insts) { |
| 518 | + OS << " case " << Inst << ":\n"; |
| 519 | + } |
| 520 | + OS << " return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n"; |
| 521 | + } |
| 522 | + OS << " }\n"; |
| 523 | + } else { |
| 524 | + OS << " return LogicalOpIdx;\n"; |
| 525 | + } |
| 526 | + OS << "}\n"; |
| 527 | + |
| 528 | + OS << "LLVM_READONLY static inline unsigned\n"; |
| 529 | + OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n"; |
| 530 | + OS << " auto S = 0U;\n"; |
| 531 | + OS << " for (auto i = 0U; i < LogicalOpIdx; ++i)\n"; |
| 532 | + OS << " S += getLogicalOperandSize(Opcode, i);\n"; |
| 533 | + OS << " return S;\n"; |
| 534 | + OS << "}\n"; |
| 535 | + |
| 536 | + OS << "} // end namespace " << Namespace << "\n"; |
| 537 | + OS << "} // end namespace llvm\n"; |
| 538 | + OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n"; |
| 539 | +} |
| 540 | + |
| 541 | +void InstrInfoEmitter::emitLogicalOperandTypeMappings( |
| 542 | + raw_ostream &OS, StringRef Namespace, |
| 543 | + ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
| 544 | + std::map<std::vector<std::string>, unsigned> LogicalOpTypeMap; |
| 545 | + |
| 546 | + std::map<unsigned, std::vector<std::string>> InstMap; |
| 547 | + |
| 548 | + size_t OpTypeListSize = 0U; |
| 549 | + std::vector<std::string> LogicalOpTypeList; |
| 550 | + for (const auto *Inst : NumberedInstructions) { |
| 551 | + if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings")) |
| 552 | + continue; |
| 553 | + |
| 554 | + LogicalOpTypeList.clear(); |
| 555 | + for (const auto &Op : Inst->Operands) { |
| 556 | + auto *OpR = Op.Rec; |
| 557 | + if ((OpR->isSubClassOf("Operand") || |
| 558 | + OpR->isSubClassOf("RegisterOperand") || |
| 559 | + OpR->isSubClassOf("RegisterClass")) && |
| 560 | + !OpR->isAnonymous()) { |
| 561 | + LogicalOpTypeList.push_back( |
| 562 | + (Namespace + "::OpTypes::" + Op.Rec->getName()).str()); |
| 563 | + } else { |
| 564 | + LogicalOpTypeList.push_back("-1"); |
| 565 | + } |
| 566 | + } |
| 567 | + OpTypeListSize = std::max(LogicalOpTypeList.size(), OpTypeListSize); |
| 568 | + |
| 569 | + auto I = |
| 570 | + LogicalOpTypeMap.insert({LogicalOpTypeList, LogicalOpTypeMap.size()}) |
| 571 | + .first; |
| 572 | + InstMap[I->second].push_back( |
| 573 | + (Namespace + "::" + Inst->TheDef->getName()).str()); |
| 574 | + } |
| 575 | + |
| 576 | + OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n"; |
| 577 | + OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n"; |
| 578 | + OS << "namespace llvm {\n"; |
| 579 | + OS << "namespace " << Namespace << " {\n"; |
| 580 | + OS << "LLVM_READONLY static int\n"; |
| 581 | + OS << "getLogicalOperandType(uint16_t Opcode, uint16_t LogicalOpIdx) {\n"; |
| 582 | + if (!InstMap.empty()) { |
| 583 | + std::vector<const std::vector<std::string> *> LogicalOpTypeList( |
| 584 | + LogicalOpTypeMap.size()); |
| 585 | + for (auto &P : LogicalOpTypeMap) { |
| 586 | + LogicalOpTypeList[P.second] = &P.first; |
| 587 | + } |
| 588 | + OS << " static const int TypeMap[][" << OpTypeListSize << "] = {\n"; |
| 589 | + for (int r = 0, rs = LogicalOpTypeList.size(); r < rs; ++r) { |
| 590 | + const auto &Row = *LogicalOpTypeList[r]; |
| 591 | + OS << " {"; |
| 592 | + int i, s = Row.size(); |
| 593 | + for (i = 0; i < s; ++i) { |
| 594 | + if (i > 0) |
| 595 | + OS << ", "; |
| 596 | + OS << Row[i]; |
| 597 | + } |
| 598 | + for (; i < static_cast<int>(OpTypeListSize); ++i) { |
| 599 | + if (i > 0) |
| 600 | + OS << ", "; |
| 601 | + OS << "-1"; |
| 602 | + } |
| 603 | + OS << "}"; |
| 604 | + if (r != rs - 1) |
| 605 | + OS << ","; |
| 606 | + OS << "\n"; |
| 607 | + } |
| 608 | + OS << " };\n"; |
| 609 | + |
| 610 | + OS << " switch (Opcode) {\n"; |
| 611 | + OS << " default: return -1;\n"; |
| 612 | + for (auto &P : InstMap) { |
| 613 | + auto OpMapIdx = P.first; |
| 614 | + const auto &Insts = P.second; |
| 615 | + for (const auto &Inst : Insts) { |
| 616 | + OS << " case " << Inst << ":\n"; |
| 617 | + } |
| 618 | + OS << " return TypeMap[" << OpMapIdx << "][LogicalOpIdx];\n"; |
| 619 | + } |
| 620 | + OS << " }\n"; |
| 621 | + } else { |
| 622 | + OS << " return -1;\n"; |
| 623 | + } |
| 624 | + OS << "}\n"; |
| 625 | + OS << "} // end namespace " << Namespace << "\n"; |
| 626 | + OS << "} // end namespace llvm\n"; |
| 627 | + OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n\n"; |
| 628 | +} |
| 629 | + |
445 | 630 | void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
|
446 | 631 | StringRef TargetName) {
|
447 | 632 | RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");
|
@@ -726,6 +911,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
726 | 911 | Records.startTimer("Emit operand type mappings");
|
727 | 912 | emitOperandTypeMappings(OS, Target, NumberedInstructions);
|
728 | 913 |
|
| 914 | + Records.startTimer("Emit logical operand size mappings"); |
| 915 | + emitLogicalOperandSizeMappings(OS, TargetName, NumberedInstructions); |
| 916 | + |
| 917 | + Records.startTimer("Emit logical operand type mappings"); |
| 918 | + emitLogicalOperandTypeMappings(OS, TargetName, NumberedInstructions); |
| 919 | + |
729 | 920 | Records.startTimer("Emit helper methods");
|
730 | 921 | emitMCIIHelperMethods(OS, TargetName);
|
731 | 922 | }
|
|
0 commit comments