Index: llvm/include/llvm/CodeGen/TargetSubtargetInfo.h =================================================================== --- llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -58,8 +58,8 @@ /// class TargetSubtargetInfo : public MCSubtargetInfo { protected: // Can only create subclasses... - TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, - ArrayRef PF, + TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, ArrayRef PF, ArrayRef PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, Index: llvm/include/llvm/MC/MCSubtargetInfo.h =================================================================== --- llvm/include/llvm/MC/MCSubtargetInfo.h +++ llvm/include/llvm/MC/MCSubtargetInfo.h @@ -54,6 +54,7 @@ struct SubtargetSubTypeKV { const char *Key; ///< K-V key string FeatureBitArray Implies; ///< K-V bit mask + FeatureBitArray TuneImplies; ///< K-V bit mask const MCSchedModel *SchedModel; /// Compare routine for std::lower_bound @@ -74,6 +75,7 @@ class MCSubtargetInfo { Triple TargetTriple; std::string CPU; // CPU being targeted. + std::string TuneCPU; // CPU being tuned for. ArrayRef ProcFeatures; // Processor feature list ArrayRef ProcDesc; // Processor descriptions @@ -90,8 +92,8 @@ public: MCSubtargetInfo(const MCSubtargetInfo &) = default; - MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, - ArrayRef PF, + MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, ArrayRef PF, ArrayRef PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, @@ -103,6 +105,7 @@ const Triple &getTargetTriple() const { return TargetTriple; } StringRef getCPU() const { return CPU; } + StringRef getTuneCPU() const { return TuneCPU; } const FeatureBitset& getFeatureBits() const { return FeatureBits; } void setFeatureBits(const FeatureBitset &FeatureBits_) { @@ -118,12 +121,12 @@ /// /// FIXME: Find a way to stick this in the constructor, since it should only /// be called during initialization. - void InitMCProcessorInfo(StringRef CPU, StringRef FS); + void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS); public: - /// Set the features to the default for the given CPU with an appended feature - /// string. - void setDefaultFeatures(StringRef CPU, StringRef FS); + /// Set the features to the default for the given CPU and TuneCPU, with ano + /// appended feature string. + void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); /// Toggle a feature and return the re-computed feature bits. /// This version does not change the implied bits. Index: llvm/include/llvm/Target/Target.td =================================================================== --- llvm/include/llvm/Target/Target.td +++ llvm/include/llvm/Target/Target.td @@ -1511,6 +1511,9 @@ // setting hasExtraDefRegAllocReq and hasExtraSrcRegAllocReq to 1 // for all opcodes if this flag is set to 0. int AllowRegisterRenaming = 0; + + // HasTuneCPU - Controls whether this target supports a tune CPU. + int HasTuneCPU = 0; } //===----------------------------------------------------------------------===// @@ -1558,7 +1561,8 @@ // by the scheduler. Each Processor definition requires corresponding // instruction itineraries. // -class Processor f> { +class Processor f, + list tunef = []> { // Name - Chip set name. Used by command line (-mcpu=) to determine the // appropriate target chip. // @@ -1574,6 +1578,9 @@ // Features - list of list Features = f; + + // TuneFeatures - list of features for tuning for this CPU. + list TuneFeatures = tunef; } // ProcessorModel allows subtargets to specify the more general @@ -1582,8 +1589,9 @@ // // Although this class always passes NoItineraries to the Processor // class, the SchedMachineModel may still define valid Itineraries. -class ProcessorModel f> - : Processor { +class ProcessorModel f, + list tunef = []> + : Processor { let SchedModel = m; } Index: llvm/lib/CodeGen/TargetSubtargetInfo.cpp =================================================================== --- llvm/lib/CodeGen/TargetSubtargetInfo.cpp +++ llvm/lib/CodeGen/TargetSubtargetInfo.cpp @@ -15,13 +15,12 @@ using namespace llvm; TargetSubtargetInfo::TargetSubtargetInfo( - const Triple &TT, StringRef CPU, StringRef FS, + const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, ArrayRef PF, ArrayRef PD, - const MCWriteProcResEntry *WPR, - const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, - const InstrStage *IS, const unsigned *OC, const unsigned *FP) - : MCSubtargetInfo(TT, CPU, FS, PF, PD, WPR, WL, RA, IS, OC, FP) { -} + const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, + const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC, + const unsigned *FP) + : MCSubtargetInfo(TT, CPU, TuneCPU, FS, PF, PD, WPR, WL, RA, IS, OC, FP) {} TargetSubtargetInfo::~TargetSubtargetInfo() = default; Index: llvm/lib/MC/MCSubtargetInfo.cpp =================================================================== --- llvm/lib/MC/MCSubtargetInfo.cpp +++ llvm/lib/MC/MCSubtargetInfo.cpp @@ -147,7 +147,7 @@ PrintOnce = true; } -static FeatureBitset getFeatures(StringRef CPU, StringRef FS, +static FeatureBitset getFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS, ArrayRef ProcDesc, ArrayRef ProcFeatures) { SubtargetFeatures Features(FS); @@ -178,6 +178,19 @@ } } + if (!TuneCPU.empty()) { + const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc); + + // If there is a match + if (CPUEntry) { + // Set the features implied by this CPU feature, if any. + SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures); + } else if (TuneCPU != CPU) { + errs() << "'" << TuneCPU << "' is not a recognized processor for this " + << "target (ignoring processor)\n"; + } + } + // Iterate through each feature for (const std::string &Feature : Features.getFeatures()) { // Check for help @@ -192,30 +205,33 @@ return Bits; } -void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) { - FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures); - if (!CPU.empty()) - CPUSchedModel = &getSchedModelForCPU(CPU); +void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, + StringRef FS) { + FeatureBits = getFeatures(CPU, TuneCPU, FS, ProcDesc, ProcFeatures); + if (!TuneCPU.empty()) + CPUSchedModel = &getSchedModelForCPU(TuneCPU); else CPUSchedModel = &MCSchedModel::GetDefaultSchedModel(); } -void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) { - FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures); +void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef TuneCPU, + StringRef FS) { + FeatureBits = getFeatures(CPU, TuneCPU, FS, ProcDesc, ProcFeatures); } -MCSubtargetInfo::MCSubtargetInfo(const Triple &TT, StringRef C, StringRef FS, - ArrayRef PF, +MCSubtargetInfo::MCSubtargetInfo(const Triple &TT, StringRef C, StringRef TC, + StringRef FS, ArrayRef PF, ArrayRef PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC, const unsigned *FP) - : TargetTriple(TT), CPU(std::string(C)), ProcFeatures(PF), ProcDesc(PD), - WriteProcResTable(WPR), WriteLatencyTable(WL), ReadAdvanceTable(RA), - Stages(IS), OperandCycles(OC), ForwardingPaths(FP) { - InitMCProcessorInfo(CPU, FS); + : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)), + ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR), + WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS), + OperandCycles(OC), ForwardingPaths(FP) { + InitMCProcessorInfo(CPU, TuneCPU, FS); } FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) { Index: llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -5159,7 +5159,8 @@ MCSubtargetInfo &STI = copySTI(); std::vector ArchFeatures(AArch64Features.begin(), AArch64Features.end()); - STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ",")); + STI.setDefaultFeatures("generic", /*TuneCPU*/ "generic", + join(ArchFeatures.begin(), ArchFeatures.end(), ",")); SmallVector RequestedExtensions; if (!ExtensionString.empty()) @@ -5261,7 +5262,7 @@ } MCSubtargetInfo &STI = copySTI(); - STI.setDefaultFeatures(CPU, ""); + STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); CurLoc = incrementLoc(CurLoc, CPU.size()); ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions); Index: llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -11134,7 +11134,8 @@ bool WasThumb = isThumb(); Triple T; MCSubtargetInfo &STI = copySTI(); - STI.setDefaultFeatures("", ("+" + ARM::getArchName(ID)).str()); + STI.setDefaultFeatures("", /*TuneCPU*/ "", + ("+" + ARM::getArchName(ID)).str()); setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); FixModeAfterArchChange(WasThumb, L); @@ -11247,7 +11248,7 @@ bool WasThumb = isThumb(); MCSubtargetInfo &STI = copySTI(); - STI.setDefaultFeatures(CPU, ""); + STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); FixModeAfterArchChange(WasThumb, L); Index: llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -295,7 +295,7 @@ if (CPU.empty()) CPU = "generic"; - return createX86MCSubtargetInfoImpl(TT, CPU, ArchFS); + return createX86MCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, ArchFS); } static MCInstrInfo *createX86MCInstrInfo() { Index: llvm/lib/Target/X86/X86.td =================================================================== --- llvm/lib/Target/X86/X86.td +++ llvm/lib/Target/X86/X86.td @@ -1018,12 +1018,12 @@ class Proc Features, list TuneFeatures> - : ProcessorModel; + : ProcessorModel; class ProcModel Features, list TuneFeatures> - : ProcessorModel; + : ProcessorModel; // NOTE: CMPXCHG8B is here for legacy compatibility so that it is only disabled // if i386/i486 is specifically requested. @@ -1396,6 +1396,7 @@ let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant]; let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter]; let AllowRegisterRenaming = 1; + let HasTuneCPU = 1; } //===----------------------------------------------------------------------===// Index: llvm/lib/Target/X86/X86Subtarget.h =================================================================== --- llvm/lib/Target/X86/X86Subtarget.h +++ llvm/lib/Target/X86/X86Subtarget.h @@ -514,7 +514,7 @@ /// This constructor initializes the data members to match that /// of the specified triple. /// - X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS, + X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, const X86TargetMachine &TM, MaybeAlign StackAlignOverride, unsigned PreferVectorWidthOverride, unsigned RequiredVectorWidth); @@ -548,7 +548,7 @@ /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); /// Methods used by Global ISel const CallLowering *getCallLowering() const override; @@ -559,8 +559,10 @@ private: /// Initialize the full set of dependencies so we can use an initializer /// list for X86Subtarget. - X86Subtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); - void initSubtargetFeatures(StringRef CPU, StringRef FS); + X86Subtarget &initializeSubtargetDependencies(StringRef CPU, + StringRef TuneCPU, + StringRef FS); + void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); public: /// Is this x86_64? (disregarding specific ABI / programming model) Index: llvm/lib/Target/X86/X86Subtarget.cpp =================================================================== --- llvm/lib/Target/X86/X86Subtarget.cpp +++ llvm/lib/Target/X86/X86Subtarget.cpp @@ -227,10 +227,14 @@ return isTargetELF() || TM.getRelocationModel() == Reloc::Static; } -void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { +void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, + StringRef FS) { if (CPU.empty()) CPU = "generic"; + if (TuneCPU.empty()) + TuneCPU = "generic"; + std::string FullFS = X86_MC::ParseX86Triple(TargetTriple); assert(!FullFS.empty() && "Failed to parse X86 triple"); @@ -238,7 +242,7 @@ FullFS = (Twine(FullFS) + "," + FS).str(); // Parse features string and set the CPU. - ParseSubtargetFeatures(CPU, FullFS); + ParseSubtargetFeatures(CPU, TuneCPU, FullFS); // All CPUs that implement SSE4.2 or SSE4A support unaligned accesses of // 16-bytes and under that are reasonably fast. These features were @@ -272,22 +276,24 @@ } X86Subtarget &X86Subtarget::initializeSubtargetDependencies(StringRef CPU, + StringRef TuneCPU, StringRef FS) { - initSubtargetFeatures(CPU, FS); + initSubtargetFeatures(CPU, TuneCPU, FS); return *this; } -X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS, - const X86TargetMachine &TM, +X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, const X86TargetMachine &TM, MaybeAlign StackAlignOverride, unsigned PreferVectorWidthOverride, unsigned RequiredVectorWidth) - : X86GenSubtargetInfo(TT, CPU, FS), PICStyle(PICStyles::Style::None), - TM(TM), TargetTriple(TT), StackAlignOverride(StackAlignOverride), + : X86GenSubtargetInfo(TT, CPU, TuneCPU, FS), + PICStyle(PICStyles::Style::None), TM(TM), TargetTriple(TT), + StackAlignOverride(StackAlignOverride), PreferVectorWidthOverride(PreferVectorWidthOverride), RequiredVectorWidth(RequiredVectorWidth), - InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), - FrameLowering(*this, getStackAlignment()) { + InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)), + TLInfo(TM, *this), FrameLowering(*this, getStackAlignment()) { // Determine the PICStyle based on the target selected. if (!isPositionIndependent()) setPICStyle(PICStyles::Style::None); Index: llvm/lib/Target/X86/X86TargetMachine.cpp =================================================================== --- llvm/lib/Target/X86/X86TargetMachine.cpp +++ llvm/lib/Target/X86/X86TargetMachine.cpp @@ -233,11 +233,15 @@ const X86Subtarget * X86TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute TuneAttr = F.getFnAttribute("tune-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); StringRef CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString() : (StringRef)TargetCPU; + StringRef TuneCPU = !TuneAttr.hasAttribute(Attribute::None) + ? TuneAttr.getValueAsString() + : (StringRef)CPU; StringRef FS = !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : (StringRef)TargetFS; @@ -276,6 +280,10 @@ // Add CPU to the Key. Key += CPU; + // Add tune CPU to the Key. + Key += "tune="; + Key += TuneCPU; + // Keep track of the start of the feature portion of the string. unsigned FSStart = Key.size(); @@ -304,7 +312,7 @@ // function that reside in TargetOptions. resetTargetOptions(F); I = std::make_unique( - TargetTriple, CPU, FS, *this, + TargetTriple, CPU, TuneCPU, FS, *this, MaybeAlign(Options.StackAlignmentOverride), PreferVectorWidthOverride, RequiredVectorWidth); } Index: llvm/test/CodeGen/X86/tune-cpu.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/tune-cpu.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +; This test should use VPMULLQ which is an avx512dq feature +; which it gets from target-cpu=skx. It should not generate +; a vzeroupper since the tune-cpu is knl. +define void @vzeroupper(<4 x i64>* %x, <4 x i64>* %y) #0 { +; CHECK-LABEL: vzeroupper: +; CHECK: # %bb.0: +; CHECK-NEXT: vmovdqa (%rdi), %ymm0 +; CHECK-NEXT: vpmullq (%rsi), %ymm0, %ymm0 +; CHECK-NEXT: vmovdqa %ymm0, (%rdi) +; CHECK-NEXT: retq + %a = load <4 x i64>, <4 x i64>* %x + %b = load <4 x i64>, <4 x i64>* %y + %c = mul <4 x i64> %a, %b + store <4 x i64> %c, <4 x i64>* %x + ret void +} + +define void @prefer256(<8 x i64>* %x, <8 x i64>* %y) #1 { +; CHECK-LABEL: prefer256: +; CHECK: # %bb.0: +; CHECK-NEXT: vmovdqa (%rdi), %ymm0 +; CHECK-NEXT: vmovdqa 32(%rdi), %ymm1 +; CHECK-NEXT: vpaddq 32(%rsi), %ymm1, %ymm1 +; CHECK-NEXT: vpaddq (%rsi), %ymm0, %ymm0 +; CHECK-NEXT: vmovdqa %ymm0, (%rdi) +; CHECK-NEXT: vmovdqa %ymm1, 32(%rdi) +; CHECK-NEXT: vzeroupper +; CHECK-NEXT: retq + %a = load <8 x i64>, <8 x i64>* %x + %b = load <8 x i64>, <8 x i64>* %y + %c = add <8 x i64> %a, %b + store <8 x i64> %c, <8 x i64>* %x + ret void +} + +; target-cpu doesn't have slow divide 64 set, but tune-cpu does. Make sure we +; codegen as if its slow. +define i64 @slowdivide64(i64 %x, i64 %y) #2 { +; CHECK-LABEL: slowdivide64: +; CHECK: # %bb.0: +; CHECK-NEXT: movq %rdi, %rax +; CHECK-NEXT: movq %rdi, %rcx +; CHECK-NEXT: orq %rsi, %rcx +; CHECK-NEXT: shrq $32, %rcx +; CHECK-NEXT: je .LBB2_1 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: xorl %edx, %edx +; CHECK-NEXT: divq %rsi +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB2_1: +; CHECK-NEXT: # kill: def $eax killed $eax killed $rax +; CHECK-NEXT: xorl %edx, %edx +; CHECK-NEXT: divl %esi +; CHECK-NEXT: # kill: def $eax killed $eax def $rax +; CHECK-NEXT: retq + %a = udiv i64 %x, %y + ret i64 %a +} + +attributes #0 = { "target-cpu"="skx" "tune-cpu"="knl"} +attributes #1 = { "min-legal-vector-width"="256" "target-cpu"="haswell" "tune-cpu"="skx" "target-features"="+avx512vl" } +attributes #2 = { "target-cpu"="nocona" "tune-cpu"="sandybridge" } Index: llvm/unittests/CodeGen/MFCommon.inc =================================================================== --- llvm/unittests/CodeGen/MFCommon.inc +++ llvm/unittests/CodeGen/MFCommon.inc @@ -72,7 +72,7 @@ class BogusSubtarget : public TargetSubtargetInfo { public: BogusSubtarget(TargetMachine &TM) - : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr, + : TargetSubtargetInfo(Triple(""), "", "", "", {}, {}, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr), FL(), TL(TM) {} ~BogusSubtarget() override {} Index: llvm/utils/TableGen/CodeGenTarget.h =================================================================== --- llvm/utils/TableGen/CodeGenTarget.h +++ llvm/utils/TableGen/CodeGenTarget.h @@ -82,6 +82,9 @@ /// bool getAllowRegisterRenaming() const; + /// getHasTuneCPU - Return the HasTuneCPU flag value for this target. + bool getHasTuneCPU() const; + /// getAsmParser - Return the AssemblyParser definition for this target. /// Record *getAsmParser() const; Index: llvm/utils/TableGen/CodeGenTarget.cpp =================================================================== --- llvm/utils/TableGen/CodeGenTarget.cpp +++ llvm/utils/TableGen/CodeGenTarget.cpp @@ -274,6 +274,10 @@ return TargetRec->getValueAsInt("AllowRegisterRenaming"); } +bool CodeGenTarget::getHasTuneCPU() const { + return TargetRec->getValueAsInt("HasTuneCPU"); +} + /// getAsmParser - Return the AssemblyParser definition for this target. /// Record *CodeGenTarget::getAsmParser() const { Index: llvm/utils/TableGen/SubtargetEmitter.cpp =================================================================== --- llvm/utils/TableGen/SubtargetEmitter.cpp +++ llvm/utils/TableGen/SubtargetEmitter.cpp @@ -267,12 +267,15 @@ for (Record *Processor : ProcessorList) { StringRef Name = Processor->getValueAsString("Name"); RecVec FeatureList = Processor->getValueAsListOfDefs("Features"); + RecVec TuneFeatureList = Processor->getValueAsListOfDefs("TuneFeatures"); // Emit as { "cpu", "description", 0, { f1 , f2 , ... fn } }, OS << " { " << "\"" << Name << "\", "; printFeatureMask(OS, FeatureList, FeatureMap); + OS << ", "; + printFeatureMask(OS, TuneFeatureList, FeatureMap); // Emit the scheduler model pointer. const std::string &ProcModelName = @@ -1692,7 +1695,10 @@ << "// subtarget options.\n" << "void llvm::"; OS << Target; - OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" + OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, "; + if (TGT.getHasTuneCPU()) + OS << "StringRef TuneCPU, "; + OS << "StringRef FS) {\n" << " LLVM_DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" << " LLVM_DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n"; @@ -1701,7 +1707,12 @@ return; } - OS << " InitMCProcessorInfo(CPU, FS);\n" + OS << " InitMCProcessorInfo(CPU, "; + if (TGT.getHasTuneCPU()) + OS << "TuneCPU"; + else + OS << "/*TuneCPU*/CPU"; + OS << ", FS);\n" << " const FeatureBitset& Bits = getFeatureBits();\n"; for (Record *R : Features) { @@ -1734,14 +1745,23 @@ OS << "struct " << Target << "GenMCSubtargetInfo : public MCSubtargetInfo {\n"; - OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT, \n" - << " StringRef CPU, StringRef FS, ArrayRef PF,\n" + OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT,\n" + << " StringRef CPU, "; + if (TGT.getHasTuneCPU()) + OS << "StringRef TuneCPU, "; + OS << "StringRef FS,\n" + << " ArrayRef PF,\n" << " ArrayRef PD,\n" << " const MCWriteProcResEntry *WPR,\n" << " const MCWriteLatencyEntry *WL,\n" << " const MCReadAdvanceEntry *RA, const InstrStage *IS,\n" << " const unsigned *OC, const unsigned *FP) :\n" - << " MCSubtargetInfo(TT, CPU, FS, PF, PD,\n" + << " MCSubtargetInfo(TT, CPU, "; + if (TGT.getHasTuneCPU()) + OS << "TuneCPU"; + else + OS << "CPU\n"; + OS << ", FS, PF, PD,\n" << " WPR, WL, RA, IS, OC, FP) { }\n\n" << " unsigned resolveVariantSchedClass(unsigned SchedClass,\n" << " const MCInst *MI, unsigned CPUID) const override {\n" @@ -1815,10 +1835,18 @@ // MCInstrInfo initialization routine. emitGenMCSubtargetInfo(OS); + bool HasTuneCPU = TGT.getHasTuneCPU(); + OS << "\nstatic inline MCSubtargetInfo *create" << Target << "MCSubtargetInfoImpl(" - << "const Triple &TT, StringRef CPU, StringRef FS) {\n"; - OS << " return new " << Target << "GenMCSubtargetInfo(TT, CPU, FS, "; + << "const Triple &TT, StringRef CPU, "; + if (HasTuneCPU) + OS << "StringRef TuneCPU, "; + OS << "StringRef FS) {\n"; + OS << " return new " << Target << "GenMCSubtargetInfo(TT, CPU, "; + if (HasTuneCPU) + OS << "TuneCPU, "; + OS << "FS, "; if (NumFeatures) OS << Target << "FeatureKV, "; else @@ -1865,8 +1893,10 @@ << " const MCInst *MI, unsigned CPUID);\n" << "} // end namespace " << Target << "_MC\n\n"; OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" - << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, " - << "StringRef FS);\n" + << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, "; + if (HasTuneCPU) + OS << "StringRef TuneCPU, "; + OS << "StringRef FS);\n" << "public:\n" << " unsigned resolveSchedClass(unsigned SchedClass, " << " const MachineInstr *DefMI," @@ -1908,9 +1938,16 @@ OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; } - OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, " - << "StringRef FS)\n" - << " : TargetSubtargetInfo(TT, CPU, FS, "; + OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, "; + if (HasTuneCPU) + OS << "StringRef TuneCPU, "; + OS << "StringRef FS)\n" + << " : TargetSubtargetInfo(TT, CPU, "; + if (HasTuneCPU) + OS << "TuneCPU, "; + else + OS << "/*TuneCPU*/CPU, "; + OS << "FS, "; if (NumFeatures) OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), "; else