10b57cec5SDimitry Andric //===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This tablegen backend is responsible for emitting a description of a target 100b57cec5SDimitry Andric // register file for a code generator. It uses instances of the Register, 110b57cec5SDimitry Andric // RegisterAliases, and RegisterClass classes to gather this information. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 15*0fca6ea1SDimitry Andric #include "Basic/SequenceToOffsetTable.h" 16*0fca6ea1SDimitry Andric #include "Common/CodeGenHwModes.h" 17*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h" 18*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 19*0fca6ea1SDimitry Andric #include "Common/InfoByHwMode.h" 20*0fca6ea1SDimitry Andric #include "Common/Types.h" 210b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 220b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 240b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SparseBitVector.h" 270b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 28*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h" 290b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 300b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 310b57cec5SDimitry Andric #include "llvm/Support/Format.h" 320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 330b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 340b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 350b57cec5SDimitry Andric #include "llvm/TableGen/SetTheory.h" 360b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 370b57cec5SDimitry Andric #include <algorithm> 380b57cec5SDimitry Andric #include <cassert> 390b57cec5SDimitry Andric #include <cstddef> 400b57cec5SDimitry Andric #include <cstdint> 410b57cec5SDimitry Andric #include <deque> 420b57cec5SDimitry Andric #include <iterator> 430b57cec5SDimitry Andric #include <set> 440b57cec5SDimitry Andric #include <string> 450b57cec5SDimitry Andric #include <vector> 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric using namespace llvm; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric cl::OptionCategory RegisterInfoCat("Options for -gen-register-info"); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric static cl::opt<bool> 520b57cec5SDimitry Andric RegisterInfoDebug("register-info-debug", cl::init(false), 530b57cec5SDimitry Andric cl::desc("Dump register information to help debugging"), 540b57cec5SDimitry Andric cl::cat(RegisterInfoCat)); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric namespace { 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric class RegisterInfoEmitter { 590b57cec5SDimitry Andric CodeGenTarget Target; 600b57cec5SDimitry Andric RecordKeeper &Records; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric RegisterInfoEmitter(RecordKeeper &R) : Target(R), Records(R) { 640b57cec5SDimitry Andric CodeGenRegBank &RegBank = Target.getRegBank(); 650b57cec5SDimitry Andric RegBank.computeDerivedInfo(); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // runEnums - Print out enum values for all of the registers. 690b57cec5SDimitry Andric void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // runMCDesc - Print out MC register descriptions. 720b57cec5SDimitry Andric void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // runTargetHeader - Emit a header fragment for the register info emitter. 750b57cec5SDimitry Andric void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, 760b57cec5SDimitry Andric CodeGenRegBank &Bank); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // runTargetDesc - Output the target register and register file descriptions. 790b57cec5SDimitry Andric void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, 800b57cec5SDimitry Andric CodeGenRegBank &Bank); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // run - Output the register file description. 830b57cec5SDimitry Andric void run(raw_ostream &o); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric void debugDump(raw_ostream &OS); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric private: 880b57cec5SDimitry Andric void EmitRegMapping(raw_ostream &o, const std::deque<CodeGenRegister> &Regs, 890b57cec5SDimitry Andric bool isCtor); 900b57cec5SDimitry Andric void EmitRegMappingTables(raw_ostream &o, 910b57cec5SDimitry Andric const std::deque<CodeGenRegister> &Regs, 920b57cec5SDimitry Andric bool isCtor); 930b57cec5SDimitry Andric void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, 940b57cec5SDimitry Andric const std::string &ClassName); 950b57cec5SDimitry Andric void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, 960b57cec5SDimitry Andric const std::string &ClassName); 970b57cec5SDimitry Andric void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, 980b57cec5SDimitry Andric const std::string &ClassName); 990b57cec5SDimitry Andric }; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric } // end anonymous namespace 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // runEnums - Print out enum values for all of the registers. 104*0fca6ea1SDimitry Andric void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, 105*0fca6ea1SDimitry Andric CodeGenRegBank &Bank) { 1060b57cec5SDimitry Andric const auto &Registers = Bank.getRegisters(); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Register enums are stored as uint16_t in the tables. Make sure we'll fit. 1090b57cec5SDimitry Andric assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace"); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric emitSourceFileHeader("Target Register Enum Values", OS); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric OS << "\n#ifdef GET_REGINFO_ENUM\n"; 1160b57cec5SDimitry Andric OS << "#undef GET_REGINFO_ENUM\n\n"; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric OS << "class MCRegisterClass;\n" 1210b57cec5SDimitry Andric << "extern const MCRegisterClass " << Target.getName() 1220b57cec5SDimitry Andric << "MCRegisterClasses[];\n\n"; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric if (!Namespace.empty()) 1250b57cec5SDimitry Andric OS << "namespace " << Namespace << " {\n"; 1260b57cec5SDimitry Andric OS << "enum {\n NoRegister,\n"; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric for (const auto &Reg : Registers) 1290b57cec5SDimitry Andric OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; 1300b57cec5SDimitry Andric assert(Registers.size() == Registers.back().EnumValue && 1310b57cec5SDimitry Andric "Register enum value mismatch!"); 132e8d8bef9SDimitry Andric OS << " NUM_TARGET_REGS // " << Registers.size() + 1 << "\n"; 1330b57cec5SDimitry Andric OS << "};\n"; 1340b57cec5SDimitry Andric if (!Namespace.empty()) 1350b57cec5SDimitry Andric OS << "} // end namespace " << Namespace << "\n"; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric const auto &RegisterClasses = Bank.getRegClasses(); 1380b57cec5SDimitry Andric if (!RegisterClasses.empty()) { 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // RegisterClass enums are stored as uint16_t in the tables. 1410b57cec5SDimitry Andric assert(RegisterClasses.size() <= 0xffff && 1420b57cec5SDimitry Andric "Too many register classes to fit in tables"); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric OS << "\n// Register classes\n\n"; 1450b57cec5SDimitry Andric if (!Namespace.empty()) 1460b57cec5SDimitry Andric OS << "namespace " << Namespace << " {\n"; 1470b57cec5SDimitry Andric OS << "enum {\n"; 1480b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) 1495f757f3fSDimitry Andric OS << " " << RC.getIdName() << " = " << RC.EnumValue << ",\n"; 1500b57cec5SDimitry Andric OS << "\n};\n"; 1510b57cec5SDimitry Andric if (!Namespace.empty()) 1520b57cec5SDimitry Andric OS << "} // end namespace " << Namespace << "\n\n"; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 155*0fca6ea1SDimitry Andric const std::vector<Record *> &RegAltNameIndices = 156*0fca6ea1SDimitry Andric Target.getRegAltNameIndices(); 1570b57cec5SDimitry Andric // If the only definition is the default NoRegAltName, we don't need to 1580b57cec5SDimitry Andric // emit anything. 1590b57cec5SDimitry Andric if (RegAltNameIndices.size() > 1) { 1600b57cec5SDimitry Andric OS << "\n// Register alternate name indices\n\n"; 1610b57cec5SDimitry Andric if (!Namespace.empty()) 1620b57cec5SDimitry Andric OS << "namespace " << Namespace << " {\n"; 1630b57cec5SDimitry Andric OS << "enum {\n"; 1640b57cec5SDimitry Andric for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) 1650b57cec5SDimitry Andric OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; 1660b57cec5SDimitry Andric OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; 1670b57cec5SDimitry Andric OS << "};\n"; 1680b57cec5SDimitry Andric if (!Namespace.empty()) 1690b57cec5SDimitry Andric OS << "} // end namespace " << Namespace << "\n\n"; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric auto &SubRegIndices = Bank.getSubRegIndices(); 1730b57cec5SDimitry Andric if (!SubRegIndices.empty()) { 1740b57cec5SDimitry Andric OS << "\n// Subregister indices\n\n"; 1750b57cec5SDimitry Andric std::string Namespace = SubRegIndices.front().getNamespace(); 1760b57cec5SDimitry Andric if (!Namespace.empty()) 1770b57cec5SDimitry Andric OS << "namespace " << Namespace << " {\n"; 1785ffd83dbSDimitry Andric OS << "enum : uint16_t {\n NoSubRegister,\n"; 1790b57cec5SDimitry Andric unsigned i = 0; 1800b57cec5SDimitry Andric for (const auto &Idx : SubRegIndices) 1810b57cec5SDimitry Andric OS << " " << Idx.getName() << ",\t// " << ++i << "\n"; 1820b57cec5SDimitry Andric OS << " NUM_TARGET_SUBREGS\n};\n"; 1830b57cec5SDimitry Andric if (!Namespace.empty()) 1840b57cec5SDimitry Andric OS << "} // end namespace " << Namespace << "\n\n"; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1875ffd83dbSDimitry Andric OS << "// Register pressure sets enum.\n"; 1885ffd83dbSDimitry Andric if (!Namespace.empty()) 1895ffd83dbSDimitry Andric OS << "namespace " << Namespace << " {\n"; 1905ffd83dbSDimitry Andric OS << "enum RegisterPressureSets {\n"; 1915ffd83dbSDimitry Andric unsigned NumSets = Bank.getNumRegPressureSets(); 1925ffd83dbSDimitry Andric for (unsigned i = 0; i < NumSets; ++i) { 1935ffd83dbSDimitry Andric const RegUnitSet &RegUnits = Bank.getRegSetAt(i); 1945ffd83dbSDimitry Andric OS << " " << RegUnits.Name << " = " << i << ",\n"; 1955ffd83dbSDimitry Andric } 1965ffd83dbSDimitry Andric OS << "};\n"; 1975ffd83dbSDimitry Andric if (!Namespace.empty()) 1985ffd83dbSDimitry Andric OS << "} // end namespace " << Namespace << '\n'; 1995ffd83dbSDimitry Andric OS << '\n'; 2005ffd83dbSDimitry Andric 2010b57cec5SDimitry Andric OS << "} // end namespace llvm\n\n"; 2020b57cec5SDimitry Andric OS << "#endif // GET_REGINFO_ENUM\n\n"; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 205*0fca6ea1SDimitry Andric static void printInt(raw_ostream &OS, int Val) { OS << Val; } 2060b57cec5SDimitry Andric 207*0fca6ea1SDimitry Andric void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS, 208*0fca6ea1SDimitry Andric const CodeGenRegBank &RegBank, 2090b57cec5SDimitry Andric const std::string &ClassName) { 2100b57cec5SDimitry Andric unsigned NumRCs = RegBank.getRegClasses().size(); 2110b57cec5SDimitry Andric unsigned NumSets = RegBank.getNumRegPressureSets(); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric OS << "/// Get the weight in units of pressure for this register class.\n" 2140b57cec5SDimitry Andric << "const RegClassWeight &" << ClassName << "::\n" 2150b57cec5SDimitry Andric << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" 2160b57cec5SDimitry Andric << " static const RegClassWeight RCWeightTable[] = {\n"; 2170b57cec5SDimitry Andric for (const auto &RC : RegBank.getRegClasses()) { 2180b57cec5SDimitry Andric const CodeGenRegister::Vec &Regs = RC.getMembers(); 2195ffd83dbSDimitry Andric OS << " {" << RC.getWeight(RegBank) << ", "; 2200b57cec5SDimitry Andric if (Regs.empty() || RC.Artificial) 2215ffd83dbSDimitry Andric OS << '0'; 2220b57cec5SDimitry Andric else { 2230b57cec5SDimitry Andric std::vector<unsigned> RegUnits; 2240b57cec5SDimitry Andric RC.buildRegUnitSet(RegBank, RegUnits); 2255ffd83dbSDimitry Andric OS << RegBank.getRegUnitSetWeight(RegUnits); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric OS << "}, \t// " << RC.getName() << "\n"; 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric OS << " };\n" 2300b57cec5SDimitry Andric << " return RCWeightTable[RC->getID()];\n" 2310b57cec5SDimitry Andric << "}\n\n"; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // Reasonable targets (not ARMv7) have unit weight for all units, so don't 2340b57cec5SDimitry Andric // bother generating a table. 2350b57cec5SDimitry Andric bool RegUnitsHaveUnitWeight = true; 2360b57cec5SDimitry Andric for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); 2370b57cec5SDimitry Andric UnitIdx < UnitEnd; ++UnitIdx) { 2380b57cec5SDimitry Andric if (RegBank.getRegUnit(UnitIdx).Weight > 1) 2390b57cec5SDimitry Andric RegUnitsHaveUnitWeight = false; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric OS << "/// Get the weight in units of pressure for this register unit.\n" 2420b57cec5SDimitry Andric << "unsigned " << ClassName << "::\n" 2430b57cec5SDimitry Andric << "getRegUnitWeight(unsigned RegUnit) const {\n" 2440b57cec5SDimitry Andric << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() 2450b57cec5SDimitry Andric << " && \"invalid register unit\");\n"; 2460b57cec5SDimitry Andric if (!RegUnitsHaveUnitWeight) { 2470b57cec5SDimitry Andric OS << " static const uint8_t RUWeightTable[] = {\n "; 2480b57cec5SDimitry Andric for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); 2490b57cec5SDimitry Andric UnitIdx < UnitEnd; ++UnitIdx) { 2500b57cec5SDimitry Andric const RegUnit &RU = RegBank.getRegUnit(UnitIdx); 2510b57cec5SDimitry Andric assert(RU.Weight < 256 && "RegUnit too heavy"); 2520b57cec5SDimitry Andric OS << RU.Weight << ", "; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric OS << "};\n" 2550b57cec5SDimitry Andric << " return RUWeightTable[RegUnit];\n"; 256*0fca6ea1SDimitry Andric } else { 2570b57cec5SDimitry Andric OS << " // All register units have unit weight.\n" 2580b57cec5SDimitry Andric << " return 1;\n"; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric OS << "}\n\n"; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric OS << "\n" 2630b57cec5SDimitry Andric << "// Get the number of dimensions of register pressure.\n" 2640b57cec5SDimitry Andric << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" 2650b57cec5SDimitry Andric << " return " << NumSets << ";\n}\n\n"; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric OS << "// Get the name of this register unit pressure set.\n" 2680b57cec5SDimitry Andric << "const char *" << ClassName << "::\n" 2690b57cec5SDimitry Andric << "getRegPressureSetName(unsigned Idx) const {\n" 27081ad6265SDimitry Andric << " static const char *PressureNameTable[] = {\n"; 2710b57cec5SDimitry Andric unsigned MaxRegUnitWeight = 0; 2720b57cec5SDimitry Andric for (unsigned i = 0; i < NumSets; ++i) { 2730b57cec5SDimitry Andric const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); 2740b57cec5SDimitry Andric MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); 2750b57cec5SDimitry Andric OS << " \"" << RegUnits.Name << "\",\n"; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric OS << " };\n" 2780b57cec5SDimitry Andric << " return PressureNameTable[Idx];\n" 2790b57cec5SDimitry Andric << "}\n\n"; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric OS << "// Get the register unit pressure limit for this dimension.\n" 2820b57cec5SDimitry Andric << "// This limit must be adjusted dynamically for reserved registers.\n" 2830b57cec5SDimitry Andric << "unsigned " << ClassName << "::\n" 2840b57cec5SDimitry Andric << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const " 2850b57cec5SDimitry Andric "{\n" 2860b57cec5SDimitry Andric << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32) 2870b57cec5SDimitry Andric << " PressureLimitTable[] = {\n"; 2880b57cec5SDimitry Andric for (unsigned i = 0; i < NumSets; ++i) { 2890b57cec5SDimitry Andric const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); 290*0fca6ea1SDimitry Andric OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name 291*0fca6ea1SDimitry Andric << "\n"; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric OS << " };\n" 2940b57cec5SDimitry Andric << " return PressureLimitTable[Idx];\n" 2950b57cec5SDimitry Andric << "}\n\n"; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric SequenceToOffsetTable<std::vector<int>> PSetsSeqs; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // This table may be larger than NumRCs if some register units needed a list 3000b57cec5SDimitry Andric // of unit sets that did not correspond to a register class. 3010b57cec5SDimitry Andric unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); 3020b57cec5SDimitry Andric std::vector<std::vector<int>> PSets(NumRCUnitSets); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { 3050b57cec5SDimitry Andric ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); 3060b57cec5SDimitry Andric PSets[i].reserve(PSetIDs.size()); 307fe6060f1SDimitry Andric for (unsigned PSetID : PSetIDs) { 308fe6060f1SDimitry Andric PSets[i].push_back(RegBank.getRegPressureSet(PSetID).Order); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric llvm::sort(PSets[i]); 3110b57cec5SDimitry Andric PSetsSeqs.add(PSets[i]); 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric PSetsSeqs.layout(); 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric OS << "/// Table of pressure sets per register class or unit.\n" 3170b57cec5SDimitry Andric << "static const int RCSetsTable[] = {\n"; 3180b57cec5SDimitry Andric PSetsSeqs.emit(OS, printInt, "-1"); 3190b57cec5SDimitry Andric OS << "};\n\n"; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric OS << "/// Get the dimensions of register pressure impacted by this " 3220b57cec5SDimitry Andric << "register class.\n" 3230b57cec5SDimitry Andric << "/// Returns a -1 terminated array of pressure set IDs\n" 3240b57cec5SDimitry Andric << "const int *" << ClassName << "::\n" 3250b57cec5SDimitry Andric << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; 3260b57cec5SDimitry Andric OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) 3270b57cec5SDimitry Andric << " RCSetStartTable[] = {\n "; 3280b57cec5SDimitry Andric for (unsigned i = 0, e = NumRCs; i != e; ++i) { 3290b57cec5SDimitry Andric OS << PSetsSeqs.get(PSets[i]) << ","; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric OS << "};\n" 3320b57cec5SDimitry Andric << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" 3330b57cec5SDimitry Andric << "}\n\n"; 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric OS << "/// Get the dimensions of register pressure impacted by this " 3360b57cec5SDimitry Andric << "register unit.\n" 3370b57cec5SDimitry Andric << "/// Returns a -1 terminated array of pressure set IDs\n" 3380b57cec5SDimitry Andric << "const int *" << ClassName << "::\n" 3390b57cec5SDimitry Andric << "getRegUnitPressureSets(unsigned RegUnit) const {\n" 3400b57cec5SDimitry Andric << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() 3410b57cec5SDimitry Andric << " && \"invalid register unit\");\n"; 3420b57cec5SDimitry Andric OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32) 3430b57cec5SDimitry Andric << " RUSetStartTable[] = {\n "; 3440b57cec5SDimitry Andric for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); 3450b57cec5SDimitry Andric UnitIdx < UnitEnd; ++UnitIdx) { 3460b57cec5SDimitry Andric OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) 3470b57cec5SDimitry Andric << ","; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric OS << "};\n" 3500b57cec5SDimitry Andric << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" 3510b57cec5SDimitry Andric << "}\n\n"; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric using DwarfRegNumsMapPair = std::pair<Record *, std::vector<int64_t>>; 3550b57cec5SDimitry Andric using DwarfRegNumsVecTy = std::vector<DwarfRegNumsMapPair>; 3560b57cec5SDimitry Andric 357e8d8bef9SDimitry Andric static void finalizeDwarfRegNumsKeys(DwarfRegNumsVecTy &DwarfRegNums) { 3580b57cec5SDimitry Andric // Sort and unique to get a map-like vector. We want the last assignment to 3590b57cec5SDimitry Andric // match previous behaviour. 360e8d8bef9SDimitry Andric llvm::stable_sort(DwarfRegNums, on_first<LessRecordRegister>()); 3610b57cec5SDimitry Andric // Warn about duplicate assignments. 3620b57cec5SDimitry Andric const Record *LastSeenReg = nullptr; 3630b57cec5SDimitry Andric for (const auto &X : DwarfRegNums) { 3640b57cec5SDimitry Andric const auto &Reg = X.first; 3650b57cec5SDimitry Andric // The only way LessRecordRegister can return equal is if they're the same 3660b57cec5SDimitry Andric // string. Use simple equality instead. 3670b57cec5SDimitry Andric if (LastSeenReg && Reg->getName() == LastSeenReg->getName()) 3680b57cec5SDimitry Andric PrintWarning(Reg->getLoc(), Twine("DWARF numbers for register ") + 3690b57cec5SDimitry Andric getQualifiedName(Reg) + 3700b57cec5SDimitry Andric "specified multiple times"); 3710b57cec5SDimitry Andric LastSeenReg = Reg; 3720b57cec5SDimitry Andric } 373*0fca6ea1SDimitry Andric auto Last = llvm::unique(DwarfRegNums, [](const DwarfRegNumsMapPair &A, 374*0fca6ea1SDimitry Andric const DwarfRegNumsMapPair &B) { 3750b57cec5SDimitry Andric return A.first->getName() == B.first->getName(); 3760b57cec5SDimitry Andric }); 3770b57cec5SDimitry Andric DwarfRegNums.erase(Last, DwarfRegNums.end()); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric void RegisterInfoEmitter::EmitRegMappingTables( 3810b57cec5SDimitry Andric raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) { 3820b57cec5SDimitry Andric // Collect all information about dwarf register numbers 3830b57cec5SDimitry Andric DwarfRegNumsVecTy DwarfRegNums; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // First, just pull all provided information to the map 3860b57cec5SDimitry Andric unsigned maxLength = 0; 3870b57cec5SDimitry Andric for (auto &RE : Regs) { 3880b57cec5SDimitry Andric Record *Reg = RE.TheDef; 3890b57cec5SDimitry Andric std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); 3900b57cec5SDimitry Andric maxLength = std::max((size_t)maxLength, RegNums.size()); 3910b57cec5SDimitry Andric DwarfRegNums.emplace_back(Reg, std::move(RegNums)); 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric finalizeDwarfRegNumsKeys(DwarfRegNums); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric if (!maxLength) 3960b57cec5SDimitry Andric return; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric // Now we know maximal length of number list. Append -1's, where needed 399fe6060f1SDimitry Andric for (auto &DwarfRegNum : DwarfRegNums) 400fe6060f1SDimitry Andric for (unsigned I = DwarfRegNum.second.size(), E = maxLength; I != E; ++I) 401fe6060f1SDimitry Andric DwarfRegNum.second.push_back(-1); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace"); 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric // Emit reverse information about the dwarf register numbers. 4080b57cec5SDimitry Andric for (unsigned j = 0; j < 2; ++j) { 409fe6060f1SDimitry Andric for (unsigned I = 0, E = maxLength; I != E; ++I) { 4100b57cec5SDimitry Andric OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; 4110b57cec5SDimitry Andric OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); 412fe6060f1SDimitry Andric OS << I << "Dwarf2L[]"; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric if (!isCtor) { 4150b57cec5SDimitry Andric OS << " = {\n"; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // Store the mapping sorted by the LLVM reg num so lookup can be done 4180b57cec5SDimitry Andric // with a binary search. 4190b57cec5SDimitry Andric std::map<uint64_t, Record *> Dwarf2LMap; 420fe6060f1SDimitry Andric for (auto &DwarfRegNum : DwarfRegNums) { 421fe6060f1SDimitry Andric int DwarfRegNo = DwarfRegNum.second[I]; 4220b57cec5SDimitry Andric if (DwarfRegNo < 0) 4230b57cec5SDimitry Andric continue; 424fe6060f1SDimitry Andric Dwarf2LMap[DwarfRegNo] = DwarfRegNum.first; 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 427fe6060f1SDimitry Andric for (auto &I : Dwarf2LMap) 428fe6060f1SDimitry Andric OS << " { " << I.first << "U, " << getQualifiedName(I.second) 4290b57cec5SDimitry Andric << " },\n"; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric OS << "};\n"; 4320b57cec5SDimitry Andric } else { 4330b57cec5SDimitry Andric OS << ";\n"; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric // We have to store the size in a const global, it's used in multiple 4370b57cec5SDimitry Andric // places. 4380b57cec5SDimitry Andric OS << "extern const unsigned " << Namespace 439fe6060f1SDimitry Andric << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2LSize"; 4400b57cec5SDimitry Andric if (!isCtor) 441bdd1243dSDimitry Andric OS << " = std::size(" << Namespace 442fe6060f1SDimitry Andric << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2L);\n\n"; 4430b57cec5SDimitry Andric else 4440b57cec5SDimitry Andric OS << ";\n\n"; 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric for (auto &RE : Regs) { 4490b57cec5SDimitry Andric Record *Reg = RE.TheDef; 4500b57cec5SDimitry Andric const RecordVal *V = Reg->getValue("DwarfAlias"); 4510b57cec5SDimitry Andric if (!V || !V->getValue()) 4520b57cec5SDimitry Andric continue; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric DefInit *DI = cast<DefInit>(V->getValue()); 4550b57cec5SDimitry Andric Record *Alias = DI->getDef(); 456e8d8bef9SDimitry Andric const auto &AliasIter = llvm::lower_bound( 457e8d8bef9SDimitry Andric DwarfRegNums, Alias, [](const DwarfRegNumsMapPair &A, const Record *B) { 4580b57cec5SDimitry Andric return LessRecordRegister()(A.first, B); 4590b57cec5SDimitry Andric }); 4600b57cec5SDimitry Andric assert(AliasIter != DwarfRegNums.end() && AliasIter->first == Alias && 4610b57cec5SDimitry Andric "Expected Alias to be present in map"); 462e8d8bef9SDimitry Andric const auto &RegIter = llvm::lower_bound( 463e8d8bef9SDimitry Andric DwarfRegNums, Reg, [](const DwarfRegNumsMapPair &A, const Record *B) { 4640b57cec5SDimitry Andric return LessRecordRegister()(A.first, B); 4650b57cec5SDimitry Andric }); 4660b57cec5SDimitry Andric assert(RegIter != DwarfRegNums.end() && RegIter->first == Reg && 4670b57cec5SDimitry Andric "Expected Reg to be present in map"); 4680b57cec5SDimitry Andric RegIter->second = AliasIter->second; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric // Emit information about the dwarf register numbers. 4720b57cec5SDimitry Andric for (unsigned j = 0; j < 2; ++j) { 4730b57cec5SDimitry Andric for (unsigned i = 0, e = maxLength; i != e; ++i) { 4740b57cec5SDimitry Andric OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; 4750b57cec5SDimitry Andric OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); 4760b57cec5SDimitry Andric OS << i << "L2Dwarf[]"; 4770b57cec5SDimitry Andric if (!isCtor) { 4780b57cec5SDimitry Andric OS << " = {\n"; 4790b57cec5SDimitry Andric // Store the mapping sorted by the Dwarf reg num so lookup can be done 4800b57cec5SDimitry Andric // with a binary search. 481fe6060f1SDimitry Andric for (auto &DwarfRegNum : DwarfRegNums) { 482fe6060f1SDimitry Andric int RegNo = DwarfRegNum.second[i]; 4830b57cec5SDimitry Andric if (RegNo == -1) // -1 is the default value, don't emit a mapping. 4840b57cec5SDimitry Andric continue; 4850b57cec5SDimitry Andric 486fe6060f1SDimitry Andric OS << " { " << getQualifiedName(DwarfRegNum.first) << ", " << RegNo 4870b57cec5SDimitry Andric << "U },\n"; 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric OS << "};\n"; 4900b57cec5SDimitry Andric } else { 4910b57cec5SDimitry Andric OS << ";\n"; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric // We have to store the size in a const global, it's used in multiple 4950b57cec5SDimitry Andric // places. 4960b57cec5SDimitry Andric OS << "extern const unsigned " << Namespace 4970b57cec5SDimitry Andric << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; 4980b57cec5SDimitry Andric if (!isCtor) 499bdd1243dSDimitry Andric OS << " = std::size(" << Namespace 5000b57cec5SDimitry Andric << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; 5010b57cec5SDimitry Andric else 5020b57cec5SDimitry Andric OS << ";\n\n"; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric void RegisterInfoEmitter::EmitRegMapping( 5080b57cec5SDimitry Andric raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) { 5090b57cec5SDimitry Andric // Emit the initializer so the tables from EmitRegMappingTables get wired up 5100b57cec5SDimitry Andric // to the MCRegisterInfo object. 5110b57cec5SDimitry Andric unsigned maxLength = 0; 5120b57cec5SDimitry Andric for (auto &RE : Regs) { 5130b57cec5SDimitry Andric Record *Reg = RE.TheDef; 5140b57cec5SDimitry Andric maxLength = std::max((size_t)maxLength, 5150b57cec5SDimitry Andric Reg->getValueAsListOfInts("DwarfNumbers").size()); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (!maxLength) 5190b57cec5SDimitry Andric return; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace"); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric // Emit reverse information about the dwarf register numbers. 5240b57cec5SDimitry Andric for (unsigned j = 0; j < 2; ++j) { 5250b57cec5SDimitry Andric OS << " switch ("; 5260b57cec5SDimitry Andric if (j == 0) 5270b57cec5SDimitry Andric OS << "DwarfFlavour"; 5280b57cec5SDimitry Andric else 5290b57cec5SDimitry Andric OS << "EHFlavour"; 5300b57cec5SDimitry Andric OS << ") {\n" 5310b57cec5SDimitry Andric << " default:\n" 5320b57cec5SDimitry Andric << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric for (unsigned i = 0, e = maxLength; i != e; ++i) { 5350b57cec5SDimitry Andric OS << " case " << i << ":\n"; 5360b57cec5SDimitry Andric OS << " "; 5370b57cec5SDimitry Andric if (!isCtor) 5380b57cec5SDimitry Andric OS << "RI->"; 5390b57cec5SDimitry Andric std::string Tmp; 540*0fca6ea1SDimitry Andric raw_string_ostream(Tmp) 541*0fca6ea1SDimitry Andric << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i 5420b57cec5SDimitry Andric << "Dwarf2L"; 5430b57cec5SDimitry Andric OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; 5440b57cec5SDimitry Andric if (j == 0) 5450b57cec5SDimitry Andric OS << "false"; 5460b57cec5SDimitry Andric else 5470b57cec5SDimitry Andric OS << "true"; 5480b57cec5SDimitry Andric OS << ");\n"; 5490b57cec5SDimitry Andric OS << " break;\n"; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric OS << " }\n"; 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric // Emit information about the dwarf register numbers. 5550b57cec5SDimitry Andric for (unsigned j = 0; j < 2; ++j) { 5560b57cec5SDimitry Andric OS << " switch ("; 5570b57cec5SDimitry Andric if (j == 0) 5580b57cec5SDimitry Andric OS << "DwarfFlavour"; 5590b57cec5SDimitry Andric else 5600b57cec5SDimitry Andric OS << "EHFlavour"; 5610b57cec5SDimitry Andric OS << ") {\n" 5620b57cec5SDimitry Andric << " default:\n" 5630b57cec5SDimitry Andric << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric for (unsigned i = 0, e = maxLength; i != e; ++i) { 5660b57cec5SDimitry Andric OS << " case " << i << ":\n"; 5670b57cec5SDimitry Andric OS << " "; 5680b57cec5SDimitry Andric if (!isCtor) 5690b57cec5SDimitry Andric OS << "RI->"; 5700b57cec5SDimitry Andric std::string Tmp; 571*0fca6ea1SDimitry Andric raw_string_ostream(Tmp) 572*0fca6ea1SDimitry Andric << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i 5730b57cec5SDimitry Andric << "L2Dwarf"; 5740b57cec5SDimitry Andric OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; 5750b57cec5SDimitry Andric if (j == 0) 5760b57cec5SDimitry Andric OS << "false"; 5770b57cec5SDimitry Andric else 5780b57cec5SDimitry Andric OS << "true"; 5790b57cec5SDimitry Andric OS << ");\n"; 5800b57cec5SDimitry Andric OS << " break;\n"; 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric OS << " }\n"; 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric // Print a BitVector as a sequence of hex numbers using a little-endian mapping. 5870b57cec5SDimitry Andric // Width is the number of bits per hex number. 588*0fca6ea1SDimitry Andric static void printBitVectorAsHex(raw_ostream &OS, const BitVector &Bits, 5890b57cec5SDimitry Andric unsigned Width) { 5900b57cec5SDimitry Andric assert(Width <= 32 && "Width too large"); 5910b57cec5SDimitry Andric unsigned Digits = (Width + 3) / 4; 5920b57cec5SDimitry Andric for (unsigned i = 0, e = Bits.size(); i < e; i += Width) { 5930b57cec5SDimitry Andric unsigned Value = 0; 5940b57cec5SDimitry Andric for (unsigned j = 0; j != Width && i + j != e; ++j) 5950b57cec5SDimitry Andric Value |= Bits.test(i + j) << j; 5960b57cec5SDimitry Andric OS << format("0x%0*x, ", Digits, Value); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // Helper to emit a set of bits into a constant byte array. 6010b57cec5SDimitry Andric class BitVectorEmitter { 6020b57cec5SDimitry Andric BitVector Values; 603*0fca6ea1SDimitry Andric 6040b57cec5SDimitry Andric public: 6050b57cec5SDimitry Andric void add(unsigned v) { 6060b57cec5SDimitry Andric if (v >= Values.size()) 6070b57cec5SDimitry Andric Values.resize(((v / 8) + 1) * 8); // Round up to the next byte. 6080b57cec5SDimitry Andric Values[v] = true; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 611*0fca6ea1SDimitry Andric void print(raw_ostream &OS) { printBitVectorAsHex(OS, Values, 8); } 6120b57cec5SDimitry Andric }; 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { 6150b57cec5SDimitry Andric OS << getEnumName(VT); 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { 6190b57cec5SDimitry Andric OS << Idx->EnumValue; 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric // Differentially encoded register and regunit lists allow for better 6230b57cec5SDimitry Andric // compression on regular register banks. The sequence is computed from the 6240b57cec5SDimitry Andric // differential list as: 6250b57cec5SDimitry Andric // 6260b57cec5SDimitry Andric // out[0] = InitVal; 6270b57cec5SDimitry Andric // out[n+1] = out[n] + diff[n]; // n = 0, 1, ... 6280b57cec5SDimitry Andric // 6290b57cec5SDimitry Andric // The initial value depends on the specific list. The list is terminated by a 6300b57cec5SDimitry Andric // 0 differential which means we can't encode repeated elements. 6310b57cec5SDimitry Andric 63206c3fb27SDimitry Andric typedef SmallVector<int16_t, 4> DiffVec; 6330b57cec5SDimitry Andric typedef SmallVector<LaneBitmask, 4> MaskVec; 6340b57cec5SDimitry Andric 63506c3fb27SDimitry Andric // Fills V with differentials between every two consecutive elements of List. 63606c3fb27SDimitry Andric static DiffVec &diffEncode(DiffVec &V, SparseBitVector<> List) { 6370b57cec5SDimitry Andric assert(V.empty() && "Clear DiffVec before diffEncode."); 63806c3fb27SDimitry Andric SparseBitVector<>::iterator I = List.begin(), E = List.end(); 63906c3fb27SDimitry Andric unsigned Val = *I; 64006c3fb27SDimitry Andric while (++I != E) { 64106c3fb27SDimitry Andric unsigned Cur = *I; 6420b57cec5SDimitry Andric V.push_back(Cur - Val); 6430b57cec5SDimitry Andric Val = Cur; 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric return V; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric template <typename Iter> 649*0fca6ea1SDimitry Andric static DiffVec &diffEncode(DiffVec &V, unsigned InitVal, Iter Begin, Iter End) { 6500b57cec5SDimitry Andric assert(V.empty() && "Clear DiffVec before diffEncode."); 65106c3fb27SDimitry Andric unsigned Val = InitVal; 6520b57cec5SDimitry Andric for (Iter I = Begin; I != End; ++I) { 65306c3fb27SDimitry Andric unsigned Cur = (*I)->EnumValue; 6540b57cec5SDimitry Andric V.push_back(Cur - Val); 6550b57cec5SDimitry Andric Val = Cur; 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric return V; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 66006c3fb27SDimitry Andric static void printDiff16(raw_ostream &OS, int16_t Val) { OS << Val; } 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric static void printMask(raw_ostream &OS, LaneBitmask Val) { 6630b57cec5SDimitry Andric OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')'; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // Try to combine Idx's compose map into Vec if it is compatible. 6670b57cec5SDimitry Andric // Return false if it's not possible. 6680b57cec5SDimitry Andric static bool combine(const CodeGenSubRegIndex *Idx, 6690b57cec5SDimitry Andric SmallVectorImpl<CodeGenSubRegIndex *> &Vec) { 6700b57cec5SDimitry Andric const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites(); 6710b57cec5SDimitry Andric for (const auto &I : Map) { 6720b57cec5SDimitry Andric CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1]; 6730b57cec5SDimitry Andric if (Entry && Entry != I.second) 6740b57cec5SDimitry Andric return false; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // All entries are compatible. Make it so. 6780b57cec5SDimitry Andric for (const auto &I : Map) { 6790b57cec5SDimitry Andric auto *&Entry = Vec[I.first->EnumValue - 1]; 680*0fca6ea1SDimitry Andric assert((!Entry || Entry == I.second) && "Expected EnumValue to be unique"); 6810b57cec5SDimitry Andric Entry = I.second; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric return true; 6840b57cec5SDimitry Andric } 6850b57cec5SDimitry Andric 686*0fca6ea1SDimitry Andric void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, 6870b57cec5SDimitry Andric CodeGenRegBank &RegBank, 6880b57cec5SDimitry Andric const std::string &ClName) { 6890b57cec5SDimitry Andric const auto &SubRegIndices = RegBank.getSubRegIndices(); 6900b57cec5SDimitry Andric OS << "unsigned " << ClName 6910b57cec5SDimitry Andric << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Many sub-register indexes are composition-compatible, meaning that 6940b57cec5SDimitry Andric // 6950b57cec5SDimitry Andric // compose(IdxA, IdxB) == compose(IdxA', IdxB) 6960b57cec5SDimitry Andric // 6970b57cec5SDimitry Andric // for many IdxA, IdxA' pairs. Not all sub-register indexes can be composed. 6980b57cec5SDimitry Andric // The illegal entries can be use as wildcards to compress the table further. 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric // Map each Sub-register index to a compatible table row. 7010b57cec5SDimitry Andric SmallVector<unsigned, 4> RowMap; 7020b57cec5SDimitry Andric SmallVector<SmallVector<CodeGenSubRegIndex *, 4>, 4> Rows; 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric auto SubRegIndicesSize = 7050b57cec5SDimitry Andric std::distance(SubRegIndices.begin(), SubRegIndices.end()); 7060b57cec5SDimitry Andric for (const auto &Idx : SubRegIndices) { 7070b57cec5SDimitry Andric unsigned Found = ~0u; 7080b57cec5SDimitry Andric for (unsigned r = 0, re = Rows.size(); r != re; ++r) { 7090b57cec5SDimitry Andric if (combine(&Idx, Rows[r])) { 7100b57cec5SDimitry Andric Found = r; 7110b57cec5SDimitry Andric break; 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric if (Found == ~0u) { 7150b57cec5SDimitry Andric Found = Rows.size(); 7160b57cec5SDimitry Andric Rows.resize(Found + 1); 7170b57cec5SDimitry Andric Rows.back().resize(SubRegIndicesSize); 7180b57cec5SDimitry Andric combine(&Idx, Rows.back()); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric RowMap.push_back(Found); 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Output the row map if there is multiple rows. 7240b57cec5SDimitry Andric if (Rows.size() > 1) { 7250b57cec5SDimitry Andric OS << " static const " << getMinimalTypeForRange(Rows.size(), 32) 7260b57cec5SDimitry Andric << " RowMap[" << SubRegIndicesSize << "] = {\n "; 7270b57cec5SDimitry Andric for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) 7280b57cec5SDimitry Andric OS << RowMap[i] << ", "; 7290b57cec5SDimitry Andric OS << "\n };\n"; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // Output the rows. 7330b57cec5SDimitry Andric OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32) 7340b57cec5SDimitry Andric << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; 7350b57cec5SDimitry Andric for (unsigned r = 0, re = Rows.size(); r != re; ++r) { 7360b57cec5SDimitry Andric OS << " { "; 7370b57cec5SDimitry Andric for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) 7380b57cec5SDimitry Andric if (Rows[r][i]) 739480093f4SDimitry Andric OS << Rows[r][i]->getQualifiedName() << ", "; 7400b57cec5SDimitry Andric else 7410b57cec5SDimitry Andric OS << "0, "; 7420b57cec5SDimitry Andric OS << "},\n"; 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric OS << " };\n\n"; 7450b57cec5SDimitry Andric 74681ad6265SDimitry Andric OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << "); (void) IdxA;\n" 7470b57cec5SDimitry Andric << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; 7480b57cec5SDimitry Andric if (Rows.size() > 1) 7490b57cec5SDimitry Andric OS << " return Rows[RowMap[IdxA]][IdxB];\n"; 7500b57cec5SDimitry Andric else 7510b57cec5SDimitry Andric OS << " return Rows[0][IdxB];\n"; 7520b57cec5SDimitry Andric OS << "}\n\n"; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 755*0fca6ea1SDimitry Andric void RegisterInfoEmitter::emitComposeSubRegIndexLaneMask( 756*0fca6ea1SDimitry Andric raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClName) { 7570b57cec5SDimitry Andric // See the comments in computeSubRegLaneMasks() for our goal here. 7580b57cec5SDimitry Andric const auto &SubRegIndices = RegBank.getSubRegIndices(); 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric // Create a list of Mask+Rotate operations, with equivalent entries merged. 7610b57cec5SDimitry Andric SmallVector<unsigned, 4> SubReg2SequenceIndexMap; 7620b57cec5SDimitry Andric SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences; 7630b57cec5SDimitry Andric for (const auto &Idx : SubRegIndices) { 764*0fca6ea1SDimitry Andric const SmallVector<MaskRolPair, 1> &IdxSequence = 765*0fca6ea1SDimitry Andric Idx.CompositionLaneMaskTransform; 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric unsigned Found = ~0u; 7680b57cec5SDimitry Andric unsigned SIdx = 0; 7690b57cec5SDimitry Andric unsigned NextSIdx; 7700b57cec5SDimitry Andric for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { 7710b57cec5SDimitry Andric SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; 7720b57cec5SDimitry Andric NextSIdx = SIdx + Sequence.size() + 1; 7730b57cec5SDimitry Andric if (Sequence == IdxSequence) { 7740b57cec5SDimitry Andric Found = SIdx; 7750b57cec5SDimitry Andric break; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric if (Found == ~0u) { 7790b57cec5SDimitry Andric Sequences.push_back(IdxSequence); 7800b57cec5SDimitry Andric Found = SIdx; 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric SubReg2SequenceIndexMap.push_back(Found); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric OS << " struct MaskRolOp {\n" 7860b57cec5SDimitry Andric " LaneBitmask Mask;\n" 7870b57cec5SDimitry Andric " uint8_t RotateLeft;\n" 7880b57cec5SDimitry Andric " };\n" 7890b57cec5SDimitry Andric " static const MaskRolOp LaneMaskComposeSequences[] = {\n"; 7900b57cec5SDimitry Andric unsigned Idx = 0; 7910b57cec5SDimitry Andric for (size_t s = 0, se = Sequences.size(); s != se; ++s) { 7920b57cec5SDimitry Andric OS << " "; 7930b57cec5SDimitry Andric const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; 7940b57cec5SDimitry Andric for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { 7950b57cec5SDimitry Andric const MaskRolPair &P = Sequence[p]; 7960b57cec5SDimitry Andric printMask(OS << "{ ", P.Mask); 7970b57cec5SDimitry Andric OS << format(", %2u }, ", P.RotateLeft); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric OS << "{ LaneBitmask::getNone(), 0 }"; 8000b57cec5SDimitry Andric if (s + 1 != se) 8010b57cec5SDimitry Andric OS << ", "; 8020b57cec5SDimitry Andric OS << " // Sequence " << Idx << "\n"; 8030b57cec5SDimitry Andric Idx += Sequence.size() + 1; 8040b57cec5SDimitry Andric } 805*0fca6ea1SDimitry Andric auto *IntType = 806*0fca6ea1SDimitry Andric getMinimalTypeForRange(*llvm::max_element(SubReg2SequenceIndexMap)); 8070b57cec5SDimitry Andric OS << " };\n" 80881ad6265SDimitry Andric " static const " 80981ad6265SDimitry Andric << IntType << " CompositeSequences[] = {\n"; 8100b57cec5SDimitry Andric for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { 8110b57cec5SDimitry Andric OS << " "; 81281ad6265SDimitry Andric OS << SubReg2SequenceIndexMap[i]; 8130b57cec5SDimitry Andric if (i + 1 != e) 8140b57cec5SDimitry Andric OS << ","; 8150b57cec5SDimitry Andric OS << " // to " << SubRegIndices[i].getName() << "\n"; 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric OS << " };\n\n"; 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric OS << "LaneBitmask " << ClName 8200b57cec5SDimitry Andric << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)" 8210b57cec5SDimitry Andric " const {\n" 822*0fca6ea1SDimitry Andric " --IdxA; assert(IdxA < " 823*0fca6ea1SDimitry Andric << SubRegIndices.size() 8240b57cec5SDimitry Andric << " && \"Subregister index out of bounds\");\n" 8250b57cec5SDimitry Andric " LaneBitmask Result;\n" 82681ad6265SDimitry Andric " for (const MaskRolOp *Ops =\n" 82781ad6265SDimitry Andric " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" 82881ad6265SDimitry Andric " Ops->Mask.any(); ++Ops) {\n" 829*0fca6ea1SDimitry Andric " LaneBitmask::Type M = LaneMask.getAsInteger() & " 830*0fca6ea1SDimitry Andric "Ops->Mask.getAsInteger();\n" 8310b57cec5SDimitry Andric " if (unsigned S = Ops->RotateLeft)\n" 832*0fca6ea1SDimitry Andric " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - " 833*0fca6ea1SDimitry Andric "S)));\n" 8340b57cec5SDimitry Andric " else\n" 8350b57cec5SDimitry Andric " Result |= LaneBitmask(M);\n" 8360b57cec5SDimitry Andric " }\n" 8370b57cec5SDimitry Andric " return Result;\n" 8380b57cec5SDimitry Andric "}\n\n"; 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric OS << "LaneBitmask " << ClName 8410b57cec5SDimitry Andric << "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, " 8420b57cec5SDimitry Andric " LaneBitmask LaneMask) const {\n" 8430b57cec5SDimitry Andric " LaneMask &= getSubRegIndexLaneMask(IdxA);\n" 844*0fca6ea1SDimitry Andric " --IdxA; assert(IdxA < " 845*0fca6ea1SDimitry Andric << SubRegIndices.size() 8460b57cec5SDimitry Andric << " && \"Subregister index out of bounds\");\n" 8470b57cec5SDimitry Andric " LaneBitmask Result;\n" 84881ad6265SDimitry Andric " for (const MaskRolOp *Ops =\n" 84981ad6265SDimitry Andric " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" 85081ad6265SDimitry Andric " Ops->Mask.any(); ++Ops) {\n" 8510b57cec5SDimitry Andric " LaneBitmask::Type M = LaneMask.getAsInteger();\n" 8520b57cec5SDimitry Andric " if (unsigned S = Ops->RotateLeft)\n" 853*0fca6ea1SDimitry Andric " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - " 854*0fca6ea1SDimitry Andric "S)));\n" 8550b57cec5SDimitry Andric " else\n" 8560b57cec5SDimitry Andric " Result |= LaneBitmask(M);\n" 8570b57cec5SDimitry Andric " }\n" 8580b57cec5SDimitry Andric " return Result;\n" 8590b57cec5SDimitry Andric "}\n\n"; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric // 8630b57cec5SDimitry Andric // runMCDesc - Print out MC register descriptions. 8640b57cec5SDimitry Andric // 865*0fca6ea1SDimitry Andric void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, 8660b57cec5SDimitry Andric CodeGenRegBank &RegBank) { 8670b57cec5SDimitry Andric emitSourceFileHeader("MC Register Information", OS); 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; 8700b57cec5SDimitry Andric OS << "#undef GET_REGINFO_MC_DESC\n\n"; 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric const auto &Regs = RegBank.getRegisters(); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric auto &SubRegIndices = RegBank.getSubRegIndices(); 8750b57cec5SDimitry Andric // The lists of sub-registers and super-registers go in the same array. That 8760b57cec5SDimitry Andric // allows us to share suffixes. 8770b57cec5SDimitry Andric typedef std::vector<const CodeGenRegister *> RegVec; 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Differentially encoded lists. 8800b57cec5SDimitry Andric SequenceToOffsetTable<DiffVec> DiffSeqs; 8810b57cec5SDimitry Andric SmallVector<DiffVec, 4> SubRegLists(Regs.size()); 8820b57cec5SDimitry Andric SmallVector<DiffVec, 4> SuperRegLists(Regs.size()); 8830b57cec5SDimitry Andric SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric // List of lane masks accompanying register unit sequences. 8860b57cec5SDimitry Andric SequenceToOffsetTable<MaskVec> LaneMaskSeqs; 8870b57cec5SDimitry Andric SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size()); 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric // Keep track of sub-register names as well. These are not differentially 8900b57cec5SDimitry Andric // encoded. 8910b57cec5SDimitry Andric typedef SmallVector<const CodeGenSubRegIndex *, 4> SubRegIdxVec; 8928bcb0991SDimitry Andric SequenceToOffsetTable<SubRegIdxVec, deref<std::less<>>> SubRegIdxSeqs; 8930b57cec5SDimitry Andric SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric SequenceToOffsetTable<std::string> RegStrings; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric // Precompute register lists for the SequenceToOffsetTable. 8980b57cec5SDimitry Andric unsigned i = 0; 8990b57cec5SDimitry Andric for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) { 9000b57cec5SDimitry Andric const auto &Reg = *I; 9015ffd83dbSDimitry Andric RegStrings.add(std::string(Reg.getName())); 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric // Compute the ordered sub-register list. 9040b57cec5SDimitry Andric SetVector<const CodeGenRegister *> SR; 9050b57cec5SDimitry Andric Reg.addSubRegsPreOrder(SR, RegBank); 9060b57cec5SDimitry Andric diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end()); 9070b57cec5SDimitry Andric DiffSeqs.add(SubRegLists[i]); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric // Compute the corresponding sub-register indexes. 9100b57cec5SDimitry Andric SubRegIdxVec &SRIs = SubRegIdxLists[i]; 9110b57cec5SDimitry Andric for (const CodeGenRegister *S : SR) 9120b57cec5SDimitry Andric SRIs.push_back(Reg.getSubRegIndex(S)); 9130b57cec5SDimitry Andric SubRegIdxSeqs.add(SRIs); 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric // Super-registers are already computed. 9160b57cec5SDimitry Andric const RegVec &SuperRegList = Reg.getSuperRegs(); 9170b57cec5SDimitry Andric diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(), 9180b57cec5SDimitry Andric SuperRegList.end()); 9190b57cec5SDimitry Andric DiffSeqs.add(SuperRegLists[i]); 9200b57cec5SDimitry Andric 92106c3fb27SDimitry Andric const SparseBitVector<> &RUs = Reg.getNativeRegUnits(); 92206c3fb27SDimitry Andric DiffSeqs.add(diffEncode(RegUnitLists[i], RUs)); 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric const auto &RUMasks = Reg.getRegUnitLaneMasks(); 9250b57cec5SDimitry Andric MaskVec &LaneMaskVec = RegUnitLaneMasks[i]; 9260b57cec5SDimitry Andric assert(LaneMaskVec.empty()); 927e8d8bef9SDimitry Andric llvm::append_range(LaneMaskVec, RUMasks); 9280b57cec5SDimitry Andric LaneMaskSeqs.add(LaneMaskVec); 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric // Compute the final layout of the sequence table. 9320b57cec5SDimitry Andric DiffSeqs.layout(); 9330b57cec5SDimitry Andric LaneMaskSeqs.layout(); 9340b57cec5SDimitry Andric SubRegIdxSeqs.layout(); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 9370b57cec5SDimitry Andric 9385ffd83dbSDimitry Andric const std::string &TargetName = std::string(Target.getName()); 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric // Emit the shared table of differential lists. 94106c3fb27SDimitry Andric OS << "extern const int16_t " << TargetName << "RegDiffLists[] = {\n"; 9420b57cec5SDimitry Andric DiffSeqs.emit(OS, printDiff16); 9430b57cec5SDimitry Andric OS << "};\n\n"; 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric // Emit the shared table of regunit lane mask sequences. 9460b57cec5SDimitry Andric OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n"; 9475f757f3fSDimitry Andric // TODO: Omit the terminator since it is never used. The length of this list 9485f757f3fSDimitry Andric // is known implicitly from the corresponding reg unit list. 9490b57cec5SDimitry Andric LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()"); 9500b57cec5SDimitry Andric OS << "};\n\n"; 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric // Emit the table of sub-register indexes. 9530b57cec5SDimitry Andric OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; 9540b57cec5SDimitry Andric SubRegIdxSeqs.emit(OS, printSubRegIndex); 9550b57cec5SDimitry Andric OS << "};\n\n"; 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric // Emit the string table. 9580b57cec5SDimitry Andric RegStrings.layout(); 9595ffd83dbSDimitry Andric RegStrings.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + 9605ffd83dbSDimitry Andric "RegStrings[]"); 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric OS << "extern const MCRegisterDesc " << TargetName 9630b57cec5SDimitry Andric << "RegDesc[] = { // Descriptors\n"; 964*0fca6ea1SDimitry Andric OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0, 0 },\n"; 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric // Emit the register descriptors now. 9670b57cec5SDimitry Andric i = 0; 9680b57cec5SDimitry Andric for (const auto &Reg : Regs) { 96906c3fb27SDimitry Andric unsigned FirstRU = Reg.getNativeRegUnits().find_first(); 97006c3fb27SDimitry Andric unsigned Offset = DiffSeqs.get(RegUnitLists[i]); 97106c3fb27SDimitry Andric // The value must be kept in sync with MCRegisterInfo.h. 97206c3fb27SDimitry Andric constexpr unsigned RegUnitBits = 12; 97306c3fb27SDimitry Andric assert(isUInt<RegUnitBits>(FirstRU) && "Too many regunits"); 97406c3fb27SDimitry Andric assert(isUInt<32 - RegUnitBits>(Offset) && "Offset is too big"); 9755ffd83dbSDimitry Andric OS << " { " << RegStrings.get(std::string(Reg.getName())) << ", " 9760b57cec5SDimitry Andric << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) 9770b57cec5SDimitry Andric << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " 97806c3fb27SDimitry Andric << (Offset << RegUnitBits | FirstRU) << ", " 979*0fca6ea1SDimitry Andric << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << ", " << Reg.Constant 980*0fca6ea1SDimitry Andric << " },\n"; 9810b57cec5SDimitry Andric ++i; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric OS << "};\n\n"; // End of register descriptors... 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric // Emit the table of register unit roots. Each regunit has one or two root 9860b57cec5SDimitry Andric // registers. 9870b57cec5SDimitry Andric OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; 9880b57cec5SDimitry Andric for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { 9890b57cec5SDimitry Andric ArrayRef<const CodeGenRegister *> Roots = RegBank.getRegUnit(i).getRoots(); 9900b57cec5SDimitry Andric assert(!Roots.empty() && "All regunits must have a root register."); 9910b57cec5SDimitry Andric assert(Roots.size() <= 2 && "More than two roots not supported yet."); 992fe6060f1SDimitry Andric OS << " { "; 993fe6060f1SDimitry Andric ListSeparator LS; 994fe6060f1SDimitry Andric for (const CodeGenRegister *R : Roots) 995fe6060f1SDimitry Andric OS << LS << getQualifiedName(R->TheDef); 9960b57cec5SDimitry Andric OS << " },\n"; 9970b57cec5SDimitry Andric } 9980b57cec5SDimitry Andric OS << "};\n\n"; 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric const auto &RegisterClasses = RegBank.getRegClasses(); 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric // Loop over all of the register classes... emitting each one. 10030b57cec5SDimitry Andric OS << "namespace { // Register classes...\n"; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric SequenceToOffsetTable<std::string> RegClassStrings; 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric // Emit the register enum value arrays for each RegisterClass 10080b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 10090b57cec5SDimitry Andric ArrayRef<Record *> Order = RC.getOrder(); 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric // Give the register class a legal C name if it's anonymous. 10120b57cec5SDimitry Andric const std::string &Name = RC.getName(); 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric RegClassStrings.add(Name); 10150b57cec5SDimitry Andric 101681ad6265SDimitry Andric // Emit the register list now (unless it would be a zero-length array). 101781ad6265SDimitry Andric if (!Order.empty()) { 10180b57cec5SDimitry Andric OS << " // " << Name << " Register Class...\n" 101981ad6265SDimitry Andric << " const MCPhysReg " << Name << "[] = {\n "; 10200b57cec5SDimitry Andric for (Record *Reg : Order) { 10210b57cec5SDimitry Andric OS << getQualifiedName(Reg) << ", "; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric OS << "\n };\n\n"; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric OS << " // " << Name << " Bit set.\n" 102681ad6265SDimitry Andric << " const uint8_t " << Name << "Bits[] = {\n "; 10270b57cec5SDimitry Andric BitVectorEmitter BVE; 10280b57cec5SDimitry Andric for (Record *Reg : Order) { 10290b57cec5SDimitry Andric BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric BVE.print(OS); 10320b57cec5SDimitry Andric OS << "\n };\n\n"; 103381ad6265SDimitry Andric } 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric OS << "} // end anonymous namespace\n\n"; 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric RegClassStrings.layout(); 10385ffd83dbSDimitry Andric RegClassStrings.emitStringLiteralDef( 10395ffd83dbSDimitry Andric OS, Twine("extern const char ") + TargetName + "RegClassStrings[]"); 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric OS << "extern const MCRegisterClass " << TargetName 10420b57cec5SDimitry Andric << "MCRegisterClasses[] = {\n"; 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 104581ad6265SDimitry Andric ArrayRef<Record *> Order = RC.getOrder(); 104681ad6265SDimitry Andric std::string RCName = Order.empty() ? "nullptr" : RC.getName(); 104781ad6265SDimitry Andric std::string RCBitsName = Order.empty() ? "nullptr" : RC.getName() + "Bits"; 104881ad6265SDimitry Andric std::string RCBitsSize = Order.empty() ? "0" : "sizeof(" + RCBitsName + ")"; 10490b57cec5SDimitry Andric assert(isInt<8>(RC.CopyCost) && "Copy cost too large."); 1050fe6060f1SDimitry Andric uint32_t RegSize = 0; 1051fe6060f1SDimitry Andric if (RC.RSI.isSimple()) 1052fe6060f1SDimitry Andric RegSize = RC.RSI.getSimple().RegSize; 105381ad6265SDimitry Andric OS << " { " << RCName << ", " << RCBitsName << ", " 1054fe6060f1SDimitry Andric << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() 10555f757f3fSDimitry Andric << ", " << RCBitsSize << ", " << RC.getQualifiedIdName() << ", " 10565f757f3fSDimitry Andric << RegSize << ", " << RC.CopyCost << ", " 1057*0fca6ea1SDimitry Andric << (RC.Allocatable ? "true" : "false") << ", " 1058*0fca6ea1SDimitry Andric << (RC.getBaseClassOrder() ? "true" : "false") << " },\n"; 10590b57cec5SDimitry Andric } 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric OS << "};\n\n"; 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric EmitRegMappingTables(OS, Regs, false); 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric // Emit Reg encoding table 10660b57cec5SDimitry Andric OS << "extern const uint16_t " << TargetName; 10670b57cec5SDimitry Andric OS << "RegEncodingTable[] = {\n"; 10680b57cec5SDimitry Andric // Add entry for NoRegister 10690b57cec5SDimitry Andric OS << " 0,\n"; 10700b57cec5SDimitry Andric for (const auto &RE : Regs) { 10710b57cec5SDimitry Andric Record *Reg = RE.TheDef; 10720b57cec5SDimitry Andric BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); 10730b57cec5SDimitry Andric uint64_t Value = 0; 10740b57cec5SDimitry Andric for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { 10750b57cec5SDimitry Andric if (BitInit *B = dyn_cast<BitInit>(BI->getBit(b))) 10760b57cec5SDimitry Andric Value |= (uint64_t)B->getValue() << b; 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric OS << " " << Value << ",\n"; 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric OS << "};\n"; // End of HW encoding table 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric // MCRegisterInfo initialization routine. 10830b57cec5SDimitry Andric OS << "static inline void Init" << TargetName 10840b57cec5SDimitry Andric << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " 10850b57cec5SDimitry Andric << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " 10860b57cec5SDimitry Andric "{\n" 10870b57cec5SDimitry Andric << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " 10880b57cec5SDimitry Andric << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " 10890b57cec5SDimitry Andric << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " 10900b57cec5SDimitry Andric << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " 10910b57cec5SDimitry Andric << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " 10920b57cec5SDimitry Andric << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " 10930b57cec5SDimitry Andric << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" 1094*0fca6ea1SDimitry Andric << TargetName << "RegEncodingTable);\n\n"; 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric EmitRegMapping(OS, Regs, false); 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric OS << "}\n\n"; 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric OS << "} // end namespace llvm\n\n"; 11010b57cec5SDimitry Andric OS << "#endif // GET_REGINFO_MC_DESC\n\n"; 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric 1104*0fca6ea1SDimitry Andric void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, 1105*0fca6ea1SDimitry Andric CodeGenTarget &Target, 11060b57cec5SDimitry Andric CodeGenRegBank &RegBank) { 11070b57cec5SDimitry Andric emitSourceFileHeader("Register Information Header Fragment", OS); 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric OS << "\n#ifdef GET_REGINFO_HEADER\n"; 11100b57cec5SDimitry Andric OS << "#undef GET_REGINFO_HEADER\n\n"; 11110b57cec5SDimitry Andric 11125ffd83dbSDimitry Andric const std::string &TargetName = std::string(Target.getName()); 11130b57cec5SDimitry Andric std::string ClassName = TargetName + "GenRegisterInfo"; 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric OS << "#include \"llvm/CodeGen/TargetRegisterInfo.h\"\n\n"; 11160b57cec5SDimitry Andric 11170b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric OS << "class " << TargetName << "FrameLowering;\n\n"; 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" 11220b57cec5SDimitry Andric << " explicit " << ClassName 11230b57cec5SDimitry Andric << "(unsigned RA, unsigned D = 0, unsigned E = 0,\n" 11240b57cec5SDimitry Andric << " unsigned PC = 0, unsigned HwMode = 0);\n"; 11250b57cec5SDimitry Andric if (!RegBank.getSubRegIndices().empty()) { 11260b57cec5SDimitry Andric OS << " unsigned composeSubRegIndicesImpl" 11270b57cec5SDimitry Andric << "(unsigned, unsigned) const override;\n" 11280b57cec5SDimitry Andric << " LaneBitmask composeSubRegIndexLaneMaskImpl" 11290b57cec5SDimitry Andric << "(unsigned, LaneBitmask) const override;\n" 11300b57cec5SDimitry Andric << " LaneBitmask reverseComposeSubRegIndexLaneMaskImpl" 11310b57cec5SDimitry Andric << "(unsigned, LaneBitmask) const override;\n" 11320b57cec5SDimitry Andric << " const TargetRegisterClass *getSubClassWithSubReg" 1133bdd1243dSDimitry Andric << "(const TargetRegisterClass *, unsigned) const override;\n" 1134bdd1243dSDimitry Andric << " const TargetRegisterClass *getSubRegisterClass" 11350b57cec5SDimitry Andric << "(const TargetRegisterClass *, unsigned) const override;\n"; 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric OS << " const RegClassWeight &getRegClassWeight(" 11380b57cec5SDimitry Andric << "const TargetRegisterClass *RC) const override;\n" 11390b57cec5SDimitry Andric << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" 11400b57cec5SDimitry Andric << " unsigned getNumRegPressureSets() const override;\n" 11410b57cec5SDimitry Andric << " const char *getRegPressureSetName(unsigned Idx) const override;\n" 11420b57cec5SDimitry Andric << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " 11430b57cec5SDimitry Andric "Idx) const override;\n" 11440b57cec5SDimitry Andric << " const int *getRegClassPressureSets(" 11450b57cec5SDimitry Andric << "const TargetRegisterClass *RC) const override;\n" 11460b57cec5SDimitry Andric << " const int *getRegUnitPressureSets(" 11470b57cec5SDimitry Andric << "unsigned RegUnit) const override;\n" 11480b57cec5SDimitry Andric << " ArrayRef<const char *> getRegMaskNames() const override;\n" 11490b57cec5SDimitry Andric << " ArrayRef<const uint32_t *> getRegMasks() const override;\n" 115081ad6265SDimitry Andric << " bool isGeneralPurposeRegister(const MachineFunction &, " 115181ad6265SDimitry Andric << "MCRegister) const override;\n" 115281ad6265SDimitry Andric << " bool isFixedRegister(const MachineFunction &, " 115381ad6265SDimitry Andric << "MCRegister) const override;\n" 115481ad6265SDimitry Andric << " bool isArgumentRegister(const MachineFunction &, " 115581ad6265SDimitry Andric << "MCRegister) const override;\n" 1156bdd1243dSDimitry Andric << " bool isConstantPhysReg(MCRegister PhysReg) const override final;\n" 11570b57cec5SDimitry Andric << " /// Devirtualized TargetFrameLowering.\n" 11580b57cec5SDimitry Andric << " static const " << TargetName << "FrameLowering *getFrameLowering(\n" 1159bdd1243dSDimitry Andric << " const MachineFunction &MF);\n"; 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric const auto &RegisterClasses = RegBank.getRegClasses(); 1162*0fca6ea1SDimitry Andric if (llvm::any_of(RegisterClasses, 1163*0fca6ea1SDimitry Andric [](const auto &RC) { return RC.getBaseClassOrder(); })) { 1164*0fca6ea1SDimitry Andric OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) " 1165*0fca6ea1SDimitry Andric "const override;\n"; 1166bdd1243dSDimitry Andric } 1167bdd1243dSDimitry Andric 1168bdd1243dSDimitry Andric OS << "};\n\n"; 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric if (!RegisterClasses.empty()) { 11710b57cec5SDimitry Andric OS << "namespace " << RegisterClasses.front().Namespace 11720b57cec5SDimitry Andric << " { // Register classes\n"; 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 11750b57cec5SDimitry Andric const std::string &Name = RC.getName(); 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric // Output the extern for the instance. 11780b57cec5SDimitry Andric OS << " extern const TargetRegisterClass " << Name << "RegClass;\n"; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n"; 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric OS << "} // end namespace llvm\n\n"; 11830b57cec5SDimitry Andric OS << "#endif // GET_REGINFO_HEADER\n\n"; 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric // 11870b57cec5SDimitry Andric // runTargetDesc - Output the target register and register file descriptions. 11880b57cec5SDimitry Andric // 1189*0fca6ea1SDimitry Andric void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, 11900b57cec5SDimitry Andric CodeGenRegBank &RegBank) { 11910b57cec5SDimitry Andric emitSourceFileHeader("Target Register and Register Classes Information", OS); 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; 11940b57cec5SDimitry Andric OS << "#undef GET_REGINFO_TARGET_DESC\n\n"; 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric OS << "namespace llvm {\n\n"; 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric // Get access to MCRegisterClass data. 11990b57cec5SDimitry Andric OS << "extern const MCRegisterClass " << Target.getName() 12000b57cec5SDimitry Andric << "MCRegisterClasses[];\n"; 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric // Start out by emitting each of the register classes. 12030b57cec5SDimitry Andric const auto &RegisterClasses = RegBank.getRegClasses(); 12040b57cec5SDimitry Andric const auto &SubRegIndices = RegBank.getSubRegIndices(); 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric // Collect all registers belonging to any allocatable class. 12070b57cec5SDimitry Andric std::set<Record *> AllocatableRegs; 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric // Collect allocatable registers. 12100b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 12110b57cec5SDimitry Andric ArrayRef<Record *> Order = RC.getOrder(); 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric if (RC.Allocatable) 12140b57cec5SDimitry Andric AllocatableRegs.insert(Order.begin(), Order.end()); 12150b57cec5SDimitry Andric } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric const CodeGenHwModes &CGH = Target.getHwModes(); 12180b57cec5SDimitry Andric unsigned NumModes = CGH.getNumModeIds(); 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric // Build a shared array of value types. 12210b57cec5SDimitry Andric SequenceToOffsetTable<std::vector<MVT::SimpleValueType>> VTSeqs; 12220b57cec5SDimitry Andric for (unsigned M = 0; M < NumModes; ++M) { 12230b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 12240b57cec5SDimitry Andric std::vector<MVT::SimpleValueType> S; 12250b57cec5SDimitry Andric for (const ValueTypeByHwMode &VVT : RC.VTs) 122606c3fb27SDimitry Andric if (VVT.hasDefault() || VVT.hasMode(M)) 12270b57cec5SDimitry Andric S.push_back(VVT.get(M).SimpleTy); 12280b57cec5SDimitry Andric VTSeqs.add(S); 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric } 12310b57cec5SDimitry Andric VTSeqs.layout(); 12320b57cec5SDimitry Andric OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; 12330b57cec5SDimitry Andric VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); 12340b57cec5SDimitry Andric OS << "};\n"; 12350b57cec5SDimitry Andric 12360b57cec5SDimitry Andric // Emit SubRegIndex names, skipping 0. 123781ad6265SDimitry Andric OS << "\nstatic const char *SubRegIndexNameTable[] = { \""; 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric for (const auto &Idx : SubRegIndices) { 12400b57cec5SDimitry Andric OS << Idx.getName(); 12410b57cec5SDimitry Andric OS << "\", \""; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric OS << "\" };\n\n"; 12440b57cec5SDimitry Andric 1245*0fca6ea1SDimitry Andric // Emit the table of sub-register index sizes. 1246*0fca6ea1SDimitry Andric OS << "static const TargetRegisterInfo::SubRegCoveredBits " 1247*0fca6ea1SDimitry Andric "SubRegIdxRangeTable[] = {\n"; 1248*0fca6ea1SDimitry Andric for (unsigned M = 0; M < NumModes; ++M) { 1249*0fca6ea1SDimitry Andric OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; 1250*0fca6ea1SDimitry Andric for (const auto &Idx : SubRegIndices) { 1251*0fca6ea1SDimitry Andric const SubRegRange &Range = Idx.Range.get(M); 1252*0fca6ea1SDimitry Andric OS << " { " << Range.Offset << ", " << Range.Size << " },\t// " 1253*0fca6ea1SDimitry Andric << Idx.getName() << "\n"; 1254*0fca6ea1SDimitry Andric } 1255*0fca6ea1SDimitry Andric } 1256*0fca6ea1SDimitry Andric OS << "};\n\n"; 1257*0fca6ea1SDimitry Andric 12580b57cec5SDimitry Andric // Emit SubRegIndex lane masks, including 0. 12590b57cec5SDimitry Andric OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " 12600b57cec5SDimitry Andric "LaneBitmask::getAll(),\n"; 12610b57cec5SDimitry Andric for (const auto &Idx : SubRegIndices) { 12620b57cec5SDimitry Andric printMask(OS << " ", Idx.LaneMask); 12630b57cec5SDimitry Andric OS << ", // " << Idx.getName() << '\n'; 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric OS << " };\n\n"; 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric OS << "\n"; 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric // Now that all of the structs have been emitted, emit the instances. 12700b57cec5SDimitry Andric if (!RegisterClasses.empty()) { 12710b57cec5SDimitry Andric OS << "\nstatic const TargetRegisterInfo::RegClassInfo RegClassInfos[]" 12720b57cec5SDimitry Andric << " = {\n"; 12730b57cec5SDimitry Andric for (unsigned M = 0; M < NumModes; ++M) { 12740b57cec5SDimitry Andric unsigned EV = 0; 12750b57cec5SDimitry Andric OS << " // Mode = " << M << " ("; 12760b57cec5SDimitry Andric if (M == 0) 12770b57cec5SDimitry Andric OS << "Default"; 12780b57cec5SDimitry Andric else 12790b57cec5SDimitry Andric OS << CGH.getMode(M).Name; 12800b57cec5SDimitry Andric OS << ")\n"; 12810b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 1282e8d8bef9SDimitry Andric assert(RC.EnumValue == EV && "Unexpected order of register classes"); 1283e8d8bef9SDimitry Andric ++EV; 12840b57cec5SDimitry Andric (void)EV; 12850b57cec5SDimitry Andric const RegSizeInfo &RI = RC.RSI.get(M); 12860b57cec5SDimitry Andric OS << " { " << RI.RegSize << ", " << RI.SpillSize << ", " 12870b57cec5SDimitry Andric << RI.SpillAlignment; 12880b57cec5SDimitry Andric std::vector<MVT::SimpleValueType> VTs; 12890b57cec5SDimitry Andric for (const ValueTypeByHwMode &VVT : RC.VTs) 129006c3fb27SDimitry Andric if (VVT.hasDefault() || VVT.hasMode(M)) 12910b57cec5SDimitry Andric VTs.push_back(VVT.get(M).SimpleTy); 12925f757f3fSDimitry Andric OS << ", /*VTLists+*/" << VTSeqs.get(VTs) << " }, // " 12930b57cec5SDimitry Andric << RC.getName() << '\n'; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric } 12960b57cec5SDimitry Andric OS << "};\n"; 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric OS << "\nstatic const TargetRegisterClass *const " 12990b57cec5SDimitry Andric << "NullRegClasses[] = { nullptr };\n\n"; 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric // Emit register class bit mask tables. The first bit mask emitted for a 13020b57cec5SDimitry Andric // register class, RC, is the set of sub-classes, including RC itself. 13030b57cec5SDimitry Andric // 13040b57cec5SDimitry Andric // If RC has super-registers, also create a list of subreg indices and bit 13050b57cec5SDimitry Andric // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass, 13060b57cec5SDimitry Andric // SuperRC, that satisfies: 13070b57cec5SDimitry Andric // 13080b57cec5SDimitry Andric // For all SuperReg in SuperRC: SuperReg:Idx in RC 13090b57cec5SDimitry Andric // 13100b57cec5SDimitry Andric // The 0-terminated list of subreg indices starts at: 13110b57cec5SDimitry Andric // 13120b57cec5SDimitry Andric // RC->getSuperRegIndices() = SuperRegIdxSeqs + ... 13130b57cec5SDimitry Andric // 13140b57cec5SDimitry Andric // The corresponding bitmasks follow the sub-class mask in memory. Each 13150b57cec5SDimitry Andric // mask has RCMaskWords uint32_t entries. 13160b57cec5SDimitry Andric // 13170b57cec5SDimitry Andric // Every bit mask present in the list has at least one bit set. 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric // Compress the sub-reg index lists. 13200b57cec5SDimitry Andric typedef std::vector<const CodeGenSubRegIndex *> IdxList; 13210b57cec5SDimitry Andric SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size()); 13228bcb0991SDimitry Andric SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs; 13230b57cec5SDimitry Andric BitVector MaskBV(RegisterClasses.size()); 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 13260b57cec5SDimitry Andric OS << "static const uint32_t " << RC.getName() 13270b57cec5SDimitry Andric << "SubClassMask[] = {\n "; 13280b57cec5SDimitry Andric printBitVectorAsHex(OS, RC.getSubClasses(), 32); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric // Emit super-reg class masks for any relevant SubRegIndices that can 13310b57cec5SDimitry Andric // project into RC. 13320b57cec5SDimitry Andric IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; 13330b57cec5SDimitry Andric for (auto &Idx : SubRegIndices) { 13340b57cec5SDimitry Andric MaskBV.reset(); 13350b57cec5SDimitry Andric RC.getSuperRegClasses(&Idx, MaskBV); 13360b57cec5SDimitry Andric if (MaskBV.none()) 13370b57cec5SDimitry Andric continue; 13380b57cec5SDimitry Andric SRIList.push_back(&Idx); 13390b57cec5SDimitry Andric OS << "\n "; 13400b57cec5SDimitry Andric printBitVectorAsHex(OS, MaskBV, 32); 13410b57cec5SDimitry Andric OS << "// " << Idx.getName(); 13420b57cec5SDimitry Andric } 13430b57cec5SDimitry Andric SuperRegIdxSeqs.add(SRIList); 13440b57cec5SDimitry Andric OS << "\n};\n\n"; 13450b57cec5SDimitry Andric } 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric OS << "static const uint16_t SuperRegIdxSeqs[] = {\n"; 13480b57cec5SDimitry Andric SuperRegIdxSeqs.layout(); 13490b57cec5SDimitry Andric SuperRegIdxSeqs.emit(OS, printSubRegIndex); 13500b57cec5SDimitry Andric OS << "};\n\n"; 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric // Emit NULL terminated super-class lists. 13530b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 13540b57cec5SDimitry Andric ArrayRef<CodeGenRegisterClass *> Supers = RC.getSuperClasses(); 13550b57cec5SDimitry Andric 13560b57cec5SDimitry Andric // Skip classes without supers. We can reuse NullRegClasses. 13570b57cec5SDimitry Andric if (Supers.empty()) 13580b57cec5SDimitry Andric continue; 13590b57cec5SDimitry Andric 1360*0fca6ea1SDimitry Andric OS << "static const TargetRegisterClass *const " << RC.getName() 1361*0fca6ea1SDimitry Andric << "Superclasses[] = {\n"; 13620b57cec5SDimitry Andric for (const auto *Super : Supers) 13630b57cec5SDimitry Andric OS << " &" << Super->getQualifiedName() << "RegClass,\n"; 13640b57cec5SDimitry Andric OS << " nullptr\n};\n\n"; 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric // Emit methods. 13680b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 13690b57cec5SDimitry Andric if (!RC.AltOrderSelect.empty()) { 13700b57cec5SDimitry Andric OS << "\nstatic inline unsigned " << RC.getName() 1371*0fca6ea1SDimitry Andric << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect 1372*0fca6ea1SDimitry Andric << "}\n\n" 13730b57cec5SDimitry Andric << "static ArrayRef<MCPhysReg> " << RC.getName() 13740b57cec5SDimitry Andric << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; 13750b57cec5SDimitry Andric for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) { 13760b57cec5SDimitry Andric ArrayRef<Record *> Elems = RC.getOrder(oi); 13770b57cec5SDimitry Andric if (!Elems.empty()) { 13780b57cec5SDimitry Andric OS << " static const MCPhysReg AltOrder" << oi << "[] = {"; 13790b57cec5SDimitry Andric for (unsigned elem = 0; elem != Elems.size(); ++elem) 13800b57cec5SDimitry Andric OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); 13810b57cec5SDimitry Andric OS << " };\n"; 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric OS << " const MCRegisterClass &MCR = " << Target.getName() 13850b57cec5SDimitry Andric << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" 13860b57cec5SDimitry Andric << " const ArrayRef<MCPhysReg> Order[] = {\n" 1387bdd1243dSDimitry Andric << " ArrayRef(MCR.begin(), MCR.getNumRegs()"; 13880b57cec5SDimitry Andric for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) 13890b57cec5SDimitry Andric if (RC.getOrder(oi).empty()) 13900b57cec5SDimitry Andric OS << "),\n ArrayRef<MCPhysReg>("; 13910b57cec5SDimitry Andric else 1392bdd1243dSDimitry Andric OS << "),\n ArrayRef(AltOrder" << oi; 13930b57cec5SDimitry Andric OS << ")\n };\n const unsigned Select = " << RC.getName() 13940b57cec5SDimitry Andric << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() 13950b57cec5SDimitry Andric << ");\n return Order[Select];\n}\n"; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric // Now emit the actual value-initialized register class instances. 14000b57cec5SDimitry Andric OS << "\nnamespace " << RegisterClasses.front().Namespace 14010b57cec5SDimitry Andric << " { // Register class instances\n"; 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 14040b57cec5SDimitry Andric OS << " extern const TargetRegisterClass " << RC.getName() 14050b57cec5SDimitry Andric << "RegClass = {\n " << '&' << Target.getName() 14060b57cec5SDimitry Andric << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " 14070b57cec5SDimitry Andric << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " 14080b57cec5SDimitry Andric << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "; 14090b57cec5SDimitry Andric printMask(OS, RC.LaneMask); 14100b57cec5SDimitry Andric OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " 1411bdd1243dSDimitry Andric << (RC.GlobalPriority ? "true" : "false") << ",\n " 1412349cc55cSDimitry Andric << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n " 14130b57cec5SDimitry Andric << (RC.HasDisjunctSubRegs ? "true" : "false") 14140b57cec5SDimitry Andric << ", /* HasDisjunctSubRegs */\n " 14150b57cec5SDimitry Andric << (RC.CoveredBySubRegs ? "true" : "false") 14160b57cec5SDimitry Andric << ", /* CoveredBySubRegs */\n "; 14170b57cec5SDimitry Andric if (RC.getSuperClasses().empty()) 14180b57cec5SDimitry Andric OS << "NullRegClasses,\n "; 14190b57cec5SDimitry Andric else 14200b57cec5SDimitry Andric OS << RC.getName() << "Superclasses,\n "; 14210b57cec5SDimitry Andric if (RC.AltOrderSelect.empty()) 14220b57cec5SDimitry Andric OS << "nullptr\n"; 14230b57cec5SDimitry Andric else 14240b57cec5SDimitry Andric OS << RC.getName() << "GetRawAllocationOrder\n"; 14250b57cec5SDimitry Andric OS << " };\n\n"; 14260b57cec5SDimitry Andric } 14270b57cec5SDimitry Andric 14280b57cec5SDimitry Andric OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n"; 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric OS << "\nnamespace {\n"; 14320b57cec5SDimitry Andric OS << " const TargetRegisterClass *const RegisterClasses[] = {\n"; 14330b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) 14340b57cec5SDimitry Andric OS << " &" << RC.getQualifiedName() << "RegClass,\n"; 14350b57cec5SDimitry Andric OS << " };\n"; 14360b57cec5SDimitry Andric OS << "} // end anonymous namespace\n"; 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric // Emit extra information about registers. 14395ffd83dbSDimitry Andric const std::string &TargetName = std::string(Target.getName()); 14400b57cec5SDimitry Andric const auto &Regs = RegBank.getRegisters(); 1441fe6060f1SDimitry Andric unsigned NumRegCosts = 1; 1442fe6060f1SDimitry Andric for (const auto &Reg : Regs) 1443fe6060f1SDimitry Andric NumRegCosts = std::max((size_t)NumRegCosts, Reg.CostPerUse.size()); 14440b57cec5SDimitry Andric 1445fe6060f1SDimitry Andric std::vector<unsigned> AllRegCostPerUse; 1446fe6060f1SDimitry Andric llvm::BitVector InAllocClass(Regs.size() + 1, false); 1447fe6060f1SDimitry Andric AllRegCostPerUse.insert(AllRegCostPerUse.end(), NumRegCosts, 0); 1448fe6060f1SDimitry Andric 1449fe6060f1SDimitry Andric // Populate the vector RegCosts with the CostPerUse list of the registers 1450fe6060f1SDimitry Andric // in the order they are read. Have at most NumRegCosts entries for 1451fe6060f1SDimitry Andric // each register. Fill with zero for values which are not explicitly given. 1452fe6060f1SDimitry Andric for (const auto &Reg : Regs) { 1453fe6060f1SDimitry Andric auto Costs = Reg.CostPerUse; 1454fe6060f1SDimitry Andric AllRegCostPerUse.insert(AllRegCostPerUse.end(), Costs.begin(), Costs.end()); 1455fe6060f1SDimitry Andric if (NumRegCosts > Costs.size()) 1456fe6060f1SDimitry Andric AllRegCostPerUse.insert(AllRegCostPerUse.end(), 1457fe6060f1SDimitry Andric NumRegCosts - Costs.size(), 0); 1458fe6060f1SDimitry Andric 1459fe6060f1SDimitry Andric if (AllocatableRegs.count(Reg.TheDef)) 1460fe6060f1SDimitry Andric InAllocClass.set(Reg.EnumValue); 1461fe6060f1SDimitry Andric } 1462fe6060f1SDimitry Andric 1463fe6060f1SDimitry Andric // Emit the cost values as a 1D-array after grouping them by their indices, 1464fe6060f1SDimitry Andric // i.e. the costs for all registers corresponds to index 0, 1, 2, etc. 1465fe6060f1SDimitry Andric // Size of the emitted array should be NumRegCosts * (Regs.size() + 1). 1466fe6060f1SDimitry Andric OS << "\nstatic const uint8_t " 1467fe6060f1SDimitry Andric << "CostPerUseTable[] = { \n"; 1468fe6060f1SDimitry Andric for (unsigned int I = 0; I < NumRegCosts; ++I) { 1469fe6060f1SDimitry Andric for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts) 1470fe6060f1SDimitry Andric OS << AllRegCostPerUse[J] << ", "; 1471fe6060f1SDimitry Andric } 1472fe6060f1SDimitry Andric OS << "};\n\n"; 1473fe6060f1SDimitry Andric 1474fe6060f1SDimitry Andric OS << "\nstatic const bool " 1475fe6060f1SDimitry Andric << "InAllocatableClassTable[] = { \n"; 1476fe6060f1SDimitry Andric for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) { 1477fe6060f1SDimitry Andric OS << (InAllocClass[I] ? "true" : "false") << ", "; 1478fe6060f1SDimitry Andric } 1479fe6060f1SDimitry Andric OS << "};\n\n"; 1480fe6060f1SDimitry Andric 1481fe6060f1SDimitry Andric OS << "\nstatic const TargetRegisterInfoDesc " << TargetName 1482fe6060f1SDimitry Andric << "RegInfoDesc = { // Extra Descriptors\n"; 1483fe6060f1SDimitry Andric OS << "CostPerUseTable, " << NumRegCosts << ", " 1484fe6060f1SDimitry Andric << "InAllocatableClassTable"; 1485fe6060f1SDimitry Andric OS << "};\n\n"; // End of register descriptors... 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric std::string ClassName = Target.getName().str() + "GenRegisterInfo"; 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric auto SubRegIndicesSize = 14900b57cec5SDimitry Andric std::distance(SubRegIndices.begin(), SubRegIndices.end()); 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric if (!SubRegIndices.empty()) { 14930b57cec5SDimitry Andric emitComposeSubRegIndices(OS, RegBank, ClassName); 14940b57cec5SDimitry Andric emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName); 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric if (!SubRegIndices.empty()) { 1498bdd1243dSDimitry Andric // Emit getSubClassWithSubReg. 14990b57cec5SDimitry Andric OS << "const TargetRegisterClass *" << ClassName 15000b57cec5SDimitry Andric << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" 15010b57cec5SDimitry Andric << " const {\n"; 15020b57cec5SDimitry Andric // Use the smallest type that can hold a regclass ID with room for a 15030b57cec5SDimitry Andric // sentinel. 1504bdd1243dSDimitry Andric if (RegisterClasses.size() <= UINT8_MAX) 15050b57cec5SDimitry Andric OS << " static const uint8_t Table["; 1506bdd1243dSDimitry Andric else if (RegisterClasses.size() <= UINT16_MAX) 15070b57cec5SDimitry Andric OS << " static const uint16_t Table["; 15080b57cec5SDimitry Andric else 15090b57cec5SDimitry Andric PrintFatalError("Too many register classes."); 15100b57cec5SDimitry Andric OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; 15110b57cec5SDimitry Andric for (const auto &RC : RegisterClasses) { 15120b57cec5SDimitry Andric OS << " {\t// " << RC.getName() << "\n"; 15130b57cec5SDimitry Andric for (auto &Idx : SubRegIndices) { 15140b57cec5SDimitry Andric if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) 15150b57cec5SDimitry Andric OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() 15160b57cec5SDimitry Andric << " -> " << SRC->getName() << "\n"; 15170b57cec5SDimitry Andric else 15180b57cec5SDimitry Andric OS << " 0,\t// " << Idx.getName() << "\n"; 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric OS << " },\n"; 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric OS << " };\n assert(RC && \"Missing regclass\");\n" 15230b57cec5SDimitry Andric << " if (!Idx) return RC;\n --Idx;\n" 15240b57cec5SDimitry Andric << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" 15250b57cec5SDimitry Andric << " unsigned TV = Table[RC->getID()][Idx];\n" 15260b57cec5SDimitry Andric << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; 1527bdd1243dSDimitry Andric 1528bdd1243dSDimitry Andric // Emit getSubRegisterClass 1529bdd1243dSDimitry Andric OS << "const TargetRegisterClass *" << ClassName 1530bdd1243dSDimitry Andric << "::getSubRegisterClass(const TargetRegisterClass *RC, unsigned Idx)" 1531bdd1243dSDimitry Andric << " const {\n"; 1532bdd1243dSDimitry Andric 1533bdd1243dSDimitry Andric // Use the smallest type that can hold a regclass ID with room for a 1534bdd1243dSDimitry Andric // sentinel. 1535bdd1243dSDimitry Andric if (RegisterClasses.size() <= UINT8_MAX) 1536bdd1243dSDimitry Andric OS << " static const uint8_t Table["; 1537bdd1243dSDimitry Andric else if (RegisterClasses.size() <= UINT16_MAX) 1538bdd1243dSDimitry Andric OS << " static const uint16_t Table["; 1539bdd1243dSDimitry Andric else 1540bdd1243dSDimitry Andric PrintFatalError("Too many register classes."); 1541bdd1243dSDimitry Andric 1542bdd1243dSDimitry Andric OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; 1543bdd1243dSDimitry Andric 1544bdd1243dSDimitry Andric for (const auto &RC : RegisterClasses) { 1545bdd1243dSDimitry Andric OS << " {\t// " << RC.getName() << '\n'; 1546bdd1243dSDimitry Andric for (auto &Idx : SubRegIndices) { 1547bdd1243dSDimitry Andric std::optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>> 1548bdd1243dSDimitry Andric MatchingSubClass = RC.getMatchingSubClassWithSubRegs(RegBank, &Idx); 1549bdd1243dSDimitry Andric 1550bdd1243dSDimitry Andric unsigned EnumValue = 0; 1551bdd1243dSDimitry Andric if (MatchingSubClass) { 1552bdd1243dSDimitry Andric CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; 1553bdd1243dSDimitry Andric EnumValue = SubRegClass->EnumValue + 1; 1554bdd1243dSDimitry Andric } 1555bdd1243dSDimitry Andric 1556*0fca6ea1SDimitry Andric OS << " " << EnumValue << ",\t// " << RC.getName() << ':' 1557*0fca6ea1SDimitry Andric << Idx.getName(); 1558bdd1243dSDimitry Andric 1559bdd1243dSDimitry Andric if (MatchingSubClass) { 1560bdd1243dSDimitry Andric CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; 1561bdd1243dSDimitry Andric OS << " -> " << SubRegClass->getName(); 1562bdd1243dSDimitry Andric } 1563bdd1243dSDimitry Andric 1564bdd1243dSDimitry Andric OS << '\n'; 1565bdd1243dSDimitry Andric } 1566bdd1243dSDimitry Andric 1567bdd1243dSDimitry Andric OS << " },\n"; 1568bdd1243dSDimitry Andric } 1569bdd1243dSDimitry Andric OS << " };\n assert(RC && \"Missing regclass\");\n" 1570bdd1243dSDimitry Andric << " if (!Idx) return RC;\n --Idx;\n" 1571bdd1243dSDimitry Andric << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" 1572bdd1243dSDimitry Andric << " unsigned TV = Table[RC->getID()][Idx];\n" 1573bdd1243dSDimitry Andric << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; 15740b57cec5SDimitry Andric } 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric EmitRegUnitPressure(OS, RegBank, ClassName); 15770b57cec5SDimitry Andric 1578bdd1243dSDimitry Andric // Emit register base class mapper 1579bdd1243dSDimitry Andric if (!RegisterClasses.empty()) { 1580bdd1243dSDimitry Andric // Collect base classes 1581bdd1243dSDimitry Andric SmallVector<const CodeGenRegisterClass *> BaseClasses; 1582bdd1243dSDimitry Andric for (const auto &RC : RegisterClasses) { 1583bdd1243dSDimitry Andric if (RC.getBaseClassOrder()) 1584bdd1243dSDimitry Andric BaseClasses.push_back(&RC); 1585bdd1243dSDimitry Andric } 1586bdd1243dSDimitry Andric if (!BaseClasses.empty()) { 15875f757f3fSDimitry Andric assert(BaseClasses.size() < UINT16_MAX && 15885f757f3fSDimitry Andric "Too many base register classes"); 1589bdd1243dSDimitry Andric 1590bdd1243dSDimitry Andric // Apply order 1591bdd1243dSDimitry Andric struct BaseClassOrdering { 1592*0fca6ea1SDimitry Andric bool operator()(const CodeGenRegisterClass *LHS, 1593*0fca6ea1SDimitry Andric const CodeGenRegisterClass *RHS) const { 1594*0fca6ea1SDimitry Andric return std::pair(*LHS->getBaseClassOrder(), LHS->EnumValue) < 1595*0fca6ea1SDimitry Andric std::pair(*RHS->getBaseClassOrder(), RHS->EnumValue); 1596bdd1243dSDimitry Andric } 1597bdd1243dSDimitry Andric }; 1598bdd1243dSDimitry Andric llvm::stable_sort(BaseClasses, BaseClassOrdering()); 1599bdd1243dSDimitry Andric 1600bdd1243dSDimitry Andric OS << "\n// Register to base register class mapping\n\n"; 1601bdd1243dSDimitry Andric OS << "\n"; 1602bdd1243dSDimitry Andric OS << "const TargetRegisterClass *" << ClassName 1603bdd1243dSDimitry Andric << "::getPhysRegBaseClass(MCRegister Reg)" 1604bdd1243dSDimitry Andric << " const {\n"; 16055f757f3fSDimitry Andric OS << " static const uint16_t InvalidRegClassID = UINT16_MAX;\n\n"; 16065f757f3fSDimitry Andric OS << " static const uint16_t Mapping[" << Regs.size() + 1 << "] = {\n"; 16075f757f3fSDimitry Andric OS << " InvalidRegClassID, // NoRegister\n"; 16085f757f3fSDimitry Andric for (const CodeGenRegister &Reg : Regs) { 16095f757f3fSDimitry Andric const CodeGenRegisterClass *BaseRC = nullptr; 16105f757f3fSDimitry Andric for (const CodeGenRegisterClass *RC : BaseClasses) { 16115f757f3fSDimitry Andric if (is_contained(RC->getMembers(), &Reg)) { 16125f757f3fSDimitry Andric BaseRC = RC; 16135f757f3fSDimitry Andric break; 16145f757f3fSDimitry Andric } 16155f757f3fSDimitry Andric } 16165f757f3fSDimitry Andric 16175f757f3fSDimitry Andric OS << " " 16185f757f3fSDimitry Andric << (BaseRC ? BaseRC->getQualifiedIdName() : "InvalidRegClassID") 16195f757f3fSDimitry Andric << ", // " << Reg.getName() << "\n"; 16205f757f3fSDimitry Andric } 16215f757f3fSDimitry Andric OS << " };\n\n" 16225f757f3fSDimitry Andric " assert(Reg < ArrayRef(Mapping).size());\n" 16235f757f3fSDimitry Andric " unsigned RCID = Mapping[Reg];\n" 16245f757f3fSDimitry Andric " if (RCID == InvalidRegClassID)\n" 16255f757f3fSDimitry Andric " return nullptr;\n" 16265f757f3fSDimitry Andric " return RegisterClasses[RCID];\n" 16275f757f3fSDimitry Andric "}\n"; 1628bdd1243dSDimitry Andric } 1629bdd1243dSDimitry Andric } 1630bdd1243dSDimitry Andric 16310b57cec5SDimitry Andric // Emit the constructor of the class... 16320b57cec5SDimitry Andric OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; 163306c3fb27SDimitry Andric OS << "extern const int16_t " << TargetName << "RegDiffLists[];\n"; 16340b57cec5SDimitry Andric OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n"; 16350b57cec5SDimitry Andric OS << "extern const char " << TargetName << "RegStrings[];\n"; 16360b57cec5SDimitry Andric OS << "extern const char " << TargetName << "RegClassStrings[];\n"; 16370b57cec5SDimitry Andric OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; 16380b57cec5SDimitry Andric OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; 16390b57cec5SDimitry Andric OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric EmitRegMappingTables(OS, Regs, true); 16420b57cec5SDimitry Andric 1643fe6060f1SDimitry Andric OS << ClassName << "::\n" 1644fe6060f1SDimitry Andric << ClassName 16450b57cec5SDimitry Andric << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n" 16460b57cec5SDimitry Andric " unsigned PC, unsigned HwMode)\n" 1647fe6060f1SDimitry Andric << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc" 16480b57cec5SDimitry Andric << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n" 1649*0fca6ea1SDimitry Andric << " SubRegIndexNameTable, SubRegIdxRangeTable, " 1650*0fca6ea1SDimitry Andric "SubRegIndexLaneMaskTable,\n" 16510b57cec5SDimitry Andric << " "; 16520b57cec5SDimitry Andric printMask(OS, RegBank.CoveringLanes); 16535f757f3fSDimitry Andric OS << ", RegClassInfos, VTLists, HwMode) {\n" 16540b57cec5SDimitry Andric << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 16550b57cec5SDimitry Andric << ", RA, PC,\n " << TargetName 16560b57cec5SDimitry Andric << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" 16570b57cec5SDimitry Andric << " " << TargetName << "RegUnitRoots,\n" 16580b57cec5SDimitry Andric << " " << RegBank.getNumNativeRegUnits() << ",\n" 16590b57cec5SDimitry Andric << " " << TargetName << "RegDiffLists,\n" 16600b57cec5SDimitry Andric << " " << TargetName << "LaneMaskLists,\n" 16610b57cec5SDimitry Andric << " " << TargetName << "RegStrings,\n" 16620b57cec5SDimitry Andric << " " << TargetName << "RegClassStrings,\n" 16630b57cec5SDimitry Andric << " " << TargetName << "SubRegIdxLists,\n" 16640b57cec5SDimitry Andric << " " << SubRegIndicesSize + 1 << ",\n" 16650b57cec5SDimitry Andric << " " << TargetName << "RegEncodingTable);\n\n"; 16660b57cec5SDimitry Andric 16670b57cec5SDimitry Andric EmitRegMapping(OS, Regs, true); 16680b57cec5SDimitry Andric 16690b57cec5SDimitry Andric OS << "}\n\n"; 16700b57cec5SDimitry Andric 16710b57cec5SDimitry Andric // Emit CalleeSavedRegs information. 16720b57cec5SDimitry Andric std::vector<Record *> CSRSets = 16730b57cec5SDimitry Andric Records.getAllDerivedDefinitions("CalleeSavedRegs"); 16740b57cec5SDimitry Andric for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { 16750b57cec5SDimitry Andric Record *CSRSet = CSRSets[i]; 16760b57cec5SDimitry Andric const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet); 16770b57cec5SDimitry Andric assert(Regs && "Cannot expand CalleeSavedRegs instance"); 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric // Emit the *_SaveList list of callee-saved registers. 1680*0fca6ea1SDimitry Andric OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { "; 16810b57cec5SDimitry Andric for (unsigned r = 0, re = Regs->size(); r != re; ++r) 16820b57cec5SDimitry Andric OS << getQualifiedName((*Regs)[r]) << ", "; 16830b57cec5SDimitry Andric OS << "0 };\n"; 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric // Emit the *_RegMask bit mask of call-preserved registers. 16860b57cec5SDimitry Andric BitVector Covered = RegBank.computeCoveredRegisters(*Regs); 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric // Check for an optional OtherPreserved set. 16890b57cec5SDimitry Andric // Add those registers to RegMask, but not to SaveList. 16900b57cec5SDimitry Andric if (DagInit *OPDag = 16910b57cec5SDimitry Andric dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) { 16920b57cec5SDimitry Andric SetTheory::RecSet OPSet; 16930b57cec5SDimitry Andric RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc()); 16940b57cec5SDimitry Andric Covered |= RegBank.computeCoveredRegisters( 16950b57cec5SDimitry Andric ArrayRef<Record *>(OPSet.begin(), OPSet.end())); 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 1698bdd1243dSDimitry Andric // Add all constant physical registers to the preserved mask: 1699bdd1243dSDimitry Andric SetTheory::RecSet ConstantSet; 1700bdd1243dSDimitry Andric for (auto &Reg : RegBank.getRegisters()) { 1701bdd1243dSDimitry Andric if (Reg.Constant) 1702bdd1243dSDimitry Andric ConstantSet.insert(Reg.TheDef); 1703bdd1243dSDimitry Andric } 1704bdd1243dSDimitry Andric Covered |= RegBank.computeCoveredRegisters( 1705bdd1243dSDimitry Andric ArrayRef<Record *>(ConstantSet.begin(), ConstantSet.end())); 1706bdd1243dSDimitry Andric 1707*0fca6ea1SDimitry Andric OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { "; 17080b57cec5SDimitry Andric printBitVectorAsHex(OS, Covered, 32); 17090b57cec5SDimitry Andric OS << "};\n"; 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric OS << "\n\n"; 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric OS << "ArrayRef<const uint32_t *> " << ClassName 17140b57cec5SDimitry Andric << "::getRegMasks() const {\n"; 17150b57cec5SDimitry Andric if (!CSRSets.empty()) { 17160b57cec5SDimitry Andric OS << " static const uint32_t *const Masks[] = {\n"; 17170b57cec5SDimitry Andric for (Record *CSRSet : CSRSets) 17180b57cec5SDimitry Andric OS << " " << CSRSet->getName() << "_RegMask,\n"; 17190b57cec5SDimitry Andric OS << " };\n"; 1720bdd1243dSDimitry Andric OS << " return ArrayRef(Masks);\n"; 17210b57cec5SDimitry Andric } else { 1722bdd1243dSDimitry Andric OS << " return std::nullopt;\n"; 17230b57cec5SDimitry Andric } 17240b57cec5SDimitry Andric OS << "}\n\n"; 17250b57cec5SDimitry Andric 172681ad6265SDimitry Andric const std::list<CodeGenRegisterCategory> &RegCategories = 172781ad6265SDimitry Andric RegBank.getRegCategories(); 172881ad6265SDimitry Andric OS << "bool " << ClassName << "::\n" 172981ad6265SDimitry Andric << "isGeneralPurposeRegister(const MachineFunction &MF, " 173081ad6265SDimitry Andric << "MCRegister PhysReg) const {\n" 173181ad6265SDimitry Andric << " return\n"; 173281ad6265SDimitry Andric for (const CodeGenRegisterCategory &Category : RegCategories) 173381ad6265SDimitry Andric if (Category.getName() == "GeneralPurposeRegisters") { 173481ad6265SDimitry Andric for (const CodeGenRegisterClass *RC : Category.getClasses()) 173581ad6265SDimitry Andric OS << " " << RC->getQualifiedName() 173681ad6265SDimitry Andric << "RegClass.contains(PhysReg) ||\n"; 173781ad6265SDimitry Andric break; 173881ad6265SDimitry Andric } 173981ad6265SDimitry Andric OS << " false;\n"; 174081ad6265SDimitry Andric OS << "}\n\n"; 174181ad6265SDimitry Andric 174281ad6265SDimitry Andric OS << "bool " << ClassName << "::\n" 174381ad6265SDimitry Andric << "isFixedRegister(const MachineFunction &MF, " 174481ad6265SDimitry Andric << "MCRegister PhysReg) const {\n" 174581ad6265SDimitry Andric << " return\n"; 174681ad6265SDimitry Andric for (const CodeGenRegisterCategory &Category : RegCategories) 174781ad6265SDimitry Andric if (Category.getName() == "FixedRegisters") { 174881ad6265SDimitry Andric for (const CodeGenRegisterClass *RC : Category.getClasses()) 174981ad6265SDimitry Andric OS << " " << RC->getQualifiedName() 175081ad6265SDimitry Andric << "RegClass.contains(PhysReg) ||\n"; 175181ad6265SDimitry Andric break; 175281ad6265SDimitry Andric } 175381ad6265SDimitry Andric OS << " false;\n"; 175481ad6265SDimitry Andric OS << "}\n\n"; 175581ad6265SDimitry Andric 175681ad6265SDimitry Andric OS << "bool " << ClassName << "::\n" 175781ad6265SDimitry Andric << "isArgumentRegister(const MachineFunction &MF, " 175881ad6265SDimitry Andric << "MCRegister PhysReg) const {\n" 175981ad6265SDimitry Andric << " return\n"; 176081ad6265SDimitry Andric for (const CodeGenRegisterCategory &Category : RegCategories) 176181ad6265SDimitry Andric if (Category.getName() == "ArgumentRegisters") { 176281ad6265SDimitry Andric for (const CodeGenRegisterClass *RC : Category.getClasses()) 176381ad6265SDimitry Andric OS << " " << RC->getQualifiedName() 176481ad6265SDimitry Andric << "RegClass.contains(PhysReg) ||\n"; 176581ad6265SDimitry Andric break; 176681ad6265SDimitry Andric } 176781ad6265SDimitry Andric OS << " false;\n"; 176881ad6265SDimitry Andric OS << "}\n\n"; 176981ad6265SDimitry Andric 1770bdd1243dSDimitry Andric OS << "bool " << ClassName << "::\n" 1771bdd1243dSDimitry Andric << "isConstantPhysReg(MCRegister PhysReg) const {\n" 1772bdd1243dSDimitry Andric << " return\n"; 1773bdd1243dSDimitry Andric for (const auto &Reg : Regs) 1774bdd1243dSDimitry Andric if (Reg.Constant) 1775bdd1243dSDimitry Andric OS << " PhysReg == " << getQualifiedName(Reg.TheDef) << " ||\n"; 1776bdd1243dSDimitry Andric OS << " false;\n"; 1777bdd1243dSDimitry Andric OS << "}\n\n"; 1778bdd1243dSDimitry Andric 17790b57cec5SDimitry Andric OS << "ArrayRef<const char *> " << ClassName 17800b57cec5SDimitry Andric << "::getRegMaskNames() const {\n"; 17810b57cec5SDimitry Andric if (!CSRSets.empty()) { 178281ad6265SDimitry Andric OS << " static const char *Names[] = {\n"; 17830b57cec5SDimitry Andric for (Record *CSRSet : CSRSets) 17840b57cec5SDimitry Andric OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; 17850b57cec5SDimitry Andric OS << " };\n"; 1786bdd1243dSDimitry Andric OS << " return ArrayRef(Names);\n"; 17870b57cec5SDimitry Andric } else { 1788bdd1243dSDimitry Andric OS << " return std::nullopt;\n"; 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric OS << "}\n\n"; 17910b57cec5SDimitry Andric 1792*0fca6ea1SDimitry Andric OS << "const " << TargetName << "FrameLowering *\n" 1793*0fca6ea1SDimitry Andric << TargetName 17940b57cec5SDimitry Andric << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" 17950b57cec5SDimitry Andric << " return static_cast<const " << TargetName << "FrameLowering *>(\n" 17960b57cec5SDimitry Andric << " MF.getSubtarget().getFrameLowering());\n" 17970b57cec5SDimitry Andric << "}\n\n"; 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric OS << "} // end namespace llvm\n\n"; 18000b57cec5SDimitry Andric OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; 18010b57cec5SDimitry Andric } 18020b57cec5SDimitry Andric 18030b57cec5SDimitry Andric void RegisterInfoEmitter::run(raw_ostream &OS) { 18040b57cec5SDimitry Andric CodeGenRegBank &RegBank = Target.getRegBank(); 1805e8d8bef9SDimitry Andric Records.startTimer("Print enums"); 18060b57cec5SDimitry Andric runEnums(OS, Target, RegBank); 1807e8d8bef9SDimitry Andric 1808e8d8bef9SDimitry Andric Records.startTimer("Print MC registers"); 18090b57cec5SDimitry Andric runMCDesc(OS, Target, RegBank); 1810e8d8bef9SDimitry Andric 1811e8d8bef9SDimitry Andric Records.startTimer("Print header fragment"); 18120b57cec5SDimitry Andric runTargetHeader(OS, Target, RegBank); 1813e8d8bef9SDimitry Andric 1814e8d8bef9SDimitry Andric Records.startTimer("Print target registers"); 18150b57cec5SDimitry Andric runTargetDesc(OS, Target, RegBank); 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric if (RegisterInfoDebug) 18180b57cec5SDimitry Andric debugDump(errs()); 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric void RegisterInfoEmitter::debugDump(raw_ostream &OS) { 18220b57cec5SDimitry Andric CodeGenRegBank &RegBank = Target.getRegBank(); 18230b57cec5SDimitry Andric const CodeGenHwModes &CGH = Target.getHwModes(); 18240b57cec5SDimitry Andric unsigned NumModes = CGH.getNumModeIds(); 18250b57cec5SDimitry Andric auto getModeName = [CGH](unsigned M) -> StringRef { 18260b57cec5SDimitry Andric if (M == 0) 18270b57cec5SDimitry Andric return "Default"; 18280b57cec5SDimitry Andric return CGH.getMode(M).Name; 18290b57cec5SDimitry Andric }; 18300b57cec5SDimitry Andric 18310b57cec5SDimitry Andric for (const CodeGenRegisterClass &RC : RegBank.getRegClasses()) { 18320b57cec5SDimitry Andric OS << "RegisterClass " << RC.getName() << ":\n"; 18330b57cec5SDimitry Andric OS << "\tSpillSize: {"; 18340b57cec5SDimitry Andric for (unsigned M = 0; M != NumModes; ++M) 18350b57cec5SDimitry Andric OS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillSize; 18360b57cec5SDimitry Andric OS << " }\n\tSpillAlignment: {"; 18370b57cec5SDimitry Andric for (unsigned M = 0; M != NumModes; ++M) 18380b57cec5SDimitry Andric OS << ' ' << getModeName(M) << ':' << RC.RSI.get(M).SpillAlignment; 18390b57cec5SDimitry Andric OS << " }\n\tNumRegs: " << RC.getMembers().size() << '\n'; 18400b57cec5SDimitry Andric OS << "\tLaneMask: " << PrintLaneMask(RC.LaneMask) << '\n'; 18410b57cec5SDimitry Andric OS << "\tHasDisjunctSubRegs: " << RC.HasDisjunctSubRegs << '\n'; 18420b57cec5SDimitry Andric OS << "\tCoveredBySubRegs: " << RC.CoveredBySubRegs << '\n'; 184381ad6265SDimitry Andric OS << "\tAllocatable: " << RC.Allocatable << '\n'; 184481ad6265SDimitry Andric OS << "\tAllocationPriority: " << unsigned(RC.AllocationPriority) << '\n'; 1845*0fca6ea1SDimitry Andric OS << "\tBaseClassOrder: " << RC.getBaseClassOrder() << '\n'; 18460b57cec5SDimitry Andric OS << "\tRegs:"; 18470b57cec5SDimitry Andric for (const CodeGenRegister *R : RC.getMembers()) { 18480b57cec5SDimitry Andric OS << " " << R->getName(); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric OS << '\n'; 18510b57cec5SDimitry Andric OS << "\tSubClasses:"; 18520b57cec5SDimitry Andric const BitVector &SubClasses = RC.getSubClasses(); 18530b57cec5SDimitry Andric for (const CodeGenRegisterClass &SRC : RegBank.getRegClasses()) { 18540b57cec5SDimitry Andric if (!SubClasses.test(SRC.EnumValue)) 18550b57cec5SDimitry Andric continue; 18560b57cec5SDimitry Andric OS << " " << SRC.getName(); 18570b57cec5SDimitry Andric } 18580b57cec5SDimitry Andric OS << '\n'; 18590b57cec5SDimitry Andric OS << "\tSuperClasses:"; 18600b57cec5SDimitry Andric for (const CodeGenRegisterClass *SRC : RC.getSuperClasses()) { 18610b57cec5SDimitry Andric OS << " " << SRC->getName(); 18620b57cec5SDimitry Andric } 18630b57cec5SDimitry Andric OS << '\n'; 18640b57cec5SDimitry Andric } 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric for (const CodeGenSubRegIndex &SRI : RegBank.getSubRegIndices()) { 18670b57cec5SDimitry Andric OS << "SubRegIndex " << SRI.getName() << ":\n"; 18680b57cec5SDimitry Andric OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; 18690b57cec5SDimitry Andric OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; 1870*0fca6ea1SDimitry Andric OS << "\tOffset: {"; 1871*0fca6ea1SDimitry Andric for (unsigned M = 0; M != NumModes; ++M) 1872*0fca6ea1SDimitry Andric OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Offset; 1873*0fca6ea1SDimitry Andric OS << " }\n\tSize: {"; 1874*0fca6ea1SDimitry Andric for (unsigned M = 0; M != NumModes; ++M) 1875*0fca6ea1SDimitry Andric OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Size; 1876*0fca6ea1SDimitry Andric OS << " }\n"; 18770b57cec5SDimitry Andric } 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric for (const CodeGenRegister &R : RegBank.getRegisters()) { 18800b57cec5SDimitry Andric OS << "Register " << R.getName() << ":\n"; 1881fe6060f1SDimitry Andric OS << "\tCostPerUse: "; 1882fe6060f1SDimitry Andric for (const auto &Cost : R.CostPerUse) 1883fe6060f1SDimitry Andric OS << Cost << " "; 1884fe6060f1SDimitry Andric OS << '\n'; 18850b57cec5SDimitry Andric OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n'; 18860b57cec5SDimitry Andric OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n'; 1887*0fca6ea1SDimitry Andric for (std::pair<CodeGenSubRegIndex *, CodeGenRegister *> P : 1888*0fca6ea1SDimitry Andric R.getSubRegs()) { 1889*0fca6ea1SDimitry Andric OS << "\tSubReg " << P.first->getName() << " = " << P.second->getName() 1890*0fca6ea1SDimitry Andric << '\n'; 18910b57cec5SDimitry Andric } 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 189506c3fb27SDimitry Andric static TableGen::Emitter::OptClass<RegisterInfoEmitter> 189606c3fb27SDimitry Andric X("gen-register-info", "Generate registers and register classes info"); 1897