Index: include/llvm/CodeGen/TargetRegisterInfo.h =================================================================== --- include/llvm/CodeGen/TargetRegisterInfo.h +++ include/llvm/CodeGen/TargetRegisterInfo.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_TARGETREGISTERINFO_H #define LLVM_CODEGEN_TARGETREGISTERINFO_H +#include "llvm/HwMode.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -234,7 +235,6 @@ regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses LaneBitmask CoveringLanes; const RegClassInfo *const RCInfos; - unsigned HwMode; protected: TargetRegisterInfo(const TargetRegisterInfoDesc *ID, @@ -244,7 +244,7 @@ const LaneBitmask *SRILaneMasks, LaneBitmask CoveringLanes, const RegClassInfo *const RSI, - unsigned Mode = 0); + HwMode Mode = HwMode()); virtual ~TargetRegisterInfo(); public: @@ -662,7 +662,7 @@ // protected: const RegClassInfo &getRegClassInfo(const TargetRegisterClass &RC) const { - return RCInfos[getNumRegClasses() * HwMode + RC.getID()]; + return RCInfos[getNumRegClasses() * hwMode.get() + RC.getID()]; } public: Index: include/llvm/CodeGen/TargetSubtargetInfo.h =================================================================== --- include/llvm/CodeGen/TargetSubtargetInfo.h +++ include/llvm/CodeGen/TargetSubtargetInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_TARGETSUBTARGETINFO_H #define LLVM_CODEGEN_TARGETSUBTARGETINFO_H +#include "llvm/HwMode.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -110,8 +111,6 @@ return nullptr; } - virtual unsigned getHwMode() const { return 0; } - /// Target can subclass this hook to select a different DAG scheduler. virtual RegisterScheduler::FunctionPassCtor getDAGScheduler(CodeGenOpt::Level) const { Index: include/llvm/HwMode.h =================================================================== --- /dev/null +++ include/llvm/HwMode.h @@ -0,0 +1,39 @@ +//===--------- HwMode.h - Hardware modes class ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file contais a definition of HwMode which is used for +// parameterized register class information +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_HWMODE_H_ +#define LLVM_HWMODE_H_ + +#include +#include +#include + +namespace llvm { + + typedef std::map > HwModeList; + + struct HwMode { + std::map hwModesByType; + unsigned get(std::string Type = "default") const { + auto it = hwModesByType.find(Type); + if (it == hwModesByType.end()) + return 0; + return it->second; + } + }; + +} // namespace llvm + +#endif /* LLVM_HWMODE_H_ */ + Index: include/llvm/MC/MCRegisterInfo.h =================================================================== --- include/llvm/MC/MCRegisterInfo.h +++ include/llvm/MC/MCRegisterInfo.h @@ -16,6 +16,7 @@ #ifndef LLVM_MC_MCREGISTERINFO_H #define LLVM_MC_MCREGISTERINFO_H +#include "llvm/HwMode.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/MC/LaneBitmask.h" @@ -240,6 +241,12 @@ friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; + HwMode hwMode; + +public: + void setHwMode(HwMode M) { + hwMode = M; + } /// \brief Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, Index: include/llvm/MC/MCSubtargetInfo.h =================================================================== --- include/llvm/MC/MCSubtargetInfo.h +++ include/llvm/MC/MCSubtargetInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_MC_MCSUBTARGETINFO_H #define LLVM_MC_MCSUBTARGETINFO_H +#include "llvm/HwMode.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -90,13 +91,29 @@ return FeatureBits[Feature]; } + HwMode hwMode; + +public: + void InitHwModes(HwModeList modes) { + for (const auto &T : modes) { + for (unsigned i = 0; i < T.second.size(); i++) { + if (checkFeatures(T.second[i])) { + hwMode.hwModesByType[T.first] = i + 1; + break; + } + } + if (hwMode.hwModesByType.find(T.first) == hwMode.hwModesByType.end()) { + hwMode.hwModesByType[T.first] = 0; + } + } + } + protected: /// Initialize the scheduling model and feature bits. /// /// FIXME: Find a way to stick this in the constructor, since it should only /// be called during initialization. void InitMCProcessorInfo(StringRef CPU, StringRef FS); - public: /// Set the features to the default for the given CPU with an appended feature /// string. @@ -188,6 +205,14 @@ virtual std::string getSchedInfoStr(MCInst const &MCI) const { return {}; } + + unsigned getHwMode(StringRef type) const { + return hwMode.get(type); + } + + HwMode getHwMode() const { + return hwMode; + } }; } // end namespace llvm Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -21,7 +21,7 @@ class RegisterClass; // Forward def -class HwMode { +class HwMode { // A string representing subtarget features that turn on this HW mode. // For example, "+feat1,-feat2" will indicate that the mode is active // when "feat1" is enabled and "feat2" is disabled at the same time. @@ -29,6 +29,7 @@ // When multiple modes are used, they should be mutually exclusive, // otherwise the results are unpredictable. string Features = FS; + string Type = T; } // A special mode recognized by tablegen. This mode is considered active Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -44,12 +44,13 @@ const LaneBitmask *SRILaneMasks, LaneBitmask SRICoveringLanes, const RegClassInfo *const RCIs, - unsigned Mode) + HwMode Mode) : InfoDesc(ID), SubRegIndexNames(SRINames), SubRegIndexLaneMasks(SRILaneMasks), RegClassBegin(RCB), RegClassEnd(RCE), CoveringLanes(SRICoveringLanes), - RCInfos(RCIs), HwMode(Mode) { + RCInfos(RCIs) { + setHwMode(Mode); } TargetRegisterInfo::~TargetRegisterInfo() = default; Index: lib/Target/Hexagon/HexagonRegisterInfo.h =================================================================== --- lib/Target/Hexagon/HexagonRegisterInfo.h +++ lib/Target/Hexagon/HexagonRegisterInfo.h @@ -29,7 +29,7 @@ class HexagonRegisterInfo : public HexagonGenRegisterInfo { public: - HexagonRegisterInfo(unsigned HwMode); + HexagonRegisterInfo(HwMode hwMode); /// Code Generation virtual methods... const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) Index: lib/Target/Hexagon/HexagonRegisterInfo.cpp =================================================================== --- lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -41,9 +41,9 @@ using namespace llvm; -HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode) +HexagonRegisterInfo::HexagonRegisterInfo(HwMode hwMode) : HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/, - 0/*PC*/, HwMode) {} + 0/*PC*/, hwMode) {} bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(unsigned R) const { Index: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -546,6 +546,8 @@ std::unique_ptr STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); + MRI->setHwMode(STI->getHwMode()); + MCInstPrinter *IP = nullptr; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant, Index: utils/TableGen/CodeGenHwModes.h =================================================================== --- utils/TableGen/CodeGenHwModes.h +++ utils/TableGen/CodeGenHwModes.h @@ -28,6 +28,7 @@ struct HwMode { HwMode(Record *R); StringRef Name; + std::string Type; std::string Features; void dump() const; }; @@ -44,19 +45,37 @@ static StringRef DefaultModeName; CodeGenHwModes(RecordKeeper &R); - unsigned getHwModeId(StringRef Name) const; - const HwMode &getMode(unsigned Id) const { + unsigned getHwModeId(StringRef Name, StringRef Type = "default") const; + const HwMode &getMode(unsigned Id, StringRef Type = "default") const { assert(Id != 0 && "Mode id of 0 is reserved for the default mode"); - return Modes[Id-1]; + auto M = Modes.find(Type); + assert(M != Modes.end() && "Type not recognized"); + return M->second[Id-1]; } const HwModeSelect &getHwModeSelect(Record *R) const; - unsigned getNumModeIds() const { return Modes.size()+1; } + unsigned getNumModeIds(StringRef Type = "default") const { + auto M = Modes.find(Type); + if (M != Modes.end()) { + return M->second.size()+1; + } + return 1; // There is always at least a default mode + } + + std::vector getTypes() const { + std::vector types; + for (auto M : Modes) { + types.push_back(M.first); + } + return types; + } + void dump() const; private: RecordKeeper &Records; - StringMap ModeIds; // HwMode (string) -> HwModeId - std::vector Modes; + // HwMode(type)(string) -> HwModeId + std::map > ModeIds; + std::map > Modes; std::map ModeSelects; }; } Index: utils/TableGen/CodeGenHwModes.cpp =================================================================== --- utils/TableGen/CodeGenHwModes.cpp +++ utils/TableGen/CodeGenHwModes.cpp @@ -21,12 +21,13 @@ HwMode::HwMode(Record *R) { Name = R->getName(); + Type = R->getValueAsString("Type"); Features = R->getValueAsString("Features"); } LLVM_DUMP_METHOD void HwMode::dump() const { - dbgs() << Name << ": " << Features << '\n'; + dbgs() << Name << "/" << Type << ": " << Features << '\n'; } HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) { @@ -39,7 +40,8 @@ report_fatal_error("error in target description."); } for (unsigned i = 0, e = Modes.size(); i != e; ++i) { - unsigned ModeId = CGH.getHwModeId(Modes[i]->getName()); + unsigned ModeId = CGH.getHwModeId(Modes[i]->getName(), + Modes[i]->getValueAsString("Type")); Items.push_back(std::make_pair(ModeId, Objects[i])); } } @@ -64,9 +66,10 @@ } for (Record *R : MRs) { - Modes.emplace_back(R); - unsigned NewId = Modes.size(); - ModeIds.insert(std::make_pair(Modes[NewId-1].Name, NewId)); + std::string Type = R->getValueAsString("Type"); + Modes[Type].emplace_back(R); + unsigned NewId = Modes[Type].size(); + ModeIds[Type].insert(std::make_pair(Modes[Type][NewId-1].Name, NewId)); } std::vector MSs = Records.getAllDerivedDefinitions("HwModeSelect"); @@ -77,11 +80,13 @@ } } -unsigned CodeGenHwModes::getHwModeId(StringRef Name) const { +unsigned CodeGenHwModes::getHwModeId(StringRef Name, StringRef Type) const { if (Name == DefaultModeName) return DefaultMode; - auto F = ModeIds.find(Name); - assert(F != ModeIds.end() && "Unknown mode name"); + auto M = ModeIds.find(Type); + assert(M != ModeIds.end() && "Type not recognized"); + auto F = M->second.find(Name); + assert(F != M->second.end() && "Unknown mode name"); return F->second; } @@ -94,15 +99,19 @@ LLVM_DUMP_METHOD void CodeGenHwModes::dump() const { dbgs() << "Modes: {\n"; - for (const HwMode &M : Modes) { - dbgs() << " "; - M.dump(); + for (const auto T : Modes) { + for (const HwMode &M : T.second) { + dbgs() << " "; + M.dump(); + } } dbgs() << "}\n"; dbgs() << "ModeIds: {\n"; - for (const auto &P : ModeIds) - dbgs() << " " << P.first() << " -> " << P.second << '\n'; + for (const auto T : ModeIds) + for (const auto &P1 : T.second) + dbgs() << " " << P1.first() << "/" << T.first + << " -> " << P1.second << '\n'; dbgs() << "}\n"; dbgs() << "ModeSelects: {\n"; Index: utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- utils/TableGen/RegisterInfoEmitter.cpp +++ utils/TableGen/RegisterInfoEmitter.cpp @@ -1111,7 +1111,7 @@ OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName << "(unsigned RA, unsigned D = 0, unsigned E = 0,\n" - << " unsigned PC = 0, unsigned HwMode = 0);\n"; + << " unsigned PC = 0, HwMode hwMode = HwMode());\n"; if (!RegBank.getSubRegIndices().empty()) { OS << " unsigned composeSubRegIndicesImpl" << "(unsigned, unsigned) const override;\n" @@ -1470,13 +1470,13 @@ OS << ClassName << "::\n" << ClassName << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n" - " unsigned PC, unsigned HwMode)\n" + " unsigned PC, HwMode hwMode)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n" << " SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n" << " "; printMask(OS, RegBank.CoveringLanes); - OS << ", RegClassInfos, HwMode) {\n" + OS << ", RegClassInfos, hwMode) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" Index: utils/TableGen/SubtargetEmitter.cpp =================================================================== --- utils/TableGen/SubtargetEmitter.cpp +++ utils/TableGen/SubtargetEmitter.cpp @@ -109,7 +109,7 @@ void EmitProcessorLookup(raw_ostream &OS); void EmitSchedModelHelpers(const std::string &ClassName, raw_ostream &OS); void EmitSchedModel(raw_ostream &OS); - void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS); + void EmitHwModesList(const CodeGenHwModes &CGH, raw_ostream &OS); void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, unsigned NumProcs); @@ -1334,20 +1334,18 @@ << "} // " << ClassName << "::resolveSchedClass\n"; } -void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName, - raw_ostream &OS) { - const CodeGenHwModes &CGH = TGT.getHwModes(); - assert(CGH.getNumModeIds() > 0); - if (CGH.getNumModeIds() == 1) - return; - - OS << "unsigned " << ClassName << "::getHwMode() const {\n"; - for (unsigned M = 1, NumModes = CGH.getNumModeIds(); M != NumModes; ++M) { - const HwMode &HM = CGH.getMode(M); - OS << " if (checkFeatures(\"" << HM.Features - << "\")) return " << M << ";\n"; +void SubtargetEmitter::EmitHwModesList(const CodeGenHwModes &CGH, raw_ostream &OS) { + OS << "\nHwModeList HwModes;"; + for (auto T : CGH.getTypes()) { + if (CGH.getNumModeIds(T) > 1) { + OS << "\nHwModes[\"" << T << "\"] = {"; + for (unsigned M = 1, NumModes = CGH.getNumModeIds(T); M != NumModes; ++M) { + const HwMode &HM = CGH.getMode(M, T); + OS << "\"" << HM.Features << "\","; + } + OS << "};"; + } } - OS << " return 0;\n}\n"; } // @@ -1432,7 +1430,7 @@ OS << "\nstatic inline MCSubtargetInfo *create" << Target << "MCSubtargetInfoImpl(" << "const Triple &TT, StringRef CPU, StringRef FS) {\n"; - OS << " return new MCSubtargetInfo(TT, CPU, FS, "; + OS << " MCSubtargetInfo *MCSI = new MCSubtargetInfo(TT, CPU, FS, "; if (NumFeatures) OS << Target << "FeatureKV, "; else @@ -1453,7 +1451,12 @@ << Target << "ForwardingPaths"; } else OS << "nullptr, nullptr, nullptr"; - OS << ");\n}\n\n"; + OS << ");\n\n"; + const CodeGenHwModes &CGH = TGT.getHwModes(); + EmitHwModesList(CGH, OS); + OS << " MCSI->InitHwModes(HwModes);\n\n"; + OS << " return MCSI;\n"; + OS << "}\n\n"; OS << "} // end namespace llvm\n\n"; @@ -1484,8 +1487,6 @@ << " const TargetSchedModel *SchedModel) const override;\n" << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" << " const;\n"; - if (TGT.getHwModes().getNumModeIds() > 1) - OS << " unsigned getHwMode() const override;\n"; OS << "};\n" << "} // end namespace llvm\n\n"; @@ -1535,10 +1536,12 @@ << Target << "ForwardingPaths"; } else OS << "nullptr, nullptr, nullptr"; - OS << ") {}\n\n"; + OS << ") {"; + EmitHwModesList(CGH, OS); + OS << " InitHwModes(HwModes);\n"; + OS << "}\n\n"; EmitSchedModelHelpers(ClassName, OS); - EmitHwModeCheck(ClassName, OS); OS << "} // end namespace llvm\n\n";