diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h index f6a83dfbdbf..e809fc0a2cc 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/Target/SubtargetFeature.h @@ -34,6 +34,7 @@ struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor uint32_t Value; // K-V integer value + uint32_t Implies; // K-V bit mask // Compare routine for std binary search bool operator<(const SubtargetFeatureKV &S) const { diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp index 4669e0fdc3c..598f02982b0 100644 --- a/lib/Target/SubtargetFeature.cpp +++ b/lib/Target/SubtargetFeature.cpp @@ -199,6 +199,43 @@ void SubtargetFeatures::setCPUIfNone(const std::string &String) { if (Features[0].empty()) setCPU(String); } +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} /// getBits - Get feature bits. /// @@ -251,8 +288,17 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, // If there is a match if (FeatureEntry) { // Enable/disable feature in bits - if (isEnabled(Feature)) Bits |= FeatureEntry->Value; - else Bits &= ~FeatureEntry->Value; + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } } else { cerr << "'" << Feature << "' is not a recognized feature for this target" @@ -260,6 +306,7 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, << "\n"; } } + return Bits; } diff --git a/lib/Target/Target.td b/lib/Target/Target.td index 938e4cdc8fb..f98c414d34c 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -338,7 +338,8 @@ class Target { //===----------------------------------------------------------------------===// // SubtargetFeature - A characteristic of the chip set. // -class SubtargetFeature { +class SubtargetFeature i = []> { // Name - Feature name. Used by command line (-mattr=) to determine the // appropriate target chip. // @@ -356,6 +357,11 @@ class SubtargetFeature { // information. // string Desc = d; + + // Implies - Features that this feature implies are present. If one of those + // features isn't set, then this one shouldn't be set either. + // + list Implies = i; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 94e69f5a36f..89cb749d646 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -18,24 +18,28 @@ include "../Target.td" //===----------------------------------------------------------------------===// // X86 Subtarget features. -// +//===----------------------------------------------------------------------===// -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions">; -def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", - "Enable MMX instructions">; -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions">; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions">; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions">; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions">; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions">; +def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", + "Support 64-bit instructions">; +def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", + "Enable MMX instructions">; +def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", + "Enable SSE instructions", + [FeatureMMX]>; +def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", + "Enable SSE2 instructions", + [FeatureSSE1]>; +def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", + "Enable SSE3 instructions", + [FeatureSSE2]>; +def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", + "Enable SSSE3 instructions", + [FeatureSSE3]>; +def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", + "Enable 3DNow! instructions">; +def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", + "Enable 3DNow! Athlon instructions">; //===----------------------------------------------------------------------===// // X86 processors supported. diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index f6c7a44f347..fc913e69e12 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -56,8 +56,7 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, Record *Def = DefList[i]; // Get and emit name - std::string Name = Def->getName(); - OS << " " << Name; + OS << " " << Def->getName(); // If bit flags then emit expression (1 << i) if (isBits) OS << " = " << " 1 << " << i; @@ -73,8 +72,8 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, } // -// FeatureKeyValues - Emit data of all the subtarget features. Used by command -// line. +// FeatureKeyValues - Emit data of all the subtarget features. Used by the +// command line. // void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { // Gather and sort all the features @@ -91,18 +90,31 @@ void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { // Next feature Record *Feature = FeatureList[i]; - std::string Name = Feature->getName(); - std::string CommandLineName = Feature->getValueAsString("Name"); - std::string Desc = Feature->getValueAsString("Desc"); + const std::string &Name = Feature->getName(); + const std::string &CommandLineName = Feature->getValueAsString("Name"); + const std::string &Desc = Feature->getValueAsString("Desc"); if (CommandLineName.empty()) continue; - // Emit as { "feature", "decription", feactureEnum } + // Emit as { "feature", "decription", feactureEnum, i1 | i2 | ... | in } OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " - << Name - << " }"; + << Name << ", "; + + const std::vector &ImpliesList = + Feature->getValueAsListOfDefs("Implies"); + + if (ImpliesList.empty()) { + OS << "0"; + } else { + for (unsigned j = 0, M = ImpliesList.size(); j < M;) { + OS << ImpliesList[j]->getName(); + if (++j < M) OS << " | "; + } + } + + OS << " }"; // Depending on 'if more in the list' emit comma if ((i + 1) < N) OS << ","; @@ -138,8 +150,8 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { // Next processor Record *Processor = ProcessorList[i]; - std::string Name = Processor->getValueAsString("Name"); - std::vector FeatureList = + const std::string &Name = Processor->getValueAsString("Name"); + const std::vector &FeatureList = Processor->getValueAsListOfDefs("Features"); // Emit as { "cpu", "description", f1 | f2 | ... fn }, @@ -151,14 +163,13 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { OS << "0"; } else { for (unsigned j = 0, M = FeatureList.size(); j < M;) { - Record *Feature = FeatureList[j]; - std::string Name = Feature->getName(); - OS << Name; + OS << FeatureList[j]->getName(); if (++j < M) OS << " | "; } } - OS << " }"; + // The "0" is for the "implies" section of this data structure. + OS << ", 0 }"; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; @@ -190,11 +201,10 @@ unsigned SubtargetEmitter::CollectAllItinClasses(std::ostream &OS, unsigned N = ItinClassList.size(); for (unsigned i = 0; i < N; i++) { // Next itinerary class - Record *ItinClass = ItinClassList[i]; + const Record *ItinClass = ItinClassList[i]; // Get name of itinerary class - std::string Name = ItinClass->getName(); // Assign itinerary class a unique number - ItinClassesMap[Name] = i; + ItinClassesMap[ItinClass->getName()] = i; } // Emit size of table @@ -214,28 +224,26 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData, std::string &ItinString, unsigned &NStages) { // Get states list - std::vector StageList = ItinData->getValueAsListOfDefs("Stages"); + const std::vector &StageList = + ItinData->getValueAsListOfDefs("Stages"); // For each stage unsigned N = NStages = StageList.size(); for (unsigned i = 0; i < N;) { // Next stage - Record *Stage = StageList[i]; + const Record *Stage = StageList[i]; // Form string as ,{ cycles, u1 | u2 | ... | un } int Cycles = Stage->getValueAsInt("Cycles"); ItinString += " { " + itostr(Cycles) + ", "; // Get unit list - std::vector UnitList = Stage->getValueAsListOfDefs("Units"); + const std::vector &UnitList = Stage->getValueAsListOfDefs("Units"); // For each unit for (unsigned j = 0, M = UnitList.size(); j < M;) { - // Next unit - Record *Unit = UnitList[j]; - // Add name and bitwise or - ItinString += Unit->getName(); + ItinString += UnitList[j]->getName(); if (++j < M) ItinString += " | "; } @@ -271,7 +279,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS, Record *Proc = ProcItinList[i]; // Get processor itinerary name - std::string Name = Proc->getName(); + const std::string &Name = Proc->getName(); // Skip default if (Name == "NoItineraries") continue; @@ -308,7 +316,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS, InstrItinerary Intinerary = { Find, Find + NStages }; // Locate where to inject into processor itinerary table - std::string Name = ItinData->getValueAsDef("TheClass")->getName(); + const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); Find = ItinClassesMap[Name]; // Inject - empty slots will be 0, 0 @@ -347,7 +355,7 @@ void SubtargetEmitter::EmitProcessorData(std::ostream &OS, Record *Itin = Itins[i]; // Get processor itinerary name - std::string Name = Itin->getName(); + const std::string &Name = Itin->getName(); // Skip default if (Name == "NoItineraries") continue; @@ -398,8 +406,9 @@ void SubtargetEmitter::EmitProcessorLookup(std::ostream &OS) { // Next processor Record *Processor = ProcessorList[i]; - std::string Name = Processor->getValueAsString("Name"); - std::string ProcItin = Processor->getValueAsDef("ProcItin")->getName(); + const std::string &Name = Processor->getValueAsString("Name"); + const std::string &ProcItin = + Processor->getValueAsDef("ProcItin")->getName(); // Emit as { "cpu", procinit }, OS << " { " @@ -456,33 +465,32 @@ void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) { std::sort(Features.begin(), Features.end(), LessRecord()); OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" - "// subtarget options.\n" - "void llvm::"; + << "// subtarget options.\n" + << "void llvm::"; OS << Target; OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" - " const std::string &CPU) {\n" - " SubtargetFeatures Features(FS);\n" - " Features.setCPUIfNone(CPU);\n" - " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" - " FeatureKV, FeatureKVSize);\n"; - + << " const std::string &CPU) {\n" + << " SubtargetFeatures Features(FS);\n" + << " Features.setCPUIfNone(CPU);\n" + << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + << " FeatureKV, FeatureKVSize);\n"; + for (unsigned i = 0; i < Features.size(); i++) { // Next record Record *R = Features[i]; - std::string Instance = R->getName(); - std::string Name = R->getValueAsString("Name"); - std::string Value = R->getValueAsString("Value"); - std::string Attribute = R->getValueAsString("Attribute"); + const std::string &Instance = R->getName(); + const std::string &Value = R->getValueAsString("Value"); + const std::string &Attribute = R->getValueAsString("Attribute"); OS << " if ((Bits & " << Instance << ") != 0) " << Attribute << " = " << Value << ";\n"; } - + if (HasItineraries) { OS << "\n" << " InstrItinerary *Itinerary = (InstrItinerary *)" - "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" - " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; + << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" + << " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; } OS << "}\n";