Index: include/llvm/MC/MCSubtargetInfo.h =================================================================== --- include/llvm/MC/MCSubtargetInfo.h +++ include/llvm/MC/MCSubtargetInfo.h @@ -110,6 +110,10 @@ /// all feature bits implied by the flag. FeatureBitset ApplyFeatureFlag(StringRef FS); + /// Check whether the subtarget features are enabled/disabled as per + /// the provided string, ignoring all other features. + bool checkFeatures(StringRef FS) const; + /// getSchedModelForCPU - Get the machine model of a CPU. /// const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; Index: include/llvm/MC/SubtargetFeature.h =================================================================== --- include/llvm/MC/SubtargetFeature.h +++ include/llvm/MC/SubtargetFeature.h @@ -115,6 +115,9 @@ ArrayRef CPUTable, ArrayRef FeatureTable); + /// Returns the vector of individual subtarget features. + const std::vector &getFeatures() const { return Features; } + /// Prints feature string. void print(raw_ostream &OS) const; Index: include/llvm/Target/TargetSubtargetInfo.h =================================================================== --- include/llvm/Target/TargetSubtargetInfo.h +++ include/llvm/Target/TargetSubtargetInfo.h @@ -101,6 +101,8 @@ 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: lib/MC/MCSubtargetInfo.cpp =================================================================== --- lib/MC/MCSubtargetInfo.cpp +++ lib/MC/MCSubtargetInfo.cpp @@ -75,6 +75,18 @@ return FeatureBits; } +bool MCSubtargetInfo::checkFeatures(StringRef FS) const { + SubtargetFeatures T(FS); + FeatureBitset Set, All; + for (std::string F : T.getFeatures()) { + SubtargetFeatures::ApplyFeatureFlag(Set, F, ProcFeatures); + if (F[0] == '-') + F[0] = '+'; + SubtargetFeatures::ApplyFeatureFlag(All, F, ProcFeatures); + } + return (FeatureBits & All) == Set; +} + const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { assert(ProcSchedModels && "Processor machine model not available!"); Index: utils/TableGen/SubtargetEmitter.cpp =================================================================== --- utils/TableGen/SubtargetEmitter.cpp +++ utils/TableGen/SubtargetEmitter.cpp @@ -68,6 +68,7 @@ } }; + const CodeGenTarget &TGT; RecordKeeper &Records; CodeGenSchedModels &SchedModels; std::string Target; @@ -106,12 +107,14 @@ 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 ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, unsigned NumProcs); public: - SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT): - Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {} + SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT) + : TGT(TGT), Records(R), SchedModels(TGT.getSchedModels()), + Target(TGT.getName()) {} void run(raw_ostream &o); }; @@ -1331,6 +1334,22 @@ << "} // " << 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"; + } + OS << " return 0;\n}\n"; +} + // // ParseFeaturesFunction - Produces a subtarget specific function for parsing // the subtarget features string. @@ -1464,9 +1483,11 @@ << " const MachineInstr *DefMI," << " const TargetSchedModel *SchedModel) const override;\n" << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" - << " const;\n" - << "};\n"; - OS << "} // end namespace llvm\n\n"; + << " const;\n"; + if (TGT.getHwModes().getNumModeIds() > 1) + OS << " unsigned getHwMode() const override;\n"; + OS << "};\n" + << "} // end namespace llvm\n\n"; OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; @@ -1517,6 +1538,7 @@ OS << ") {}\n\n"; EmitSchedModelHelpers(ClassName, OS); + EmitHwModeCheck(ClassName, OS); OS << "} // end namespace llvm\n\n";