X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FRegisterInfoEmitter.cpp;h=d7dd9e7a824b1222c2c5daf5d336b35497011acf;hp=87624665cbc142404aa2b37a558c6620f2702282;hb=156aeff2f7942d05611284ce96d76ab9db6d9f0a;hpb=ef2340ef4848065f74f9b98c5d392028392d7cae diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 87624665cbc..d7dd9e7a824 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -53,27 +53,30 @@ public: void run(raw_ostream &o); private: - void EmitRegMapping(raw_ostream &o, - const std::vector &Regs, bool isCtor); + void EmitRegMapping(raw_ostream &o, const std::deque &Regs, + bool isCtor); void EmitRegMappingTables(raw_ostream &o, - const std::vector &Regs, + const std::deque &Regs, bool isCtor); - void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target); - void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName); + void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, + const std::string &ClassName); + void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, + const std::string &ClassName); }; } // End anonymous namespace // runEnums - Print out enum values for all of the registers. void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &Bank) { - const std::vector &Registers = Bank.getRegisters(); + const auto &Registers = Bank.getRegisters(); // Register enums are stored as uint16_t in the tables. Make sure we'll fit. assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); - std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = + Registers.front().TheDef->getValueAsString("Namespace"); emitSourceFileHeader("Target Register Enum Values", OS); @@ -90,17 +93,16 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoRegister,\n"; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i]->getName() << " = " << - Registers[i]->EnumValue << ",\n"; - assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + for (const auto &Reg : Registers) + OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; + assert(Registers.size() == Registers.back().EnumValue && "Register enum value mismatch!"); OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) OS << "}\n"; - ArrayRef RegisterClasses = Bank.getRegClasses(); + const auto &RegisterClasses = Bank.getRegClasses(); if (!RegisterClasses.empty()) { // RegisterClass enums are stored as uint16_t in the tables. @@ -111,17 +113,15 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (i) OS << ",\n"; - OS << " " << RegisterClasses[i]->getName() << "RegClassID"; - OS << " = " << i; - } + for (const auto &RC : RegisterClasses) + OS << " " << RC.getName() << "RegClassID" + << " = " << RC.EnumValue << ",\n"; OS << "\n };\n"; if (!Namespace.empty()) OS << "}\n"; } - const std::vector RegAltNameIndices = Target.getRegAltNameIndices(); + const std::vector &RegAltNameIndices = Target.getRegAltNameIndices(); // If the only definition is the default NoRegAltName, we don't need to // emit anything. if (RegAltNameIndices.size() > 1) { @@ -137,25 +137,38 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "}\n"; } - ArrayRef SubRegIndices = Bank.getSubRegIndices(); + auto &SubRegIndices = Bank.getSubRegIndices(); if (!SubRegIndices.empty()) { OS << "\n// Subregister indices\n"; - std::string Namespace = - SubRegIndices[0]->getNamespace(); + std::string Namespace = SubRegIndices.front().getNamespace(); if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + unsigned i = 0; + for (const auto &Idx : SubRegIndices) + OS << " " << Idx.getName() << ",\t// " << ++i << "\n"; OS << " NUM_TARGET_SUBREGS\n};\n"; if (!Namespace.empty()) OS << "}\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_ENUM\n\n"; } +static void printInt(raw_ostream &OS, int Val) { + OS << Val; +} + +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + void RegisterInfoEmitter:: EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName) { @@ -166,9 +179,8 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "const RegClassWeight &" << ClassName << "::\n" << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" << " static const RegClassWeight RCWeightTable[] = {\n"; - for (unsigned i = 0, e = NumRCs; i != e; ++i) { - const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; - const CodeGenRegister::Set &Regs = RC.getMembers(); + for (const auto &RC : RegBank.getRegClasses()) { + const CodeGenRegister::Vec &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; else { @@ -179,10 +191,40 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, } OS << "}, \t// " << RC.getName() << "\n"; } - OS << " {0, 0} };\n" + OS << " };\n" << " return RCWeightTable[RC->getID()];\n" << "}\n\n"; + // Reasonable targets (not ARMv7) have unit weight for all units, so don't + // bother generating a table. + bool RegUnitsHaveUnitWeight = true; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + if (RegBank.getRegUnit(UnitIdx).Weight > 1) + RegUnitsHaveUnitWeight = false; + } + OS << "/// Get the weight in units of pressure for this register unit.\n" + << "unsigned " << ClassName << "::\n" + << "getRegUnitWeight(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + if (!RegUnitsHaveUnitWeight) { + OS << " static const uint8_t RUWeightTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + const RegUnit &RU = RegBank.getRegUnit(UnitIdx); + assert(RU.Weight < 256 && "RegUnit too heavy"); + OS << RU.Weight << ", "; + } + OS << "};\n" + << " return RUWeightTable[RegUnit];\n"; + } + else { + OS << " // All register units have unit weight.\n" + << " return 1;\n"; + } + OS << "}\n\n"; + OS << "\n" << "// Get the number of dimensions of register pressure.\n" << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" @@ -191,69 +233,100 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, OS << "// Get the name of this register unit pressure set.\n" << "const char *" << ClassName << "::\n" << "getRegPressureSetName(unsigned Idx) const {\n" - << " static const char *PressureNameTable[] = {\n"; + << " static const char *const PressureNameTable[] = {\n"; + unsigned MaxRegUnitWeight = 0; for (unsigned i = 0; i < NumSets; ++i ) { - OS << " \"" << RegBank.getRegPressureSet(i).Name << "\",\n"; + const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); + MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); + OS << " \"" << RegUnits.Name << "\",\n"; } - OS << " 0 };\n" + OS << " nullptr };\n" << " return PressureNameTable[Idx];\n" << "}\n\n"; OS << "// Get the register unit pressure limit for this dimension.\n" << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" - << "getRegPressureSetLimit(unsigned Idx) const {\n" - << " static const unsigned PressureLimitTable[] = {\n"; + << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n" + << " static const " << getMinimalTypeForRange(MaxRegUnitWeight) + << " PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { - const RegUnitSet &RegUnits = RegBank.getRegPressureSet(i); - OS << " " << RegBank.getRegUnitSetWeight(RegUnits.Units) - << ", \t// " << i << ": " << RegUnits.Name << "\n"; + const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); + OS << " " << RegUnits.Weight << ", \t// " << i << ": " + << RegUnits.Name << "\n"; } - OS << " 0 };\n" + OS << " };\n" << " return PressureLimitTable[Idx];\n" << "}\n\n"; - OS << "/// Get the dimensions of register pressure " - << "impacted by this register class.\n" - << "/// Returns a -1 terminated array of pressure set IDs\n" - << "const int* " << ClassName << "::\n" - << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n" - << " static const int RCSetsTable[] = {\n "; - std::vector RCSetStarts(NumRCs); - for (unsigned i = 0, StartIdx = 0, e = NumRCs; i != e; ++i) { - RCSetStarts[i] = StartIdx; + SequenceToOffsetTable> PSetsSeqs; + + // This table may be larger than NumRCs if some register units needed a list + // of unit sets that did not correspond to a register class. + unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); + std::vector> PSets(NumRCUnitSets); + + for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { ArrayRef PSetIDs = RegBank.getRCPressureSetIDs(i); + PSets[i].reserve(PSetIDs.size()); for (ArrayRef::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - OS << *PSetI << ", "; - ++StartIdx; + PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order); } - OS << "-1, \t// " << RegBank.getRegClasses()[i]->getName() << "\n "; - ++StartIdx; + std::sort(PSets[i].begin(), PSets[i].end()); + PSetsSeqs.add(PSets[i]); } - OS << "-1 };\n"; - OS << " static const unsigned RCSetStartTable[] = {\n "; + + PSetsSeqs.layout(); + + OS << "/// Table of pressure sets per register class or unit.\n" + << "static const int RCSetsTable[] = {\n"; + PSetsSeqs.emit(OS, printInt, "-1"); + OS << "};\n\n"; + + OS << "/// Get the dimensions of register pressure impacted by this " + << "register class.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { - OS << RCSetStarts[i] << ","; + OS << PSetsSeqs.get(PSets[i]) << ","; } - OS << "0 };\n" - << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" - << " return &RCSetsTable[SetListStart];\n" + OS << "};\n" + << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" + << "}\n\n"; + + OS << "/// Get the dimensions of register pressure impacted by this " + << "register unit.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegUnitPressureSets(unsigned RegUnit) const {\n" + << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() + << " && \"invalid register unit\");\n"; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RUSetStartTable[] = {\n "; + for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); + UnitIdx < UnitEnd; ++UnitIdx) { + OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) + << ","; + } + OS << "};\n" + << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" << "}\n\n"; } -void -RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMappingTables( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Collect all information about dwarf register numbers - typedef std::map, LessRecord> DwarfRegNumsMapTy; + typedef std::map, LessRecordRegister> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; // First, just pull all provided information to the map unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; std::vector RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); maxLength = std::max((size_t)maxLength, RegNums.size()); if (DwarfRegNums.count(Reg)) @@ -271,7 +344,7 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; @@ -311,21 +384,21 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; if (!isCtor) - OS << " = sizeof(" << Namespace + OS << " = array_lengthof(" << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + << "Dwarf2L);\n\n"; else OS << ";\n\n"; } } - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; const RecordVal *V = Reg->getValue("DwarfAlias"); if (!V || !V->getValue()) continue; - DefInit *DI = dynamic_cast(V->getValue()); + DefInit *DI = cast(V->getValue()); Record *Alias = DI->getDef(); DwarfRegNums[Reg] = DwarfRegNums[Alias]; } @@ -359,24 +432,21 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; if (!isCtor) - OS << " = sizeof(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + OS << " = array_lengthof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; else OS << ";\n\n"; } } } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMapping( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Emit the initializer so the tables from EmitRegMappingTables get wired up // to the MCRegisterInfo object. unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; maxLength = std::max((size_t)maxLength, Reg->getValueAsListOfInts("DwarfNumbers").size()); } @@ -384,7 +454,7 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, if (!maxLength) return; - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); // Emit reverse information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { @@ -498,15 +568,16 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { // 0 differential which means we can't encode repeated elements. typedef SmallVector DiffVec; +typedef SmallVector MaskVec; // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. static -DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef List) { +DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) { assert(V.empty() && "Clear DiffVec before diffEncode."); uint16_t Val = uint16_t(InitVal); - for (unsigned i = 0; i != List.size(); ++i) { - uint16_t Cur = List[i]; + + for (uint16_t Cur : List) { V.push_back(Cur - Val); Val = Cur; } @@ -530,6 +601,181 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) { OS << Val; } +static void printMask(raw_ostream &OS, unsigned Val) { + OS << format("0x%08X", Val); +} + +// Try to combine Idx's compose map into Vec if it is compatible. +// Return false if it's not possible. +static bool combine(const CodeGenSubRegIndex *Idx, + SmallVectorImpl &Vec) { + const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites(); + for (const auto &I : Map) { + CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1]; + if (Entry && Entry != I.second) + return false; + } + + // All entries are compatible. Make it so. + for (const auto &I : Map) { + auto *&Entry = Vec[I.first->EnumValue - 1]; + assert((!Entry || Entry == I.second) && + "Expected EnumValue to be unique"); + Entry = I.second; + } + return true; +} + +void +RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, + CodeGenRegBank &RegBank, + const std::string &ClName) { + const auto &SubRegIndices = RegBank.getSubRegIndices(); + OS << "unsigned " << ClName + << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; + + // Many sub-register indexes are composition-compatible, meaning that + // + // compose(IdxA, IdxB) == compose(IdxA', IdxB) + // + // for many IdxA, IdxA' pairs. Not all sub-register indexes can be composed. + // The illegal entries can be use as wildcards to compress the table further. + + // Map each Sub-register index to a compatible table row. + SmallVector RowMap; + SmallVector, 4> Rows; + + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + for (const auto &Idx : SubRegIndices) { + unsigned Found = ~0u; + for (unsigned r = 0, re = Rows.size(); r != re; ++r) { + if (combine(&Idx, Rows[r])) { + Found = r; + break; + } + } + if (Found == ~0u) { + Found = Rows.size(); + Rows.resize(Found + 1); + Rows.back().resize(SubRegIndicesSize); + combine(&Idx, Rows.back()); + } + RowMap.push_back(Found); + } + + // Output the row map if there is multiple rows. + if (Rows.size() > 1) { + OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap[" + << SubRegIndicesSize << "] = {\n "; + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) + OS << RowMap[i] << ", "; + OS << "\n };\n"; + } + + // Output the rows. + OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1) + << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (unsigned r = 0, re = Rows.size(); r != re; ++r) { + OS << " { "; + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) + if (Rows[r][i]) + OS << Rows[r][i]->EnumValue << ", "; + else + OS << "0, "; + OS << "},\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << ");\n" + << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; + if (Rows.size() > 1) + OS << " return Rows[RowMap[IdxA]][IdxB];\n"; + else + OS << " return Rows[0][IdxB];\n"; + OS << "}\n\n"; +} + +void +RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, + CodeGenRegBank &RegBank, + const std::string &ClName) { + // See the comments in computeSubRegLaneMasks() for our goal here. + const auto &SubRegIndices = RegBank.getSubRegIndices(); + + // Create a list of Mask+Rotate operations, with equivalent entries merged. + SmallVector SubReg2SequenceIndexMap; + SmallVector, 4> Sequences; + for (const auto &Idx : SubRegIndices) { + const SmallVector &IdxSequence + = Idx.CompositionLaneMaskTransform; + + unsigned Found = ~0u; + unsigned SIdx = 0; + unsigned NextSIdx; + for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { + SmallVectorImpl &Sequence = Sequences[s]; + NextSIdx = SIdx + Sequence.size() + 1; + if (Sequence == IdxSequence) { + Found = SIdx; + break; + } + } + if (Found == ~0u) { + Sequences.push_back(IdxSequence); + Found = SIdx; + } + SubReg2SequenceIndexMap.push_back(Found); + } + + OS << "unsigned " << ClName + << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)" + " const {\n"; + + OS << " struct MaskRolOp {\n" + " unsigned Mask;\n" + " uint8_t RotateLeft;\n" + " };\n" + " static const MaskRolOp Seqs[] = {\n"; + unsigned Idx = 0; + for (size_t s = 0, se = Sequences.size(); s != se; ++s) { + OS << " "; + const SmallVectorImpl &Sequence = Sequences[s]; + for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { + const MaskRolPair &P = Sequence[p]; + OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft); + } + OS << "{ 0, 0 }"; + if (s+1 != se) + OS << ", "; + OS << " // Sequence " << Idx << "\n"; + Idx += Sequence.size() + 1; + } + OS << " };\n" + " static const MaskRolOp *const CompositeSequences[] = {\n"; + for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { + OS << " "; + unsigned Idx = SubReg2SequenceIndexMap[i]; + OS << format("&Seqs[%u]", Idx); + if (i+1 != e) + OS << ","; + OS << " // to " << SubRegIndices[i].getName() << "\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() + << " && \"Subregister index out of bounds\");\n" + " unsigned Result = 0;\n" + " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)" + " {\n" + " unsigned Masked = LaneMask & Ops->Mask;\n" + " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n" + " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n" + " }\n" + " return Result;\n" + "}\n"; +} + // // runMCDesc - Print out MC register descriptions. // @@ -541,61 +787,56 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; - const std::vector &Regs = RegBank.getRegisters(); + const auto &Regs = RegBank.getRegisters(); - // The lists of sub-registers, super-registers, and overlaps all go in the - // same array. That allows us to share suffixes. + auto &SubRegIndices = RegBank.getSubRegIndices(); + // The lists of sub-registers and super-registers go in the same array. That + // allows us to share suffixes. typedef std::vector RegVec; // Differentially encoded lists. SequenceToOffsetTable DiffSeqs; SmallVector SubRegLists(Regs.size()); SmallVector SuperRegLists(Regs.size()); - SmallVector OverlapLists(Regs.size()); SmallVector RegUnitLists(Regs.size()); SmallVector RegUnitInitScale(Regs.size()); + // List of lane masks accompanying register unit sequences. + SequenceToOffsetTable LaneMaskSeqs; + SmallVector RegUnitLaneMasks(Regs.size()); + // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector SubRegIdxVec; - SequenceToOffsetTable SubRegIdxSeqs; + SequenceToOffsetTable> SubRegIdxSeqs; SmallVector SubRegIdxLists(Regs.size()); SequenceToOffsetTable RegStrings; // Precompute register lists for the SequenceToOffsetTable. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - - RegStrings.add(Reg->getName()); + unsigned i = 0; + for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) { + const auto &Reg = *I; + RegStrings.add(Reg.getName()); // Compute the ordered sub-register list. SetVector SR; - Reg->addSubRegsPreOrder(SR, RegBank); - diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); + Reg.addSubRegsPreOrder(SR, RegBank); + diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) - SRIs.push_back(Reg->getSubRegIndex(SR[j])); + SRIs.push_back(Reg.getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. - const RegVec &SuperRegList = Reg->getSuperRegs(); - diffEncode(SuperRegLists[i], Reg->EnumValue, - SuperRegList.begin(), SuperRegList.end()); + const RegVec &SuperRegList = Reg.getSuperRegs(); + diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(), + SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); - // The list of overlaps doesn't need to have any particular order, and Reg - // itself must be omitted. - DiffVec &OverlapList = OverlapLists[i]; - CodeGenRegister::Set OSet; - Reg->computeOverlaps(OSet, RegBank); - OSet.erase(Reg); - diffEncode(OverlapList, Reg->EnumValue, OSet.begin(), OSet.end()); - DiffSeqs.add(OverlapList); - // Differentially encode the register unit list, seeded by register number. // First compute a scale factor that allows more diff-lists to be reused: // @@ -608,22 +849,36 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; - ArrayRef RUs = Reg->getNativeRegUnits(); - if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) - ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); - if (i+1 != Regs.size() && - Regs[i+1]->getNativeRegUnits().size() == RUs.size()) - ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); + SparseBitVector<> RUs = Reg.getNativeRegUnits(); + if (I != Regs.begin() && + std::prev(I)->getNativeRegUnits().count() == RUs.count()) + ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin(); + if (std::next(I) != Regs.end() && + std::next(I)->getNativeRegUnits().count() == RUs.count()) + ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; - DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); + DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs)); + + const auto &RUMasks = Reg.getRegUnitLaneMasks(); + MaskVec &LaneMaskVec = RegUnitLaneMasks[i]; + assert(LaneMaskVec.empty()); + LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end()); + // Terminator mask should not be used inside of the list. +#ifndef NDEBUG + for (unsigned M : LaneMaskVec) { + assert(M != ~0u && "terminator mask should not be part of the list"); + } +#endif + LaneMaskSeqs.add(LaneMaskVec); } // Compute the final layout of the sequence table. DiffSeqs.layout(); + LaneMaskSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; @@ -631,15 +886,30 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, const std::string &TargetName = Target.getName(); // Emit the shared table of differential lists. - OS << "extern const uint16_t " << TargetName << "RegDiffLists[] = {\n"; + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n"; DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; + // Emit the shared table of regunit lane mask sequences. + OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n"; + LaneMaskSeqs.emit(OS, printMask, "~0u"); + OS << "};\n\n"; + // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; + // Emit the table of sub-register index sizes. + OS << "extern const MCRegisterInfo::SubRegCoveredBits " + << TargetName << "SubRegIdxRanges[] = {\n"; + OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; + for (const auto &Idx : SubRegIndices) { + OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " + << Idx.getName() << "\n"; + } + OS << "};\n\n"; + // Emit the string table. RegStrings.layout(); OS << "extern const char " << TargetName << "RegStrings[] = {\n"; @@ -651,20 +921,20 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; // Emit the register descriptors now. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - OS << " { " << RegStrings.get(Reg->getName()) << ", " - << DiffSeqs.get(OverlapLists[i]) << ", " - << DiffSeqs.get(SubRegLists[i]) << ", " - << DiffSeqs.get(SuperRegLists[i]) << ", " - << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " - << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; + i = 0; + for (const auto &Reg : Regs) { + OS << " { " << RegStrings.get(Reg.getName()) << ", " + << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) + << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " + << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", " + << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n"; + ++i; } OS << "};\n\n"; // End of register descriptors... // Emit the table of register unit roots. Each regunit has one or two root // registers. - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); @@ -676,22 +946,25 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; + SequenceToOffsetTable RegClassStrings; + // Emit the register enum value arrays for each RegisterClass - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); + RegClassStrings.add(Name); + // Emit the register list now. OS << " // " << Name << " Register Class...\n" - << " const uint16_t " << Name + << " const MCPhysReg " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; @@ -713,20 +986,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + RegClassStrings.layout(); + OS << "extern const char " << TargetName << "RegClassStrings[] = {\n"; + RegClassStrings.emit(OS, printChar); + OS << "};\n\n"; + OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; - + for (const auto &RC : RegisterClasses) { // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); - OS << " { " << '\"' << RC.getName() << "\", " - << RC.getName() << ", " << RC.getName() << "Bits, " + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " @@ -737,8 +1013,6 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n\n"; - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); - EmitRegMappingTables(OS, Regs, false); // Emit Reg encoding table @@ -746,13 +1020,13 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (const auto &RE : Regs) { + Record *Reg = RE.TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { - if (BitInit *B = dynamic_cast(BI->getBit(b))) - Value |= (uint64_t)B->getValue() << b; + if (BitInit *B = dyn_cast(BI->getBit(b))) + Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } @@ -761,23 +1035,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n" + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " + "{\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ", " - << TargetName << "RegUnitRoots, " - << RegBank.getNumNativeRegUnits() << ", " - << TargetName << "RegDiffLists, " - << TargetName << "RegStrings, " - << TargetName << "SubRegIdxLists, " - << (SubRegIndices.size() + 1) << ",\n" - << " " << TargetName << "RegEncodingTable);\n\n"; + << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " + << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " + << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " + << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " + << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" + << TargetName << "SubRegIdxRanges, " << TargetName + << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } @@ -796,33 +1070,44 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "namespace llvm {\n\n"; + OS << "class " << TargetName << "FrameLowering;\n\n"; + OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n" - << " virtual bool needsStackRealignment(const MachineFunction &) const\n" - << " { return false; }\n"; + << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n"; if (!RegBank.getSubRegIndices().empty()) { - OS << " virtual unsigned composeSubRegIndices(unsigned, unsigned) const;\n" - << " virtual const TargetRegisterClass *" - "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"; + OS << " unsigned composeSubRegIndicesImpl" + << "(unsigned, unsigned) const override;\n" + << " unsigned composeSubRegIndexLaneMaskImpl" + << "(unsigned, unsigned) const override;\n" + << " const TargetRegisterClass *getSubClassWithSubReg" + << "(const TargetRegisterClass*, unsigned) const override;\n"; } - OS << " virtual const RegClassWeight &getRegClassWeight(" - << "const TargetRegisterClass *RC) const;\n" - << " virtual unsigned getNumRegPressureSets() const;\n" - << " virtual const char *getRegPressureSetName(unsigned Idx) const;\n" - << " virtual unsigned getRegPressureSetLimit(unsigned Idx) const;\n" - << " virtual const int *getRegClassPressureSets(" - << "const TargetRegisterClass *RC) const;\n" + OS << " const RegClassWeight &getRegClassWeight(" + << "const TargetRegisterClass *RC) const override;\n" + << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" + << " unsigned getNumRegPressureSets() const override;\n" + << " const char *getRegPressureSetName(unsigned Idx) const override;\n" + << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " + "Idx) const override;\n" + << " const int *getRegClassPressureSets(" + << "const TargetRegisterClass *RC) const override;\n" + << " const int *getRegUnitPressureSets(" + << "unsigned RegUnit) const override;\n" + << " ArrayRef getRegMaskNames() const override;\n" + << " ArrayRef getRegMasks() const override;\n" + << " /// Devirtualized TargetFrameLowering.\n" + << " static const " << TargetName << "FrameLowering *getFrameLowering(\n" + << " const MachineFunction &MF);\n" << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "namespace " << RegisterClasses.front().Namespace << " { // Register classes\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { const std::string &Name = RC.getName(); // Output the extern for the instance. @@ -830,7 +1115,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, } OS << "} // end of namespace " << TargetName << "\n\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_HEADER\n\n"; } @@ -852,15 +1137,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. - ArrayRef RegisterClasses = RegBank.getRegClasses(); - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + const auto &RegisterClasses = RegBank.getRegClasses(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); // Collect all registers belonging to any allocatable class. std::set AllocatableRegs; // Collect allocatable registers. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); if (RC.Allocatable) @@ -868,9 +1152,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } // Build a shared array of value types. - SequenceToOffsetTable > VTSeqs; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) - VTSeqs.add(RegisterClasses[rc]->VTs); + SequenceToOffsetTable > VTSeqs; + for (const auto &RC : RegisterClasses) + VTSeqs.add(RC.VTs); VTSeqs.layout(); OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); @@ -878,18 +1162,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit SubRegIndex names, skipping 0. OS << "\nstatic const char *const SubRegIndexNameTable[] = { \""; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << SubRegIndices[i]->getName(); - if (i + 1 != e) - OS << "\", \""; + + for (const auto &Idx : SubRegIndices) { + OS << Idx.getName(); + OS << "\", \""; } OS << "\" };\n\n"; // Emit SubRegIndex lane masks, including 0. OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask) - << SubRegIndices[i]->getName() << '\n'; + for (const auto &Idx : SubRegIndices) { + OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n'; } OS << " };\n\n"; @@ -898,7 +1181,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { OS << "\nstatic const TargetRegisterClass *const " - << "NullRegClasses[] = { NULL };\n\n"; + << "NullRegClasses[] = { nullptr };\n\n"; // Emit register class bit mask tables. The first bit mask emitted for a // register class, RC, is the set of sub-classes, including RC itself. @@ -921,27 +1204,25 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Compress the sub-reg index lists. typedef std::vector IdxList; SmallVector SuperRegIdxLists(RegisterClasses.size()); - SequenceToOffsetTable SuperRegIdxSeqs; + SequenceToOffsetTable> SuperRegIdxSeqs; BitVector MaskBV(RegisterClasses.size()); - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); // Emit super-reg class masks for any relevant SubRegIndices that can // project into RC. - IdxList &SRIList = SuperRegIdxLists[rc]; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; + for (auto &Idx : SubRegIndices) { MaskBV.reset(); - RC.getSuperRegClasses(Idx, MaskBV); + RC.getSuperRegClasses(&Idx, MaskBV); if (MaskBV.none()) continue; - SRIList.push_back(Idx); + SRIList.push_back(&Idx); OS << "\n "; printBitVectorAsHex(OS, MaskBV, 32); - OS << "// " << Idx->getName(); + OS << "// " << Idx.getName(); } SuperRegIdxSeqs.add(SRIList); OS << "\n};\n\n"; @@ -953,8 +1234,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n\n"; // Emit NULL terminated super-class lists. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. @@ -963,24 +1243,23 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; - for (unsigned i = 0; i != Supers.size(); ++i) - OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; - OS << " NULL\n};\n\n"; + for (const auto *Super : Supers) + OS << " &" << Super->getQualifiedName() << "RegClass,\n"; + OS << " nullptr\n};\n\n"; } // Emit methods. - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect << "}\n\n" - << "static ArrayRef " << RC.getName() + << "static ArrayRef " << RC.getName() << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { ArrayRef Elems = RC.getOrder(oi); if (!Elems.empty()) { - OS << " static const uint16_t AltOrder" << oi << "[] = {"; + OS << " static const MCPhysReg AltOrder" << oi << "[] = {"; for (unsigned elem = 0; elem != Elems.size(); ++elem) OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); OS << " };\n"; @@ -988,38 +1267,40 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << " const MCRegisterClass &MCR = " << Target.getName() << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" - << " const ArrayRef Order[] = {\n" + << " const ArrayRef Order[] = {\n" << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) if (RC.getOrder(oi).empty()) - OS << "),\n ArrayRef("; + OS << "),\n ArrayRef("; else OS << "),\n makeArrayRef(AltOrder" << oi; OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; - } + } } // Now emit the actual value-initialized register class instances. - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "\nnamespace " << RegisterClasses.front().Namespace << " { // Register class instances\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; - OS << " extern const TargetRegisterClass " - << RegisterClasses[i]->getName() << "RegClass = {\n " - << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() - << "RegClassID],\n " - << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " - << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " - << SuperRegIdxSeqs.get(SuperRegIdxLists[i]) << ",\n "; + for (const auto &RC : RegisterClasses) { + OS << " extern const TargetRegisterClass " << RC.getName() + << "RegClass = {\n " << '&' << Target.getName() + << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " + << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() + << "SubClassMask,\n SuperRegIdxSeqs + " + << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n " + << format("0x%08x,\n ", RC.LaneMask) + << (unsigned)RC.AllocationPriority << ",\n " + << (RC.HasDisjunctSubRegs?"true":"false") + << ", /* HasDisjunctSubRegs */\n "; if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else OS << RC.getName() << "Superclasses,\n "; if (RC.AltOrderSelect.empty()) - OS << "0\n"; + OS << "nullptr\n"; else OS << RC.getName() << "GetRawAllocationOrder\n"; OS << " };\n\n"; @@ -1030,9 +1311,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) - OS << " &" << RegisterClasses[i]->getQualifiedName() - << "RegClass,\n"; + for (const auto &RC : RegisterClasses) + OS << " &" << RC.getQualifiedName() << "RegClass,\n"; OS << " };\n"; OS << "}\n"; // End of anonymous namespace... @@ -1042,9 +1322,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; OS << " { 0, 0 },\n"; - const std::vector &Regs = RegBank.getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; + const auto &Regs = RegBank.getRegisters(); + for (const auto &Reg : Regs) { OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; @@ -1054,30 +1333,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, std::string ClassName = Target.getName() + "GenRegisterInfo"; - // Emit composeSubRegIndices + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + if (!SubRegIndices.empty()) { - OS << "unsigned " << ClassName - << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" - << " switch (IdxA) {\n" - << " default:\n return IdxB;\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - bool Open = false; - for (unsigned j = 0; j != e; ++j) { - CodeGenSubRegIndex *Comp = SubRegIndices[i]->compose(SubRegIndices[j]); - if (Comp && Comp != SubRegIndices[j]) { - if (!Open) { - OS << " case " << SubRegIndices[i]->getQualifiedName() - << ": switch(IdxB) {\n default: return IdxB;\n"; - Open = true; - } - OS << " case " << SubRegIndices[j]->getQualifiedName() - << ": return " << Comp->getQualifiedName() << ";\n"; - } - } - if (Open) - OS << " }\n"; - } - OS << " }\n}\n\n"; + emitComposeSubRegIndices(OS, RegBank, ClassName); + emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName); } // Emit getSubClassWithSubReg. @@ -1092,54 +1353,61 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, else if (RegisterClasses.size() < UINT16_MAX) OS << " static const uint16_t Table["; else - throw "Too many register classes."; - OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; - for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { - const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + PrintFatalError("Too many register classes."); + OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (const auto &RC : RegisterClasses) { OS << " {\t// " << RC.getName() << "\n"; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; - if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) - OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() + for (auto &Idx : SubRegIndices) { + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() << " -> " << SRC->getName() << "\n"; else - OS << " 0,\t// " << Idx->getName() << "\n"; + OS << " 0,\t// " << Idx.getName() << "\n"; } OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" - << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" - << " return TV ? getRegClass(TV - 1) : 0;\n}\n\n"; + << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; } EmitRegUnitPressure(OS, RegBank, ClassName); // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; - OS << "extern const uint16_t " << TargetName << "RegDiffLists[];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; + OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n"; + OS << "extern const char " << TargetName << "RegClassStrings[];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; + OS << "extern const MCRegisterInfo::SubRegCoveredBits " + << TargetName << "SubRegIdxRanges[];\n"; OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; EmitRegMappingTables(OS, Regs, true); OS << ClassName << "::\n" << ClassName - << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" + << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexNameTable, SubRegIndexLaneMaskTable) {\n" - << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA,\n " << TargetName + << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x"; + OS.write_hex(RegBank.CoveringLanes); + OS << ") {\n" + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 + << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" + << " " << TargetName << "LaneMaskLists,\n" << " " << TargetName << "RegStrings,\n" + << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" - << " " << SubRegIndices.size() + 1 << ",\n" + << " " << SubRegIndicesSize + 1 << ",\n" + << " " << TargetName << "SubRegIdxRanges,\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, true); @@ -1156,21 +1424,65 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, assert(Regs && "Cannot expand CalleeSavedRegs instance"); // Emit the *_SaveList list of callee-saved registers. - OS << "static const uint16_t " << CSRSet->getName() + OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { "; for (unsigned r = 0, re = Regs->size(); r != re; ++r) OS << getQualifiedName((*Regs)[r]) << ", "; OS << "0 };\n"; // Emit the *_RegMask bit mask of call-preserved registers. + BitVector Covered = RegBank.computeCoveredRegisters(*Regs); + + // Check for an optional OtherPreserved set. + // Add those registers to RegMask, but not to SaveList. + if (DagInit *OPDag = + dyn_cast(CSRSet->getValueInit("OtherPreserved"))) { + SetTheory::RecSet OPSet; + RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc()); + Covered |= RegBank.computeCoveredRegisters( + ArrayRef(OPSet.begin(), OPSet.end())); + } + OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { "; - printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32); + printBitVectorAsHex(OS, Covered, 32); OS << "};\n"; } OS << "\n\n"; - OS << "} // End llvm namespace \n"; + OS << "ArrayRef " << ClassName + << "::getRegMasks() const {\n"; + if (!CSRSets.empty()) { + OS << " static const uint32_t *const Masks[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << CSRSet->getName() << "_RegMask,\n"; + OS << " };\n"; + OS << " return makeArrayRef(Masks);\n"; + } else { + OS << " return None;\n"; + } + OS << "}\n\n"; + + OS << "ArrayRef " << ClassName + << "::getRegMaskNames() const {\n"; + if (!CSRSets.empty()) { + OS << " static const char *const Names[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; + OS << " };\n"; + OS << " return makeArrayRef(Names);\n"; + } else { + OS << " return None;\n"; + } + OS << "}\n\n"; + + OS << "const " << TargetName << "FrameLowering *\n" << TargetName + << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" + << " return static_cast(\n" + << " MF.getSubtarget().getFrameLowering());\n" + << "}\n\n"; + + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; }